sheol Posted November 24, 2013 Posted November 24, 2013 I went ahead and experimented with these.  Using all of shinji72's female pain and adding the following: female PAIN Phase 5: Expression 9 100 Modifier 0 100 Modifier 1 100 Modifier 2 100 Modifier 3 100 Modifier 4 100 Modifier 5 100 Modifier 6 50 Modifier 7 50 Modifier 11 100 Modifier 12 30 Modifier 13 40 phoneme 0 30 phoneme 2 100 phoneme 5 40 phoneme 13 20 Phoneme 15 40 This seemed to work pretty well actually, especially for my purposes. I then wanted to see how using my system above the expression would change through the phases.  The hoped outcome would be that it would change from pain to pleasure with rising intensity, and that the pain and pleasure aspects would never be lost.  Plugging in each of these numbers for the phases provided the exact sort of result I was looking for.  However, I didn't like the way it scaled.  The extremes of values didn't produce the bias I was looking for.  So I changes the equation:Enjoyment = 5 + ((9-Purity)*Stage) + (Proficiency*Stage) This produces a number between 10 and 90 which gives a stronger pull on either side than my original formulation.
Shinobi7 Posted November 26, 2013 Posted November 26, 2013 I suggest for the last phases of pain clenched teeth and closed eyes with frowning eyebrows. These last pics seemed more like sadness than pain.
Ashal Posted November 29, 2013 Author Posted November 29, 2013 At the risk of complicating things I had a thought.  What if the expression was tied to the level of enjoyment being received. For the sake of argument we'll define enjoyment as:  purity_enjoyment = 50 - (6-stage)*Purity  Proficiency_enjoyment =  (stage)*Proficiency  Divided by 2 if they're sexual orientation is not compatible.  For example if a character is having sex, and the purity is 5, and the proficiency is 3, the stages would produce this much enjoyment: Stage 1:  25 from imPurity + 3 from Proficiency = 28 Stage 2:  30 from imPurity + 6 from Proficiency = 36 Stage 3:  35 from imPurity + 9 from Proficiency = 44 Stage 4:  40 from imPurity + 12 from Proficiency = 52 Stage 5:  45 from imPurity + 15 from Proficiency = 60   Then let's then define a "Pure Pleasure" Face.  Then the face would be the weighted average between "Pure Pleasure" and the 'base act'.  Suppose we defined Pure Pleasure as: expression 2 100 phoneme 1 100 phoneme 11 60 modifier 6 100 modifier 7 100 modifier 11 100 And we chose 'Pain' as a base for Victim (cribbing off shinji72): Expression 9 100 Modifier 2 100 Modifier 3 100 Modifier 4 100 Modifier 5 100 Modifier 11 90 Phoneme 0 100 Phoneme 2 100 Phoneme 11 40 Out Stage 3 result would be weighted 56% pain and 44% pleasure, giving us something like: Expression 9 56 (pick the highest base) modifier 2 56 modifier 3 56 modifier 4 56 modifier 5 56 modifier 6 44 modifier 7 44 modifier 11 80 phoneme 0 56 phoneme 1 44 phoneme 2 56 phoneme 11 49  This would make the pleasure being received so far as the facial expression dynamic.  One defines a base emotion for various acts at stages and then adjusts them toward pleasure.  Assuming that consensual vanilla acts would produce 'bored' which is going to be mostly neutral, that should work quite well.   I like the idea, my main concern though would be how "good" some of the mixes would end up looking as they progress, and what to do with NPC/NPC scenes as purity and proficiency levels are only available to the player, so npc's would need to fudge the numbers or rely on randomness to some degree.
crusher Posted November 29, 2013 Posted November 29, 2013 check out this work, and a few other posts/pics in thread, Â I'd pm this person for some rather amazing presets. Might even add petition in that thread. though, they could be .psd...Â
sheol Posted November 29, 2013 Posted November 29, 2013 Â I like the idea, my main concern though would be how "good" some of the mixes would end up looking as they progress, and what to do with NPC/NPC scenes as purity and proficiency levels are only available to the player, so npc's would need to fudge the numbers or rely on randomness to some degree. Â Â Yeah, unfortunately without actually writing a script with various values to test it, I can't tell either. Â I tested some by hand, and those seemed to work well, but that doesn't mean it always would. Â For NPC/NPC, you could just double the Purity values (which if they can't be found on NPC's, you could use Morality as a proxy maybe?)... Basically assume that a less pure person would also have a higher proficiency. Â It also might be worthwhile to add a little randomness to the original formulation anyway...
Ashal Posted November 30, 2013 Author Posted November 30, 2013 Â Â I like the idea, my main concern though would be how "good" some of the mixes would end up looking as they progress, and what to do with NPC/NPC scenes as purity and proficiency levels are only available to the player, so npc's would need to fudge the numbers or rely on randomness to some degree. Â Â Yeah, unfortunately without actually writing a script with various values to test it, I can't tell either. Â I tested some by hand, and those seemed to work well, but that doesn't mean it always would. Â For NPC/NPC, you could just double the Purity values (which if they can't be found on NPC's, you could use Morality as a proxy maybe?)... Basically assume that a less pure person would also have a higher proficiency. Â It also might be worthwhile to add a little randomness to the original formulation anyway... Â Â I don't know how familiar you are with Skyrim's scripting, but I put this together last night to try and test it out some: int function GetEnjoyment() ; // Scale higher with stage int BaseWeight = 5 + (5 * Stage) ; // Weights for proficency and purity stat, ~0-7 starting int ProficencyWeight int PurityWeight = Lib.Stats.CalcLevel(Purity, 0.2) ; // Animations involving Vaginal if Animation.HasTag("Vaginal") ; // Base enjoyment for vaginal BaseWeight += 5 ; // Add proficency level ProficencyWeight += Vaginal ; // Give more enjoyment for "pure" characters if Purity > 0 PurityWeight += 2 endIf endIf ; // Animations involving Anal if Animation.HasTag("Anal") ; // Base enjoyment for anal BaseWeight += 7 if !IsFemale ; // Males enjoys it more BaseWeight += 7 else ; // Females have slight discomfort, canceled out by impurity BaseWeight -= 2 endIf ; // Add proficency level ProficencyWeight += Anal ; // Impure characters enjoy it more if Purity > 0 PurityWeight -= 2 else PurityWeight += 2 endIf endIf ; // Animations involving Oral if Animation.HasTag("Oral") ; // Base enjoyment for oral BaseWeight += 7 if !IsFemale ; // Males enjoys it more BaseWeight += 5 endIf ; // Add proficency level ProficencyWeight += Oral ; // Impure characters enjoy it more if Purity > 0 PurityWeight -= 1 else PurityWeight += 1 endIf endIf ; // Animations considered "dirty" if Animation.HasTag("Dirty") ; // Pure characters don't like it if Purity > 0 PurityWeight -= 3 ; // Impure characters do else PurityWeight += 3 endIf endIf ; // Calculate enjoyment int Enjoyment = BaseWeight + ((9 + PurityWeight) * Stage) + (ProficencyWeight * Stage) ; // Cut in half if they are victim in animation if IsVictim Enjoyment = Enjoyment / 2 endIf return Enjoyment endFunction It attempts to weight their enjoyment based on specific animation's, giving weights to different animation types for different genders (The male position enjoying an oral animation more than the female position for example), and weighing it differently based on the actors given proficiency and purity stats. Â If a scene has the player, it uses the players stats for purity and proficiency, if the scene doesn't have the player, the NPC will generate and save a random proficiency level from 0 to 5 and a purity from -5 to 5 at the start of the scene. Â It results in okay numbers, though proficiency doesn't weigh into the final number as much as I'd like. I haven't plugged it into an expression yet, nor figured out a good way of mixing in the pained expression.
sheol Posted November 30, 2013 Posted November 30, 2013   int function GetEnjoyment() ; // Scale higher with stage //+ (5 * Stage) is unnecessary if we do it at the bottom     ; // So Baseweight should range from ~1-6 ? int BaseWeight = 3 ; // Weights for proficency and purity stat, ~0-7 starting int ProficencyWeight ; // Is this also ~0-7? int PurityWeight = Lib.Stats.CalcLevel(Purity, 0.2) ; // Animations involving Vaginal if Animation.HasTag("Vaginal") ; // Base enjoyment for vaginal // This shouldn't be lower than the others // BaseWeight += 5 In fact let's get rid of it         if IsFemale             ; // Females enjoys it more             BaseWeight += 3         endIf ; // Add proficency level ProficencyWeight += Vaginal ; // Give more enjoyment for "pure" characters ; // Why would Pure characters enjoy sex more? Maybe ifMarried +=2 else -=1? if Purity > 0 PurityWeight += 2 endIf endIf ; // Animations involving Anal if Animation.HasTag("Anal") ; // Base enjoyment for anal // BaseWeight += 7 if !IsFemale ; // Males enjoys it more BaseWeight += 2 else ; // Females have slight discomfort, canceled out by impurity BaseWeight -= 1 endIf ; // Add proficency level ProficencyWeight += Anal ; // Impure characters enjoy it more if Purity > 0 PurityWeight -= 2 else PurityWeight += 2 endIf endIf ; // Animations involving Oral if Animation.HasTag("Oral") ; // Base enjoyment for oral // BaseWeight += 7 if !IsFemale ; // Males enjoys it more BaseWeight += 2 endIf ; // Add proficency level ProficencyWeight += Oral ; // Impure characters enjoy it more if Purity > 0 PurityWeight -= 1 else PurityWeight += 1 endIf endIf ; // Animations considered "dirty" if Animation.HasTag("Dirty") ; // Pure characters don't like it if Purity > 0 PurityWeight -= 3 ; // Impure characters do else PurityWeight += 3 endIf endIf ; // Calculate enjoyment (Baseweight get scaled by stage at the top) ; // However this is calculated it needs to range between (0 an 20)*Stage int Enjoyment = (BaseWeight + PurityWeight + ProficencyWeight) * Stage ; // Cut in half if they are victim in animation if IsVictim Enjoyment = Enjoyment / 2 endIf return Enjoyment endFunction It attempts to weight their enjoyment based on specific animation's, giving weights to different animation types for different genders (The male position enjoying an oral animation more than the female position for example), and weighing it differently based on the actors given proficiency and purity stats.  If a scene has the player, it uses the players stats for purity and proficiency, if the scene doesn't have the player, the NPC will generate and save a random proficiency level from 0 to 5 and a purity from -5 to 5 at the start of the scene.  It results in okay numbers, though proficiency doesn't weigh into the final number as much as I'd like. I haven't plugged it into an expression yet, nor figured out a good way of mixing in the pained expression.   I like this, though I put come comments into your code where I thought it could be improved.  It seemed a little Male-centric, so I adjusted that some, and I think the way I laid it out is simpler.  Though I did want to clarify one thing.  BaseWeight + PurityWeight + ProficencyWeight has to range from 0 to 20.  (since it's going to be multiplied by 1 to 5). That means to bias in favor of each of these you need to change that components range.  A balances approach would be to have: 0 < BaseWeight < 6 0 < PurityWeight < 7 0 < ProficencyWeight < 7  However if you wanted to focus on Proficiency more you could do: 0 < BaseWeight < 4 0 < PurityWeight < 4 0 < ProficencyWeight < 12  This might be the most fun: 0 < BaseWeight < 3 0 < PurityWeight < 7 0 < ProficencyWeight < 10  Also, it seems like the Base Emotion are roughly as follows: Masturbation -> Shy Vaginal Sex -> Bored Aggressor Sex -> Angry Victim Sex -> Scared Anal Sex Giving -> ? Anal Sex Receiving -> Pain Oral Sex Giving -> Bored Oral Sex Receiving (male) -> Bored Oral Sex Receiving (Female) -> Shy? or Bored  I'm going to checkout the development branch and see if I can play with this a little.  Â
sheol Posted November 30, 2013 Posted November 30, 2013 So, I apparently downloaded the wrong branch because it's missing all the expression stuff...Even looking at your changelog I'm not positive I understand how I'd hook it in. Â
sheol Posted November 30, 2013 Posted November 30, 2013 Also, for NPC's:Purity = (3*Morality) (assuming a 0-9 scale)Proficency = (Speech / 12) (assuming a 0-9 scale)Or Proficiency may be better as:Proficency = ((Speech - 20)/13)+Morality  and Purity might be better as:Purity = Morality+(4-Confidence)
sheol Posted December 1, 2013 Posted December 1, 2013 Okay, so I spent a whole lot of time going through the script piece by piece. ; // Returns a number between 0 and 100 Actor Property PlayerREF Auto ; // I don't know which 'actor' to choose for NPC int function GetEnjoyment() int BaseWeight = 9 ; // 6 to 12 int SpeechWeight = Actor.GetAV('Speech') / 25 ; // 0 to 4 if Actor === PlayerREF int PurityWeight = GetPlayerPurityLevel() ; // -6 to +6 int ProficencyWeight ; 0 to 6 else ; // If it's an NPC infer the Purity and Proficiency int PurityWeight = 4-(Morality+(4-Actor.GetAV('Confidence')))*1.5 int ProficencyWeight = ((Actor.GetAV('Speech') - 20)/13)+ABS(PurityWeight) endIf ; // Easy way of assigning bonuses if PurityWeight > 0 PuritySign = 1 else PuritySign = -1 endIf ; // Masturbation needs to be accounted for as well if Animation.HasTag("Masturbate") ProficencyWeight += PurityWeight*PuritySign BaseWeight = 12 endIf ; // Vaginal is the preferred choice for females, and is considered 'pure' if Animation.HasTag("Vaginal") if IsFemale BaseWeight += 2 endIf ProficencyWeight += Vaginal BaseWeight += PuritySign endIf ; // Anal is slightly uncomfortable for the receptive partner if Animation.HasTag("Anal") if !IsFemale BaseWeight += 1 else BaseWeight -= 1 endIf ProficencyWeight += Anal BaseWeight -= PuritySign*2 endIf ; // Oral is not especially great for the giving partner if Animation.HasTag("Oral") if !IsFemale BaseWeight += 1 endIf ProficencyWeight += Oral BaseWeight -= PuritySign endIf ; // Dirty preference moves the negative to positive and vice versa if Animation.HasTag("Dirty") PurityWeight *= -1 elseIf !Animation.HasTag("Loving") PurityWeight *= PuritySign endIf ; // BaseWeight + Purity = 6 to 18, Proficincy is thus multiplied to keep in line, Speech gives a small bonus ; // Together they come to 0 to 40. * .5, 1, 1.5, 2, 2.5 for the various stages giving a range of 0 to 100 int Enjoyment = ((BaseWeight + PurityWeight) + ProficencyWeight*3)+SpeechWeight) * (Stage/2) ; // Sexual Assault isn't fun for the victim if IsVictim Enjoyment = Enjoyment / 2 endIf ; // if SexualOrientationMismatch ; // Enjoyment = Enjoyment / 2 ; // endif endFunction I'm a programmer, but I'm still new to Papyrus, so you'll have to take that as pseudo-code. Â However it should be mostly set.Â
sheol Posted December 1, 2013 Posted December 1, 2013 Setting Expression based on current enjoyment ; // Sets an expression based on current enjoyment int function SetExpressionBasedOnEnjoyment() int Enjoyment = GetEnjoyment() ; // .0 to 1.00 float Enjoymodifer = Enjoyment / 100 float Unenjoyment = 1 - Enjoyment while i < 8 ; // Loop through all possible expressions BaseExpression = GetExpression('actor', i)-Enjoyment ; // Magical Function that returns the value of an expression if BaseExpression > 50: ActorRef.SetExpressionOverride(i, BaseExpression) else ActorRef.SetExpressionOverride(2, Enjoyment) endif endwhile while i < 16 ; // Here I make up a function GetPhoneme if i == 1 MfgConsoleFunc.SetPhonemeModifier(ActorRef, Phoneme, 1, GetPhoneme(1)*(Unenjoyment)+(100+Enjoymodifier)) elseif i == 11 MfgConsoleFunc.SetPhonemeModifier(ActorRef, Phoneme, 11, GetPhoneme(11)*(Unenjoyment)+(60+Enjoymodifier)) else MfgConsoleFunc.SetPhonemeModifier(ActorRef, Phoneme, i, GetPhoneme(i)*(Unenjoyment)) endif endwhile ; // This would all be better if the "purePleasure" was a referencable object, but I couldn't figure that out... while i < 14 ; // Here I make up a function GetModifier if i == 6 MfgConsoleFunc.SetPhonemeModifier(ActorRef, Phoneme, 6, GetModifier(6)*(Unenjoyment)+(100+Enjoymodifier)) elseif i == 7 MfgConsoleFunc.SetPhonemeModifier(ActorRef, Phoneme, 7, GetModifier(7)*(Unenjoyment)+(100+Enjoymodifier)) elseif i == 11 MfgConsoleFunc.SetPhonemeModifier(ActorRef, Phoneme, 11, GetModifier(11)*(Unenjoyment)+(100+Enjoymodifier)) else MfgConsoleFunc.SetPhonemeModifier(ActorRef, Phoneme, i, GetModifier(i)*(Unenjoyment)) endif endwhile ; // This would all be better if the "purePleasure" was a referencable object, but I couldn't figure that out... endFunction  Here I, again, couldn't figure out how to actually reference another Expression Preset, or the Current actors MFG values.  However if you can reference those a function sort of like this would work.  Even better if the purePleasure preset could be referenced, you could check for membership in that, and turn these three functions into one liners.
sheol Posted December 1, 2013 Posted December 1, 2013 It occurs to me that the Enjoyment function is likely to get a lot of use from mods like Lovers Comfort or Radiant Prostitution...
Ashal Posted December 1, 2013 Author Posted December 1, 2013 So, I apparently downloaded the wrong branch because it's missing all the expression stuff... Even looking at your changelog I'm not positive I understand how I'd hook it in. Â Â You have to checkout the development branch after cloning the repo, it clones the master branch by default, which is the current official release. Â The branch doesn't have any of this enjoyment stuff yet though, as I'm still trying to piece most of it together in a cohesive manner. I'm working that now but i'm god awful at trying to do anything remotely algorithm related. You seem to have some grasp on that though, so if you have time right now and are up for helping me figure out a solution, PM me your Steam or Skype ID and we can hash out details of it easier that way.
Ashal Posted December 1, 2013 Author Posted December 1, 2013 It shouldn't be capped at 100 in my opinion, it should aim for 100 but be able to scale over it. Otherwise the only way an actor will be able to achieve a high enjoyment is if they have a maxed out applicable proficiency and purity, which makes it more or less unattainable for most. Â The higher their stats the easier it should be to reach ~85+, and likewise low stats should make them unlikely to reach ~85+ unless under the most ideal of tagged animations and on the final stage. Â Using your suggested formula/script as a guide I'm fairly certain I've reached a result I'm satisfied enough with. int function GetEnjoyment() ; // Init weights int BaseWeight int ProficencyWeight int PurityWeight int ActorCount = Controller.ActorCount ; // Appropiate bonus = 1.multiplier -- leaving addition intact ; // Inappropiate bonus = 0 -- canceling out the addition int FemaleBonus = (IsFemale as int) int MaleBonus = ((!IsFemale) as int) int PureBonus = (IsPure as int) int ImpureBonus = ((!IsPure) as int) ; // Scaling purity modifier int PurityMod = 1 + (Purity / 2) ; // Adjust bonuses based on type, gender, and purity if Animation.HasTag("Vaginal") ProficencyWeight += Vaginal BaseWeight += FemaleBonus * 2 BaseWeight += MaleBonus * 3 endIf if Animation.HasTag("Anal") ProficencyWeight += Anal BaseWeight += FemaleBonus * -1 BaseWeight += MaleBonus * 3 PurityWeight += PureBonus * -PurityMod PurityWeight += ImpureBonus * PurityMod endIf if Animation.HasTag("Oral") ProficencyWeight += Oral BaseWeight += FemaleBonus * -1 BaseWeight += MaleBonus * 3 PurityWeight += PureBonus * -PurityMod PurityWeight += ImpureBonus * PurityMod endIf if Animation.HasTag("Dirty") PurityWeight += PureBonus * (-PurityMod - 1) PurityWeight += ImpureBonus * PurityMod endIf if Animation.HasTag("Aggressive") PurityWeight += PureBonus * (-PurityMod - 3) endIf if Animation.HasTag("Loving") PurityWeight += PureBonus * (PurityMod + 1) endIf if Animation.IsCreature PurityWeight += PureBonus * (-PurityMod - 6) endIf if ActorCount > 2 PurityWeight += PureBonus * ((-PurityMod - 3) * (ActorCount - 2)) PurityWeight += ImpureBonus * ((PurityMod + 2) * (ActorCount - 2)) endIf if ActorCount == 1 ProficencyWeight += Purity PurityWeight += ImpureBonus * (PurityMod + (ActorRef.GetActorValue("Confidence") as int)) endIf ; // Ramp up with stage and time spent, maxout time bonus at 2.5 minutes (8 seconds * 19 intervals = 152 seconds == ~2.5 minutes) BaseWeight += (4 * Stage) + Clamp(((Controller.TotalTime / 8.0) as int), 19) ; // Calculate root enjoyment of the animation, give multipler by progress through the animation stages (1/5 stage = 1.20 multiplier) Enjoyment = (((BaseWeight + PurityWeight + (ProficencyWeight * 3)) as float) * ((Stage as float / Animation.StageCount as float) + 1.0)) as int ; // Cap victim at 50 after halving if IsVictim Enjoyment = Clamp((Enjoyment / 2), 50) endIf ; // Return raw enjoyment for modder use, if 100+ expression will clamp value return Enjoyment endFunction Testing on a couple different pairs of npcs they progressed fairly evenly through the stages, starting small and ending between 60 and 110. Â Also put together these functions for calculating a NPC's proficiency and purity levels. I'm less sold on them right now, but they were "serviceable" in my testing. int function CalcLevel(float total, float curve = 0.65) return Math.Sqrt(((Math.Abs(total) + 1.0) / 2.0) * Math.Abs(curve)) as int endFunction float function GetActorPurityStat(actor ActorRef) ; // Get relevant-ish AI data int Aggression = ActorRef.GetActorValue("Aggression") as int int Morality = ActorRef.GetActorValue("Morality") as int int Assistance = ActorRef.GetActorValue("Assistance") as int ; // Init base purity based on level and how aggressive they are float purity = ((ActorRef.GetLevel() / 2 ) * 9) float seed = ((((Aggression+1) as float) / 5.0) * 0.40) ; // Actor doesn't care about crime, make more impure if Morality == 0 seed += 0.10 ; // Actor refuses crime elseIf Morality == 3 seed += 0.07 endIf ; // Actor is a morale pacifist, make more pure if Aggression == 0 && Morality != 0 seed += 0.06 ; // Non aggessive, add small bit elseIf Aggression == 0 seed += 0.02 ; // Aggressive only towards enemies elseIf Aggression == 1 seed += 0.01 endIf ; // 0 = Actor won't help anybody, make more impure ; // 2 = Actor helps friends+allies, make more pure if Assistance != 1 seed += 0.05 endIf ; // Actor is immorale but helps friends+allies, make more pure if Assistance == 2 && Morality == 0 seed -= 0.04 endIf ; // Generate largish purity with seed and base purity purity += ((purity * seed) * 1.75) * 1.5 ; // Sign purity to make impure, based on "bad" traits return sslUtility.SignFloat((Morality == 0 || Aggression >= 2 || (Assistance == 0 && Morality == 3)), purity) endFunction int function GetActorPurityLevel(actor ActorRef) return CalcLevel(GetActorPurityStat(ActorRef), 0.2) endFunction int function GetActorProficencyLevel(actor ActorRef) int xp = (ActorRef.GetLevel() * 2) + ((((ActorRef.GetActorValue("Speechcraft")*ActorRef.GetActorValue("Confidence")) + 1) / 2.0) as int) return CalcLevel(xp, 0.65) endFunction Right now proficiency just generates a generic stat that is applied to all the types (Vaginal, Anal, & Oral) which is probably good enough, I don't see much need to expand it to different types, the main purpose is just to get a consistent number out on an NPC rather than using random numbers. Â Other mods may be able to make use of the stats on NPCs as well though, so I may expand it out to include separate types. Â Now just to figure out how to use the number in conjunction with the expressions Â
Guest kimbale Posted December 1, 2013 Posted December 1, 2013 Ooh, i like what you do with the scripting. Â But i have some issues with it: Â 1) If the scripts would try to mix different presets, there could be severe fuckups as these presets all use a base mfg expression. These don't mix, you just have either one. And applying the modifiers to another base expression yields bad expressions overall. Â 2) Shifting from one preset to the other gives a nice effect, i'd even have them shift back and forth if possible at big increments. I do that in my game already and it works great as reacting to a position shift or anything like that. Having it progress slowly takes out those "twitches" i like.... Â In the end: If all this would be configurable i'd love to have it, otherwise i'd stick to simple sex stage -> mfg preset.
sheol Posted December 1, 2013 Posted December 1, 2013 Those look great. Â The NPC stats are serviceable, so that should work. Â MCM: ; OID bool dynamicOID_B ; // Enable Dynamic Expressions int basefemaleOID_S ; // _S for slider int basemaleOID_S ; _S for slider int vaginalfemaleOID_S ; // _S for slider int vaginalmaleOID_S ; _S for slider int analfemaleOID_S ; // _S for slider int analmaleOID_S ; _S for slider int oralfemaleOID_S ; // _S for slider int oralmaleOID_S ; _S for slider ; State bool dynamic = true int basefemale = 1 ; // Base Female Sexual Enjoyment int basemale = 1 ; // Base Male Sexual Enjoyment int vaginalfemale = 2 ; // Vaginal Female Sexual Enjoyment int vaginalmale = 3 ; Vaginal Female Sexual Enjoyment int analfemale = -1 ; // Anal Female Sexual Enjoyment int analmale = 3 ; Anal Female Sexual Enjoyment int oralfemale = -1 ; // Oral Female Sexual Enjoyment int oralmaleS = 3 ; Oral Female Sexual Enjoyment event OnPageReset(string page) AddHeaderOption("Dynamic Expressions") dynamicOID_B = AddToggleOption("Enable Dynamic Expressions", toggleState) basefemaleOID_S = AddSliderOption("Female Base Enjoyment", frequency, "Base for Receptive Partner") basemaleOID_S = AddSliderOption("Male Base Enjoyment", frequency, "") vaginalfemaleOID_S = AddSliderOption("Female Vaginal Enjoyment", frequency, "Vaginal Receptive") vaginalmaleOID_S = AddSliderOption("Male Vaginal Enjoyment", frequency, "") analfemaleOID_S = AddSliderOption("Female Anal Enjoyment", frequency, "Anal Receptive") analmaleOID_S = AddSliderOption("Male Anal Enjoyment", frequency, "") oralfemaleOID_S = AddSliderOption("Female Oral Enjoyment", frequency, "Oral Receptive") oralmaleOID_S = AddSliderOption("Male Oral Enjoyment", frequency, "") endEvent event OnOptionSelect(int option) if (option == dynamicOID_ toggleState = !toggleState SetToggleOptionValue(dynamicOID_B, toggleState) endIf endEvent event if (option == basefemaleOID_S) SetSliderDialogStartValue(basefemale) SetSliderDialogDefaultValue(1) SetSliderDialogRange(0, 5) SetSliderDialogInterval(1) elseIf (option == basemaleOID_S) SetSliderDialogStartValue(basemale) SetSliderDialogDefaultValue(1) SetSliderDialogRange(0, 5) SetSliderDialogInterval(1) elseIf (option == basefemaleOID_S) SetSliderDialogStartValue(vaginalfemaleOID_S) SetSliderDialogDefaultValue(2) SetSliderDialogRange(-3, 3) SetSliderDialogInterval(1) elseIf (option == basefemaleOID_S) SetSliderDialogStartValue(vaginalmaleOID_S) SetSliderDialogDefaultValue(3) SetSliderDialogRange(-3, 3) SetSliderDialogInterval(1) elseIf (option == basefemaleOID_S) SetSliderDialogStartValue(analfemaleOID_S) SetSliderDialogDefaultValue(-1) SetSliderDialogRange(-3, 3) SetSliderDialogInterval(1) elseIf (option == basefemaleOID_S) SetSliderDialogStartValue(analmaleOID_S) SetSliderDialogDefaultValue(3) SetSliderDialogRange(-3, 3) SetSliderDialogInterval(1) elseIf (option == basefemaleOID_S) SetSliderDialogStartValue(oralfemaleOID_S) SetSliderDialogDefaultValue(-1) SetSliderDialogRange(-3, 3) SetSliderDialogInterval(1) elseIf (option == basefemaleOID_S) SetSliderDialogStartValue(oralmaleOID_S) SetSliderDialogDefaultValue(3) SetSliderDialogRange(-3, 3) SetSliderDialogInterval(1) endIf endEvent event OnOptionSliderAccept(int option, float value) if (option == dynamicOID_ dynamic = value SetSliderOptionValue(dynamicOID_B, dynamic, "") elseIf (option == basefemaleOID_S) basefemale = value SetSliderOptionValue(basefemaleOID_S, basefemale, "") elseIf (option == basemaleOID_S) basemale = value SetSliderOptionValue(basemaleOID_S, basemale, "") elseIf (option == vaginalfemaleOID_S) vaginalfemale = value SetSliderOptionValue(vaginalfemaleOID_S, vaginalfemale, "") elseIf (option == vaginalmaleOID_S) vaginalmale = value SetSliderOptionValue(vaginalmalenOID_S, vaginalmale, "") elseIf (option == analfemaleOID_S) analfemale = value SetSliderOptionValue(analfemaleOID_S, analfemale, "") elseIf (option == analmalefemaleOID_S) analmale = value SetSliderOptionValue(analmaleOID_S, analmale, "") elseIf (option == oralfemaleOID_S) oralfemale = value SetSliderOptionValue(oralfemaleOID_S, oralfemale, "") elseIf (option == oralmaleOID_S) oralmale = value SetSliderOptionValue(oralmaleOID_S, oralmale, "") endIf endEvent Which using your code would produce int function GetEnjoyment() if !dynamic return 0 ; // Also need to make vanilla sex be pleasurable base instead of neutral endIf ; // Init weights int BaseWeight int ProficencyWeight int PurityWeight int ActorCount = Controller.ActorCount ; // Appropiate bonus = 1.multiplier -- leaving addition intact ; // Inappropiate bonus = 0 -- canceling out the addition int FemaleBonus = (IsFemale as int) * basefemale int MaleBonus = ((!IsFemale) as int) * basemale int PureBonus = (IsPure as int) int ImpureBonus = ((!IsPure) as int) ; // Scaling purity modifier int PurityMod = 1 + (Purity / 2) ; // Adjust bonuses based on type, gender, and purity if Animation.HasTag("Vaginal") ProficencyWeight += Vaginal BaseWeight += FemaleBonus * vaginalfemale BaseWeight += MaleBonus * vaginalmale endIf if Animation.HasTag("Anal") ProficencyWeight += Anal BaseWeight += FemaleBonus * analfemale BaseWeight += MaleBonus * analmale PurityWeight += PureBonus * -PurityMod PurityWeight += ImpureBonus * PurityMod endIf if Animation.HasTag("Oral") ProficencyWeight += Oral BaseWeight += FemaleBonus * oralfemale BaseWeight += MaleBonus * oralmale PurityWeight += PureBonus * -PurityMod PurityWeight += ImpureBonus * PurityMod endIf if Animation.HasTag("Dirty") PurityWeight += PureBonus * (-PurityMod - 1) PurityWeight += ImpureBonus * PurityMod endIf if Animation.HasTag("Aggressive") PurityWeight += PureBonus * (-PurityMod - 3) endIf if Animation.HasTag("Loving") PurityWeight += PureBonus * (PurityMod + 1) endIf if Animation.IsCreature PurityWeight += PureBonus * (-PurityMod - 6) endIf if ActorCount > 2 PurityWeight += PureBonus * ((-PurityMod - 3) * (ActorCount - 2)) PurityWeight += ImpureBonus * ((PurityMod + 2) * (ActorCount - 2)) endIf if ActorCount == 1 ProficencyWeight += Purity PurityWeight += ImpureBonus * (PurityMod + (ActorRef.GetActorValue("Confidence") as int)) endIf ; // Ramp up with stage and time spent, maxout time bonus at 2.5 minutes (8 seconds * 19 intervals = 152 seconds == ~2.5 minutes) BaseWeight += (4 * Stage) + Clamp(((Controller.TotalTime / 8.0) as int), 19) ; // Calculate root enjoyment of the animation, give multipler by progress through the animation stages (1/5 stage = 1.20 multiplier) Enjoyment = (((BaseWeight + PurityWeight + (ProficencyWeight * 3)) as float) * ((Stage as float / Animation.StageCount as float) + 1.0)) as int ; // Cap victim at 50 after halving if IsVictim Enjoyment = Clamp((Enjoyment / 2), 50) ; // Should probably have this be configurable too... endIf ; // Return raw enjoyment for modder use, if 100+ expression will clamp value return Enjoyment endFunction You'll have to play around with the allowable ranges, I'm not quite sure what is reasonable. Â Â That MCM should allow people to have their own male/female enjoyment equations and solve the fact that some people may not want it at all. Â Though, as far as your objection kimbale, I wouldn't have bothered if experiments by hand hadn't produced reasonable results."Twitchiness" could possibly be put in, but it seems like feature creep to think about it right now...
sheol Posted December 1, 2013 Posted December 1, 2013 One more thing. Most of this doesn't change very often, so can be calculated once at the start, and then modified each stage: ; // This needs to be run when the scene starts int function GetStartEnjoyment() if !dynamic return 0 ; // Also need to make vanilla sex be pleasurable base instead of neutral endIf ; // Init weights int BaseWeight int ProficencyWeight int PurityWeight int ActorCount = Controller.ActorCount ; // Appropiate bonus = 1.multiplier -- leaving addition intact ; // Inappropiate bonus = 0 -- canceling out the addition int FemaleBonus = (IsFemale as int) * basefemale int MaleBonus = ((!IsFemale) as int) * basemale int PureBonus = (IsPure as int) int ImpureBonus = ((!IsPure) as int) ; // Scaling purity modifier int PurityMod = 1 + (Purity / 2) ; // Adjust bonuses based on type, gender, and purity if Animation.HasTag("Vaginal") ProficencyWeight += Vaginal BaseWeight += FemaleBonus * vaginalfemale BaseWeight += MaleBonus * vaginalmale endIf if Animation.HasTag("Anal") ProficencyWeight += Anal BaseWeight += FemaleBonus * analfemale BaseWeight += MaleBonus * analmale PurityWeight += PureBonus * -PurityMod PurityWeight += ImpureBonus * PurityMod endIf if Animation.HasTag("Oral") ProficencyWeight += Oral BaseWeight += FemaleBonus * oralfemale BaseWeight += MaleBonus * oralmale PurityWeight += PureBonus * -PurityMod PurityWeight += ImpureBonus * PurityMod endIf if Animation.HasTag("Dirty") PurityWeight += PureBonus * (-PurityMod - 1) PurityWeight += ImpureBonus * PurityMod endIf if Animation.HasTag("Aggressive") PurityWeight += PureBonus * (-PurityMod - 3) endIf if Animation.HasTag("Loving") PurityWeight += PureBonus * (PurityMod + 1) endIf if Animation.IsCreature PurityWeight += PureBonus * (-PurityMod - 6) endIf if ActorCount > 2 PurityWeight += PureBonus * ((-PurityMod - 3) * (ActorCount - 2)) PurityWeight += ImpureBonus * ((PurityMod + 2) * (ActorCount - 2)) endIf if ActorCount == 1 ProficencyWeight += Purity PurityWeight += ImpureBonus * (PurityMod + (ActorRef.GetActorValue("Confidence") as int)) endIf float StartingEnjoyment = (((BaseWeight + PurityWeight + (ProficencyWeight * 3)) as float) endFunction ; // This needs to be undated regularly int function GetEnjoyment() Enjoyment = StartingEnjoyment ; // Ramp up with stage and time spent, maxout time bonus at 2.5 minutes (8 seconds * 19 intervals = 152 seconds == ~2.5 minutes) Enjoyment += (4 * Stage) + Clamp(((Controller.TotalTime / 8.0) as int), 19) ; // Calculate root enjoyment of the animation, give multipler by progress through the animation stages (1/5 stage = 1.20 multiplier) Enjoyment = Enjoyment * ((Stage as float / Animation.StageCount as float) + 1.0)) as int ; // Cap victim at 50 after halving if IsVictim Enjoyment = Clamp((Enjoyment / 2), 50) ; // Should probably have this be configurable too... endIf ; // Return raw enjoyment for modder use, if 100+ expression will clamp value return Enjoyment endFunction
sheol Posted December 1, 2013 Posted December 1, 2013 I (more or less) figured out a way to handles mixing the expressions ; // In sslBaseExpression int[] male1 = new int[32] int[] male2 = new int[32] int[] male3 = new int[32] int[] male4 = new int[32] int[] male5 = new int[32] int[] female1 = new int[32] int[] female2 = new int[32] int[] female3 = new int[32] int[] female4 = new int[32] int[] female5 = new int[32] ;// Such that ;// [expression, ex_val, ;// p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, ;// m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13] ;// Then function ApplyPreset(int[] presets, actor ActorRef, bool openmouth = false) int i = 32 while i i -= 1 if i == 1 ActorRef.SetExpressionOverride(presets[(i - 1)], presets[i]). return elseIf i < 17 MfgConsoleFunc.SetPhonemeModifier(ActorRef, 'phoneme', i-2, presets[i]) else MfgConsoleFunc.SetPhonemeModifier(ActorRef, 'modifier', i-17, presets[i]) endIf endWhile endFunction int[] function PresetMixing(int[] basepreset, int[] mixingpreset, int phase, bool, isFemale, float bias) int[] newPreset = new int[32] int i = 32 while i if basepreset[i] == None basepreset[i] = 0 ; // Papyrus allows sparse arrays... endIf if mixingpreset[i] == None mixingpreset[i] = 0 endIf i -= 1 if i == 1 if (basepreset[1]*(1-bias)) > (mixingpreset[1]*bias) newPreset[0] = basepreset[0] newPreset[1] = basepreset[1]*(1-bias) else newPreset[0] = mixingpreset[0] newPreset[1] = mixingpreset[1]*bias ActorRef.SetExpressionOverride(newPreset[0], newPreset[1]) ; // I don't know whether this should be real time of cached... return newPreset ; // This will always happen elseIf i < 17 newPreset[i] = (basepreset[i]*(1-bias))+(mixingpreset[i]*bias) MfgConsoleFunc.SetPhonemeModifier(ActorRef, 'phoneme', i-2, newPreset[i]) else newPreset[i] = (basepreset[i]*(1-bias))+(mixingpreset[i]*bias) MfgConsoleFunc.SetPhonemeModifier(ActorRef, 'modifier', i-17, newPreset[i]) endIf endWhile endFunction The only downside is that it means the presets will always be integer arrays of length 32, and requires re-factoring your code to use the index as the phoneme/modifier. Â I think it's cleaner (and uses less memory) this way, but it means reworking code... Â
sheol Posted December 1, 2013 Posted December 1, 2013 Oh, and I still like  this as the height of pleasure: expression 2 100 phoneme 1 100 phoneme 11 60 modifier 6 100 modifier 7 100 modifier 11 100
WizzyD Posted December 4, 2013 Posted December 4, 2013 as a pondering user... Â will there be tongue action on the ahego faces?
Baconsama Posted December 5, 2013 Posted December 5, 2013 YOu can use the ECE expressions to get emotions too but I don't know if it'll be as compatible as using mfg(unless they're similar somehow, I've no idea). Anyways, ahegao pls (plz excuse the cursor)   Uploaded with ImageShack.com   Excelent idea!  Also,you have a promissing modding,shinji72,eager to see how it will end,but the first set pictured better pain in my opnion,could you try doing something as .gifs or videos?It would be easier to give feedback,if you manage to do so. Â
Ashal Posted December 10, 2013 Author Posted December 10, 2013 Planned release date of 1.30 is coming up quick, and don't have very many MFG presets so far, so again putting the call out for more submissions if people can do them.
shinji72 Posted December 10, 2013 Posted December 10, 2013 What are the holes to be filled? (no pun inteded...) Â I think I've reached my skill limit and can't improve much my "pain" (more or less) expressions..
Ashal Posted December 10, 2013 Author Posted December 10, 2013 The ones I have so far are Pleasure Shy Afraid Pained Angry Some ideas for missing emotions that are needed: Happy Loving Horny/Ahegao Sad 1
shinji72 Posted December 10, 2013 Posted December 10, 2013 Loving? Oh my god...3-4 stages each would be enough?
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now