atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
8b8e83329a1daec70177de3e129964094a711509
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git
src/game/progress.rsRust185 lines6.6 KB
1
use super::{
2
    Floor, Lube, MumVisit, Notice, Observer, Run, Story,
3
    balance::{
4
        BRANCH_TURN, CAT_TAKES_TOWEL, CHANGING_ROOM_CHILL, EQ_WOBBLE, EXTENDER_GAIN,
5
        FORESKIN_GLIDE, FRICTION_BURN, FRICTION_BURN_AT, FRICTION_DRY, FRICTION_GRIP, FRICTION_MAX,
6
        FRICTION_SPIT, GIRTH_THICK, HOT_EQ, OBSERVED, PRIAPISM_EQ, PRIAPISM_TURNS, PULLED_MUSCLE,
7
        PULLED_MUSCLE_INTENSITY, RING_PRIAPISM, RING_TIGHT_PRIAPISM, STROKE_EQ, STROKE_EQ_COST,
8
        SUSPICION_LIMIT, VIGOUR,
9
    },
10
};
11
12
impl Run {
13
    pub(super) fn chafe(&mut self, lube: Option<Lube>, intensity: i32) {
14
        let (base, slip) = match lube {
15
            None => (FRICTION_DRY, 0),
16
            Some(Lube::Spit) => (FRICTION_SPIT, 0),
17
            Some(Lube::Lotion) => (0, 0),
18
            Some(Lube::BabyOil | Lube::CoconutOil) => (0, 1),
19
            Some(Lube::Vaseline) => (0, 2),
20
        };
21
        let vigour = usize::try_from(intensity - 1).map_or(0, |i| VIGOUR[i.min(VIGOUR.len() - 1)]);
22
        let unlubed = matches!(lube, None | Some(Lube::Spit));
23
        let thick = i32::from(unlubed && self.body.girth > GIRTH_THICK);
24
        let glide = i32::from(unlubed && self.body.foreskin.is_some_and(|f| f >= FORESKIN_GLIDE));
25
        let mut friction = (base + vigour + thick - slip - glide).max(0);
26
        if friction > 0
27
            && self
28
                .body
29
                .jelq_grip
30
                .is_some_and(|grip| grip != self.body.grip)
31
        {
32
            friction -= FRICTION_GRIP;
33
        }
34
        self.body.jelq_grip = Some(self.body.grip);
35
        self.body.friction = (self.body.friction + friction).min(FRICTION_MAX);
36
        if self.body.friction >= FRICTION_BURN_AT
37
            && !self.body.conditions.friction_burn
38
            && self.chance(
39
                self.decision(
40
                    "friction-burn",
41
                    "With the skin this raw, has it finally burned?",
42
                ),
43
                FRICTION_BURN,
44
            )
45
        {
46
            self.body.conditions.friction_burn = true;
47
        }
48
    }
49
50
    pub(super) fn commit(&mut self, intensity: i32, lube: Option<Lube>, cost: i32) {
51
        self.begin_turn();
52
        self.step_away();
53
        if self.items.kit.extender {
54
            self.body.length += EXTENDER_GAIN;
55
        }
56
        self.body.stamina -= cost + i32::from(lube == Some(Lube::Lotion));
57
        if self.body.stamina <= 0 {
58
            self.exhaust();
59
        }
60
        let chill = if self.floor == Floor::ChangingRoom {
61
            CHANGING_ROOM_CHILL
62
        } else {
63
            0
64
        };
65
        let wobble = self.oracle.span_int(
66
            self.decision(
67
                "wobble",
68
                "How does the count drift on this stroke, up or down?",
69
            ),
70
            -EQ_WOBBLE,
71
            EQ_WOBBLE,
72
        );
73
        self.body.eq =
74
            (self.body.eq + intensity * STROKE_EQ - STROKE_EQ_COST - chill + wobble).clamp(0, 100);
75
76
        self.make_noise(intensity / 5 + i32::from(lube == Some(Lube::Vaseline)));
77
        if self.floor == Floor::Nans && lube == Some(Lube::CoconutOil) {
78
            self.add_suspicion(2);
79
        }
80
81
        if intensity >= PULLED_MUSCLE_INTENSITY
82
            && !self.body.conditions.pulled_muscle
83
            && self.oracle.chance_not(
84
                self.decision("pulled-muscle", "Do the muscles hold?"),
85
                PULLED_MUSCLE,
86
            )
87
        {
88
            self.body.conditions.pulled_muscle = true;
89
            self.body.stamina = self.body.stamina.min(self.max_stamina());
90
        }
91
        self.settle();
92
    }
93
94
    pub(super) fn make_noise(&mut self, noise: i32) {
95
        let doubled = match self.floor {
96
            Floor::Nans => true,
97
            Floor::ChangingRoom => !self.holds_own_in_the_locker_room(),
98
            _ => false,
99
        };
100
        self.add_suspicion(if doubled { noise * 2 } else { noise });
101
    }
102
103
    pub(super) fn add_suspicion(&mut self, amount: i32) {
104
        self.standing.suspicion = u8::try_from(
105
            (i32::from(self.standing.suspicion) + amount).clamp(0, i32::from(SUSPICION_LIMIT)),
106
        )
107
        .unwrap_or(SUSPICION_LIMIT);
108
    }
109
110
    pub(super) fn settle(&mut self) {
111
        self.maybe_summon_mum();
112
        if let Some(observer) = self.floor.observer()
113
            && self.chance(
114
                self.decision("observed", "Has someone quietly noticed what is going on?"),
115
                OBSERVED,
116
            )
117
        {
118
            self.observed = Some(observer);
119
            self.standing.shame += 1;
120
            if observer == Observer::Cat
121
                && self.chance(
122
                    self.decision("cat-takes-towel", "Has the cat taken the towel?"),
123
                    CAT_TAKES_TOWEL,
124
                )
125
            {
126
                self.here.towel_stolen = true;
127
            }
128
        }
129
        if self.items.kit.ring
130
            && self.body.eq > HOT_EQ
131
            && self.chance(
132
                self.decision(
133
                    "ring-priapism",
134
                    "With the ring still on and everything this warm, will it not go down?",
135
                ),
136
                if self.body.girth > GIRTH_THICK {
137
                    RING_TIGHT_PRIAPISM
138
                } else {
139
                    RING_PRIAPISM
140
                },
141
            )
142
        {
143
            self.body.conditions.priapism_turns = PRIAPISM_TURNS;
144
        }
145
        if self.body.conditions.priapism_turns > 0 {
146
            self.body.conditions.priapism_turns -= 1;
147
            self.body.eq = self.body.eq.max(PRIAPISM_EQ);
148
        }
149
        if self.turn == BRANCH_TURN && self.online.story == Story::Unopened {
150
            self.online.story = Story::Pending;
151
            self.notices.push(Notice::ThreadHasReplies);
152
        }
153
    }
154
155
    pub(super) fn maybe_summon_mum(&mut self) {
156
        let was_below = self.standing.at_turn_start < SUSPICION_LIMIT;
157
        if !self.floor.has_mum() || self.household.mum.is_some() {
158
            return;
159
        }
160
        let summoned = was_below && self.standing.suspicion == SUSPICION_LIMIT;
161
        let mut visits = u32::from(self.standing.suspicion) + 1;
162
        if self.here.brother_told {
163
            visits *= 2;
164
        }
165
        if summoned
166
            || self.oracle.ratio(
167
                self.decision(
168
                    "mum-summon",
169
                    "With this much noise in the house, is Mum on her way up?",
170
                ),
171
                visits,
172
                super::balance::MUM_VISIT,
173
            )
174
        {
175
            let errand = self.errand(summoned);
176
            let nonce = self.fresh_nonce();
177
            self.household.mum = Some(MumVisit {
178
                errand,
179
                nonce,
180
                strikes: 0,
181
                knocked: false,
182
            });
183
        }
184
    }
185
}