Improve POV outercourse positioning

This commit is contained in:
2026-06-25 16:17:19 +02:00
parent 186f225778
commit cd076b3c02
3 changed files with 84 additions and 32 deletions
+13 -3
View File
@@ -448,7 +448,9 @@
"toes curled around the shaft",
"balls held gently against the mouth",
"skin visibly compressed under fingers",
"wet contact visible on the penis"
"wet contact visible on the penis",
"hand wrapped around the shaft with the glans visible",
"fingers and palm visibly stroking the penis"
],
"expression_detail": [
"focused downward gaze",
@@ -468,7 +470,9 @@
"hands holding the ankles in place",
"one hand holding the base of the penis",
"hands cupping balls close to the mouth",
"fingers spreading the breasts around the shaft"
"fingers spreading the breasts around the shaft",
"one hand wrapped around the shaft",
"both hands stroking the penis in the foreground"
],
"outer_act": [
"boobjob with the penis squeezed between both breasts",
@@ -478,6 +482,8 @@
"balls licking with tongue contact under the shaft",
"penis licking with tongue along the shaft and glans",
"slow tongue licking on the underside of the penis",
"handjob with one hand wrapped around the penis",
"two-handed handjob with the shaft centered in frame",
"footjob with both soles wrapped around the penis",
"footjob with toes curled around the shaft",
"feet stroking the penis while the legs frame the contact"
@@ -490,9 +496,11 @@
"low-angle balls-licking position",
"kneeling penis-licking position",
"side-profile penis-licking position",
"kneeling handjob position",
"close-up handjob position",
"reclining footjob position",
"seated footjob position",
"POV footjob position"
"close-up footjob position"
],
"surface": [
"rumpled bed sheets",
@@ -511,6 +519,7 @@
"wet lips and tongue contact",
"slight saliva shine on skin",
"toes pressing into the shaft",
"fingers sliding along the shaft",
"natural asymmetry and soft tissue movement",
"visible pressure marks from fingers or soles"
],
@@ -520,6 +529,7 @@
"glans and lips visible at the same contact point",
"balls and mouth contact visible",
"tongue contact on the penis clearly visible",
"hand and penis centered in frame",
"feet and penis centered in frame",
"soles and shaft contact clearly visible",
"explicit non-penetrative genital contact visible"
+30 -15
View File
@@ -468,29 +468,37 @@ def _pov_hardcore_pose_sentence(
details = _pov_clean_detail(action_text.split(";", 1)[1], f"{context} {base}", detail_density)
return f"{base}; {details}" if details else base
def outercourse_sentence(base: str) -> str:
return _clean(base).rstrip(".")
if _is_outercourse_text(context, action_lower):
if any(term in context for term in ("boobjob", "titjob", "breast sex", "breast-sex")):
return sentence(
"POV breast-sex position: the viewer reclines with his hips in the foreground while the woman kneels between his thighs; "
"her hands press both breasts around the viewer's penis with the glans near her mouth"
return outercourse_sentence(
"The woman kneels low between the viewer's thighs, chest directly over his pelvis; "
"both hands press her breasts tightly around the viewer's penis, with the shaft vertical in the lower foreground and the glans just below her lips"
)
if any(term in context for term in ("testicle", "balls licking", "balls-licking", "balls and mouth")):
return sentence(
"POV testicle-sucking position: the viewer reclines with thighs open while the woman kneels low between his legs; "
"her mouth and tongue stay at the viewer's balls with his penis visible above her face"
return outercourse_sentence(
"The woman kneels very low between the viewer's thighs, face below the shaft at testicle height; "
"her mouth and tongue contact the viewer's balls while his penis points upward above her forehead in the lower foreground"
)
if any(term in context for term in ("penis licking", "penis-licking", "tongue along", "tongue licking")):
return sentence(
"POV penis-licking position: the viewer's hips and penis are in the foreground while the woman kneels close; "
"her tongue moves along the shaft and glans with her hands steadying the base"
return outercourse_sentence(
"The woman kneels close at the viewer's pelvis, face just above his hips; "
"her tongue runs along the underside of the penis from shaft to glans while one hand steadies the base in the lower foreground"
)
if any(term in context for term in ("handjob", "hand job", "hand wrapped", "hand stroking", "manual stimulation")):
return outercourse_sentence(
"The woman kneels close at the viewer's pelvis with her face behind the shaft; "
"one hand wraps around the penis and the other steadies the base as she strokes toward the glans in the lower foreground"
)
if any(term in context for term in ("footjob", "soles", "toes curled", "feet stroking")):
return sentence(
"POV footjob position: the viewer reclines with his penis in the foreground while the woman faces him; "
"her soles wrap around the shaft and stroke it with the contact point centered"
return outercourse_sentence(
"The woman faces the viewer with both legs raised toward the camera; "
"her soles wrap around the penis in the lower foreground, toes curled around the shaft with her face visible beyond the contact"
)
return sentence(
"POV non-penetrative outercourse position: the viewer's hips stay in the foreground while the woman keeps the visible contact point centered"
return outercourse_sentence(
"The woman stays close to the viewer's pelvis, keeping the non-penetrative contact centered in the lower foreground with her face visible behind the contact"
)
penetrative_tokens = (
"penetrat",
@@ -687,7 +695,7 @@ def _clothing_access_phrase(action_text: Any) -> str:
text = _clean(action_text).lower()
if any(term in text for term in ("cumshot", "ejaculat", "semen", "cum on", "cum across", "post-orgasm", "aftermath")):
return "leaving the body exposed for visible semen and aftermath"
if any(term in text for term in ("boobjob", "titjob", "breast sex", "footjob", "testicle", "balls", "penis licking", "non-penetrative")):
if any(term in text for term in ("boobjob", "titjob", "breast sex", "handjob", "hand job", "footjob", "testicle", "balls", "penis licking", "non-penetrative")):
return "leaving the contact point unobstructed"
if any(term in text for term in ("oral", "blowjob", "fellatio", "mouth", "tongue")):
return "leaving the oral contact unobstructed"
@@ -791,6 +799,11 @@ def _is_outercourse_text(*parts: Any) -> bool:
"penis licking",
"penis-licking",
"tongue along",
"handjob",
"hand job",
"hand wrapped",
"hand stroking",
"manual stimulation",
"footjob",
"soles",
"toes curled",
@@ -849,6 +862,8 @@ def _hardcore_pose_anchor(role_graph: str, hard_item: str, composition: str = ""
return "testicle-sucking outercourse pose"
if any(term in text for term in ("penis licking", "penis-licking", "tongue along", "tongue licking")):
return "penis-licking outercourse pose"
if any(term in text for term in ("handjob", "hand job", "hand wrapped", "hand stroking", "manual stimulation")):
return "handjob outercourse pose"
if any(term in text for term in ("footjob", "soles", "toes curled", "feet stroking")):
return "footjob outercourse pose"
return "non-penetrative outercourse pose"
+41 -14
View File
@@ -336,6 +336,7 @@ HARDCORE_POSITION_KEY_CHOICES = [
"boobjob",
"testicle_sucking",
"penis_licking",
"handjob",
"footjob",
"open_thighs",
"front_back",
@@ -379,6 +380,7 @@ HARDCORE_POSITION_KEY_MATCHES = {
"boobjob": ("boobjob", "titjob", "breast-sex", "breast sex"),
"testicle_sucking": ("testicle", "balls-licking", "balls licking", "balls and mouth"),
"penis_licking": ("penis-licking", "penis licking", "tongue along", "tongue licking"),
"handjob": ("handjob", "hand job", "stroking the penis", "hand stroking", "manual stimulation"),
"footjob": ("footjob", "soles", "toes curled", "feet stroking"),
"open_thighs": ("thighs open", "legs spread", "open thighs", "legs open", "reclining with thighs open"),
"front_back": ("front-and-back", "front and back", "one behind and one in front", "between two partners"),
@@ -1023,6 +1025,8 @@ def _outercourse_acts_for_position(values: list[Any], position: str) -> list[Any
return filtered(lambda text: any(term in text for term in ("testicle", "balls")))
if "penis-licking" in position_text or "penis licking" in position_text:
return filtered(lambda text: "licking" in text or "tongue" in text)
if "handjob" in position_text or "hand job" in position_text:
return filtered(lambda text: any(term in text for term in ("handjob", "hand job", "hand wrapped", "two-handed")))
if "footjob" in position_text:
return filtered(lambda text: any(term in text for term in ("footjob", "feet", "soles", "toes")))
return values
@@ -1070,6 +1074,15 @@ def _outercourse_axis_values_for_position(values: list[Any], position: str, axis
"body_contact": ("hips", "body angled", "lower body"),
}
return filtered(by_axis.get(axis_name, ("tongue", "glans", "shaft")))
if "handjob" in position_text or "hand job" in position_text:
by_axis = {
"contact_detail": ("hand", "fingers", "palm", "shaft", "glans"),
"hand_detail": ("hand", "hands", "shaft", "penis"),
"texture_detail": ("fingers", "pressure", "skin", "shaft"),
"visibility": ("hand", "penis", "shaft", "glans"),
"body_contact": ("hips", "knees", "body angle"),
}
return filtered(by_axis.get(axis_name, ("hand", "penis", "shaft")))
if "footjob" in position_text:
by_axis = {
"contact_detail": ("soles", "toes", "shaft"),
@@ -5100,38 +5113,48 @@ def _role_graph(
if any(term in text for term in ("boobjob", "titjob", "breast-sex", "breast sex")):
if man_is_pov:
return (
f"{woman} kneels between the POV viewer's thighs with her breasts squeezed around the POV viewer's penis, "
"hands pressing both breasts together around the shaft while the glans stays near her mouth."
f"{woman} kneels low between the POV viewer's thighs, chest directly over his pelvis, "
"both hands pressing her breasts tightly around the POV viewer's penis while the glans sits just below her lips."
)
return (
f"{man} sits with legs apart while {woman} kneels between his thighs, squeezing her breasts "
f"around {man}'s penis with both hands while the glans stays near her mouth."
f"{man} sits with legs apart while {woman} kneels low between his thighs, chest over his pelvis, "
f"both hands pressing her breasts tightly around {man}'s penis while the glans sits just below her lips."
)
if any(term in text for term in ("testicle", "balls-licking", "balls licking", "balls and mouth", "balls held")):
if man_is_pov:
return (
f"{woman} kneels between the POV viewer's thighs with her mouth at the POV viewer's balls, "
"lips and tongue making visible contact while the POV viewer's penis remains above her face."
f"{woman} kneels very low between the POV viewer's thighs, face below the shaft at testicle height, "
"mouth and tongue on the POV viewer's balls while his penis points upward above her forehead."
)
return (
f"{man} sits with legs apart while {woman} kneels low between his thighs, sucking and licking his balls "
f"with {man}'s penis visible above her face."
f"{man} sits with legs apart while {woman} kneels very low between his thighs, face below the shaft at testicle height, "
f"mouth and tongue on his balls while {man}'s penis points upward above her forehead."
)
if "penis-licking" in position_text or "penis licking" in text or "tongue along" in text or "tongue licking" in text:
if man_is_pov:
return (
f"{woman} kneels at the POV viewer's hips with her tongue along the POV viewer's penis, "
"face close to the shaft and glans while her hands steady the base."
f"{woman} kneels close at the POV viewer's pelvis, face just above his hips, "
"tongue running along the underside of the POV viewer's penis from shaft to glans while one hand steadies the base."
)
return (
f"{woman} kneels at {man}'s hips with her tongue along {man}'s penis, face close to the shaft and glans "
"while her hands steady the base."
f"{woman} kneels close at {man}'s pelvis, face just above his hips, "
f"tongue running along the underside of {man}'s penis from shaft to glans while one hand steadies the base."
)
if "handjob" in position_text or "handjob" in text or "hand job" in text or "hand wrapped" in text:
if man_is_pov:
return (
f"{woman} kneels close at the POV viewer's pelvis with her face behind the shaft, "
"one hand wrapped around the POV viewer's penis and the other hand steadying the base as she strokes toward the glans."
)
return (
f"{woman} kneels close at {man}'s pelvis with her face behind the shaft, "
f"one hand wrapped around {man}'s penis and the other hand steadying the base as she strokes toward the glans."
)
if "footjob" in text or "soles" in text or "toes curled" in text or "feet stroking" in text:
if man_is_pov:
return (
f"{woman} faces the POV viewer while the POV viewer reclines, wrapping both soles around the POV viewer's penis "
"and stroking the shaft with her feet from a clear first-person view."
f"{woman} faces the POV viewer with legs raised toward the camera, both soles wrapped around the POV viewer's penis "
"in the lower foreground and toes curled around the shaft."
)
return (
f"{man} reclines with hips forward while {woman} faces him and wraps both soles around {man}'s penis, "
@@ -6622,6 +6645,10 @@ MAN_LOWER_ACCESS_TERMS = (
"titjob",
"breast sex",
"footjob",
"handjob",
"hand job",
"hand wrapped",
"hand stroking",
"blowjob",
"fellatio",
"penis sucking",