1 .float regurgitate_prepare;
\r
2 .float system_delay, swallow_delay, digest_button_delay, regurgitate_button_delay;
\r
3 .float complain_swallow;
\r
4 const float complain_delay = 1;
\r
5 const float button_delay = 0.5;
\r
6 const float steptime = 0.1;
\r
7 const float system_delay_time = 0.1;
\r
9 .float vore_oldmovetype, vore_oldsolid, vore_oldstomachload, vore_oldview_ofs_z;
\r
11 entity Swallow_distance_check()
\r
13 // check if we can swallow a player instead of firing our weapon
\r
14 vector w_shotorg, w_shotdir;
\r
15 w_shotorg = self.origin + self.view_ofs;
\r
16 w_shotdir = v_forward;
\r
18 WarpZone_traceline_antilag(self, w_shotorg, w_shotorg + w_shotdir * cvar("g_balance_vore_swallow_range"), FALSE, self, ANTILAG_LATENCY(self));
\r
19 if(trace_fraction < 1)
\r
20 if(trace_ent.classname == "player")
\r
25 float Swallow_condition_check(entity prey)
\r
27 // checks the necessary conditions for swallowing another player
\r
28 if(prey.classname == "player" && prey.eater.classname != "player" && prey.deadflag == DEAD_NO) // we can't swallow someone who's already in someone else's stomach
\r
29 if(self.classname == "player" && self.eater.classname != "player" && self.deadflag == DEAD_NO) // we can't swallow players while inside someone's stomach ourselves
\r
30 if not(vlen(self.velocity) > cvar("g_balance_vore_regurgitate_velocitylimit"))
\r
32 if(self.stomach_load >= cvar("g_balance_vore_swallow_limit"))
\r
34 if(time > self.complain_swallow)
\r
36 play2(self, "weapons/unavailable.wav");
\r
37 sprint(self, strcat("You cannot swallow more than ^2", cvar_string("g_balance_vore_swallow_limit"), "^7 players at a time\n"));
\r
38 self.complain_swallow = time + complain_delay;
\r
43 if(cvar("g_vore_biggergut"))
\r
44 if(prey.stomach_load > self.stomach_load)
\r
46 if(time > self.complain_swallow)
\r
48 play2(self, "weapons/unavailable.wav");
\r
49 sprint(self, "You cannot swallow someone with a bigger stomach than yours\n");
\r
50 self.complain_swallow = time + complain_delay;
\r
59 // make the camera smoothly lower itself when we get swallowed
\r
60 // the target we are going for is from normal view offset to half of the view offset (because half is the best positioning of the view for the stomach model)
\r
61 .float cameraeffect_current, cameraeffect_target;
\r
62 void Vore_CameraEffect_Set(entity e)
\r
64 e.cameraeffect_current = 1;
\r
65 e.cameraeffect_target = 2;
\r
67 void Vore_CameraEffect_Apply()
\r
69 if(self.eater.classname != "player")
\r
72 if(self.cvar_cl_vore_cameraspeed)
\r
75 step = self.cvar_cl_vore_cameraspeed * frametime;
\r
77 // not sure if these maths are good, as the effect should be smoother
\r
78 if(self.cameraeffect_current >= self.cameraeffect_target + step)
\r
79 self.cameraeffect_current -= step;
\r
80 else if(self.cameraeffect_current <= self.cameraeffect_target - step)
\r
81 self.cameraeffect_current += step;
\r
84 self.cameraeffect_current = self.cameraeffect_target;
\r
86 self.view_ofs_z = self.vore_oldview_ofs_z / self.cameraeffect_current;
\r
89 void Vore_Weight_apply(entity e)
\r
91 // apply stomach weight that makes you heavier the more you eat
\r
92 // slowing the player is applied in cl_physics.qc
\r
93 if(e.stomach_load != e.vore_oldstomachload)
\r
94 e.gravity += 1 + (e.stomach_load * cvar("g_balance_vore_weight_gravity") - e.vore_oldstomachload);
\r
96 e.gravity = 0.00001; // 0 becomes 1 for .gravity, so do this to allow 0 gravity
\r
97 e.vore_oldstomachload = e.stomach_load;
\r
100 void Vore_Swallow(entity e)
\r
102 // this player is beening swallowed by another player, apply the proper changes
\r
103 e.vore_oldmovetype = e.movetype;
\r
104 e.vore_oldsolid = e.solid;
\r
105 e.vore_oldview_ofs_z = e.view_ofs_z;
\r
107 setorigin(e, e.eater.origin);
\r
108 e.velocity = '0 0 0';
\r
109 e.movetype = MOVETYPE_FOLLOW;
\r
110 e.solid = SOLID_NOT;
\r
111 e.alpha = -1; // best way of hiding / showing the eaten player
\r
112 e.aiment = e.eater; // follow the predator. Is automatically unset
\r
114 Vore_CameraEffect_Set(e);
\r
116 // drop keys (KH) and flags (CTF) when we get swallowed
\r
117 kh_Key_DropAll(e, FALSE);
\r
119 DropFlag(e.flagcarried, world, e.eater);
\r
121 if(stov(cvar_string("g_vore_regurgitatecolor_released")))
\r
122 e.colormod = stov(cvar_string("g_vore_regurgitatecolor_released"));
\r
124 PlayerSound(e.eater, playersound_swallow, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
125 setanim(e.eater, e.eater.anim_pain1, FALSE, TRUE, TRUE); // looks good for swallowing \ regurgitating
\r
126 e.eater.stomach_load += 1;
\r
127 e.eater.regurgitate_prepare = 0;
\r
128 Vore_Weight_apply(e.eater);
\r
130 e.system_delay = e.eater.system_delay = time + system_delay_time;
\r
133 void Vore_Regurgitate(entity e)
\r
135 // this player is being released from their predator, apply the proper changes
\r
136 e.movetype = e.vore_oldmovetype;
\r
137 if(e.health > 0) // leave SOLID_NOT for dead bodies
\r
138 e.solid = e.vore_oldsolid;
\r
139 e.view_ofs_z = e.vore_oldview_ofs_z;
\r
140 e.alpha = default_player_alpha; // best way of hiding / showing the eaten player
\r
143 local vector oldforward, oldright, oldup;
\r
144 oldforward = v_forward;
\r
145 oldright = v_right;
\r
147 makevectors(e.eater.v_angle);
\r
148 e.velocity = v_forward * cvar("g_balance_vore_regurgitate_force");
\r
149 e.eater.velocity += -v_forward * cvar("g_balance_vore_regurgitate_eaterforce");
\r
150 v_forward = oldforward;
\r
151 v_right = oldright;
\r
154 PlayerSound(e.eater, playersound_regurgitate, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
155 setanim(e.eater, e.eater.anim_pain1, FALSE, TRUE, TRUE); // looks good for swallowing \ regurgitating
\r
156 pointparticles(particleeffectnum("regurgitate"), e.eater.origin, '0 0 0', 1);
\r
157 e.eater.stomach_load -= 1;
\r
158 e.eater.regurgitate_prepare = 0;
\r
159 e.eater.swallow_delay = time + cvar("g_balance_vore_swallow_delay");
\r
160 Vore_Weight_apply(e.eater);
\r
162 e.system_delay = e.eater.system_delay = time + system_delay_time;
\r
166 void Vore_Gurglesound();
\r
167 void Vore_Disconnect()
\r
169 // frees prey from their predators when someone disconnects or goes spectating
\r
171 // prey disconnects or goes spectating while inside someone's belly:
\r
172 if(self.eater.classname == "player")
\r
174 self.view_ofs_z = self.vore_oldview_ofs_z;
\r
175 self.eater.stomach_load -= 1;
\r
176 Vore_Weight_apply(self.eater);
\r
177 self.eater = world;
\r
180 // pred disconnects or goes spectating with players in their belly:
\r
181 else if(self.stomach_load > 0)
\r
184 FOR_EACH_PLAYER(head)
\r
186 if(head.eater == self)
\r
187 Vore_Regurgitate(head);
\r
189 Vore_Gurglesound(); // stop the gurgling sound
\r
193 .float digestion_step;
\r
196 // apply digestion to prey
\r
197 if(time > self.eater.digestion_step + steptime)
\r
199 Damage(self, self.eater, self.eater, cvar("g_balance_vore_digestion_damage"), DEATH_DIGESTION, self.origin, '0 0 0');
\r
200 if(cvar("g_balance_vore_digestion_vampire") && self.eater.health < cvar("g_balance_vore_digestion_vampire_stable"))
\r
201 self.eater.health += cvar("g_balance_vore_digestion_vampire");
\r
203 if (self.eater.digestsound_finished < time)
\r
205 self.eater.digestsound_finished = time + 0.5;
\r
206 PlayerSound (self.eater, playersound_digest, CHAN_PLAYER, VOICETYPE_PLAYERSOUND);
\r
208 self.eater.digestion_step = time;
\r
211 if(self.health <= 0)
\r
212 if(stov(cvar_string("g_vore_regurgitatecolor_digested")))
\r
213 self.colormod = stov(cvar_string("g_vore_regurgitatecolor_digested"));
\r
216 .float teamheal_step;
\r
217 void Vore_Teamheal()
\r
219 if(cvar("g_balance_vore_teamheal") && self.health < cvar("g_balance_vore_teamheal_stable"))
\r
220 if(time > self.teamheal_step + steptime)
\r
222 self.health += cvar("g_balance_vore_teamheal");
\r
223 self.teamheal_step = time;
\r
227 .float stomachkick_delay;
\r
228 void Vore_StomachKick()
\r
230 // allows prey to kick the predator's stomach and do some damage / attempt to escape, or bring the predator's digestion upon their self when there's no other option
\r
231 if(self.eater.classname != "player")
\r
234 // kick the predator's stomach and do damage, or escape if we are lucky
\r
235 if(self.BUTTON_ATCK)
\r
236 if(time > self.stomachkick_delay)
\r
239 damage = ceil(random() * (cvar("g_balance_vore_kick_damage_max") - cvar("g_balance_vore_kick_damage_min")) + cvar("g_balance_vore_kick_damage_min"));
\r
240 Damage(self.eater, self, self, damage, DEATH_STOMACHKICK, self.eater.origin, '0 0 0');
\r
241 sound(self.eater, CHAN_PROJECTILE, "weapons/stomachkick.ogg", VOL_BASE, ATTN_NORM);
\r
243 if(cvar("g_balance_vore_kick_escapeprobability") >= random())
\r
244 Vore_Regurgitate(self);
\r
246 self.stomachkick_delay = time + cvar("g_balance_vore_kick_delay");
\r
250 .float gurglesound_finished, gurglesound_oldstomachload;
\r
251 void Vore_Gurglesound()
\r
253 if(time > self.gurglesound_finished || self.gurglesound_oldstomachload != self.stomach_load)
\r
255 GlobalSound(self.playersound_gurgle, CHAN_TRIGGER, VOICETYPE_GURGLE);
\r
257 self.gurglesound_finished = time + 11; // yes, hard coded sound length. I know it's bad but what can I do?
\r
258 self.gurglesound_oldstomachload = self.stomach_load;
\r
264 // if we are free, show our stomach load on the HUD. Otherwise, show the predator's
\r
265 if(self.eater.classname == "player")
\r
267 self.stat_stomachload = self.eater.stomach_load;
\r
268 self.stat_digesting = self.eater.digesting;
\r
269 self.stat_eaten = num_for_edict(self.eater);
\r
273 self.stat_stomachload = self.stomach_load;
\r
274 self.stat_digesting = self.digesting;
\r
275 self.stat_eaten = 0;
\r
278 // skip the vore system under some circumstances
\r
279 if(time < game_starttime)
\r
284 if(self.spectatee_status)
\r
286 if(time < self.system_delay)
\r
289 // --------------------------------
\r
290 // Code that addresses predators:
\r
291 // --------------------------------
\r
294 prey = Swallow_distance_check();
\r
296 // attempt to swallow our new prey if there's any in range
\r
297 if(self.BUTTON_ATCK && !self.BUTTON_REGURGITATE && self.swallow_delay < time)
\r
298 if(Swallow_condition_check(prey))
\r
301 Vore_Swallow(prey);
\r
302 self.swallow_delay = time + cvar("g_balance_vore_swallow_delay");
\r
304 if(self.team == prey.team && teamplay)
\r
305 centerprint(self, "You have swallowed a team mate, use caution!");
\r
307 // block firing for a small amount of time when voring, or we'll be firing the next frame after we swallow
\r
308 self.weapon_delay = time + 0.25;
\r
311 // start / stop digestion on command, if the player has someone in their stomach
\r
312 if(self.BUTTON_DIGEST)
\r
314 if(self.stomach_load)
\r
316 if(time > self.digest_button_delay)
\r
318 self.digesting = !self.digesting;
\r
319 self.digest_button_delay = time + button_delay;
\r
322 else if(time > self.complain_swallow)
\r
324 play2(self, "weapons/unavailable.wav");
\r
325 sprint(self, "There is nothing to digest\n");
\r
326 self.complain_swallow = time + complain_delay;
\r
329 if(!self.stomach_load)
\r
330 self.digesting = FALSE;
\r
332 // release players from this player's stomach on command
\r
333 if(self.BUTTON_REGURGITATE)
\r
335 if(self.stomach_load)
\r
337 if(time > self.regurgitate_button_delay)
\r
339 self.regurgitate_prepare = time + cvar("g_balance_vore_regurgitate_delay");
\r
340 PlayerSound(self, playersound_regurgitate_prepare, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
341 self.regurgitate_button_delay = time + button_delay;
\r
344 else if(time > self.complain_swallow)
\r
346 play2(self, "weapons/unavailable.wav");
\r
347 sprint(self, "There is nothing to regurgitate\n");
\r
348 self.complain_swallow = time + complain_delay;
\r
352 if(cvar("g_vore_gurglesound"))
\r
353 Vore_Gurglesound();
\r
355 // --------------------------------
\r
356 // Code that addresses the prey:
\r
357 // --------------------------------
\r
359 if(self.eater.classname != "player")
\r
362 if(self.eater.deadflag || self.deadflag)
\r
363 Vore_Regurgitate(self);
\r
364 else if(self.eater.eater.classname == "player") // don't allow a player inside a player inside another player :)
\r
365 Vore_Regurgitate(self);
\r
366 else if(vlen(self.eater.velocity) > cvar("g_balance_vore_regurgitate_velocitylimit"))
\r
367 Vore_Regurgitate(self);
\r
369 // apply delayed regurgitating
\r
370 if(self.eater.regurgitate_prepare && time > self.eater.regurgitate_prepare)
\r
372 self.eater.regurgitate_prepare = 0;
\r
373 self.eater.complain_swallow = time + complain_delay;
\r
374 Vore_Regurgitate(self);
\r
377 if(self.eater.digesting == TRUE)
\r
379 if(teams_matter && self.team == self.eater.team)
\r
382 Vore_StomachKick();
\r
384 Vore_CameraEffect_Apply();
\r