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
102 void Vore_Swallow(entity e)
\r
104 // this player is beening swallowed by another player, apply the proper changes
\r
105 e.vore_oldmovetype = e.movetype;
\r
106 e.vore_oldsolid = e.solid;
\r
107 e.vore_oldview_ofs_z = e.view_ofs_z;
\r
110 setorigin(e, e.eater.origin);
\r
111 e.velocity = '0 0 0';
\r
112 e.movetype = MOVETYPE_FOLLOW;
\r
113 e.solid = SOLID_NOT;
\r
114 e.alpha = -1; // best way of hiding / showing the eaten player
\r
115 e.aiment = e.eater; // follow the predator. Is automatically unset
\r
117 // drop keys (KH) and flags (CTF) when we get swallowed
\r
118 kh_Key_DropAll(e, FALSE);
\r
120 DropFlag(e.flagcarried, world, e.eater);
\r
122 Vore_CameraEffect_Set(e);
\r
124 if(stov(cvar_string("g_vore_regurgitatecolor_released")))
\r
125 e.colormod = stov(cvar_string("g_vore_regurgitatecolor_released"));
\r
127 if(e.team == e.eater.team && teamplay)
\r
129 centerprint(e, "^3You have been swallowed by a team mate, don't kick!");
\r
130 centerprint(e.eater, "^3You have swallowed a team mate, use caution!");
\r
133 PlayerSound(e.eater, playersound_swallow, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
134 setanim(e.eater, e.eater.anim_pain1, FALSE, TRUE, TRUE); // looks good for swallowing / regurgitating
\r
135 e.eater.stomach_load += 1;
\r
136 e.eater.regurgitate_prepare = 0;
\r
137 Vore_Weight_apply(e.eater);
\r
139 // block firing for a small amount of time when voring, or we'll be firing the next frame after we swallow
\r
140 e.eater.weapon_delay = time + button_delay;
\r
141 e.eater.swallow_delay = time + cvar("g_balance_vore_swallow_delay");
\r
142 e.system_delay = e.eater.system_delay = time + system_delay_time;
\r
145 void Vore_Regurgitate(entity e)
\r
147 // this player is being released from their predator, apply the proper changes
\r
148 e.movetype = e.vore_oldmovetype;
\r
149 if(e.health > 0) // leave SOLID_NOT for dead bodies
\r
150 e.solid = e.vore_oldsolid;
\r
151 e.view_ofs_z = e.vore_oldview_ofs_z;
\r
152 e.alpha = default_player_alpha; // best way of hiding / showing the eaten player
\r
155 local vector oldforward, oldright, oldup;
\r
156 oldforward = v_forward;
\r
157 oldright = v_right;
\r
159 makevectors(e.eater.v_angle);
\r
160 e.velocity = v_forward * cvar("g_balance_vore_regurgitate_force");
\r
161 e.eater.velocity += -v_forward * cvar("g_balance_vore_regurgitate_eaterforce");
\r
162 v_forward = oldforward;
\r
163 v_right = oldright;
\r
166 e.pusher = e.eater; // so we can frag players by regurgitating them in deadly pits
\r
167 e.pushltime = time + cvar("g_maxpushtime");
\r
169 PlayerSound(e.eater, playersound_regurgitate, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
170 setanim(e.eater, e.eater.anim_pain1, FALSE, TRUE, TRUE); // looks good for swallowing / regurgitating
\r
171 pointparticles(particleeffectnum("regurgitate"), e.eater.origin, '0 0 0', 1);
\r
172 e.eater.stomach_load -= 1;
\r
173 e.eater.regurgitate_prepare = 0;
\r
174 e.eater.swallow_delay = time + cvar("g_balance_vore_swallow_delay");
\r
175 Vore_Weight_apply(e.eater);
\r
177 e.system_delay = e.eater.system_delay = time + system_delay_time;
\r
181 void Vore_Gurglesound();
\r
182 void Vore_Disconnect()
\r
184 // frees prey from their predators when someone disconnects or goes spectating
\r
186 // prey disconnects or goes spectating while inside someone's belly:
\r
187 if(self.eater.classname == "player")
\r
189 self.view_ofs_z = self.vore_oldview_ofs_z;
\r
190 self.eater.stomach_load -= 1;
\r
191 Vore_Weight_apply(self.eater);
\r
192 self.eater = world;
\r
195 // pred disconnects or goes spectating with players in their belly:
\r
196 else if(self.stomach_load > 0)
\r
199 FOR_EACH_PLAYER(head)
\r
201 if(head.eater == self)
\r
202 Vore_Regurgitate(head);
\r
204 Vore_Gurglesound(); // stop the gurgling sound
\r
208 .float digestion_step;
\r
211 // apply digestion to prey
\r
212 if(time > self.eater.digestion_step + steptime)
\r
214 Damage(self, self.eater, self.eater, cvar("g_balance_vore_digestion_damage"), DEATH_DIGESTION, self.origin, '0 0 0');
\r
215 if(cvar("g_balance_vore_digestion_vampire") && self.eater.health < cvar("g_balance_vore_digestion_vampire_stable"))
\r
216 self.eater.health += cvar("g_balance_vore_digestion_vampire");
\r
218 if (self.eater.digestsound_finished < time)
\r
220 self.eater.digestsound_finished = time + 0.5;
\r
221 PlayerSound (self.eater, playersound_digest, CHAN_PLAYER, VOICETYPE_PLAYERSOUND);
\r
223 self.eater.digestion_step = time;
\r
226 if(self.health <= 0)
\r
227 if(stov(cvar_string("g_vore_regurgitatecolor_digested")))
\r
228 self.colormod = stov(cvar_string("g_vore_regurgitatecolor_digested"));
\r
231 .float teamheal_step;
\r
232 void Vore_Teamheal()
\r
234 if(cvar("g_balance_vore_teamheal") && self.health < cvar("g_balance_vore_teamheal_stable"))
\r
235 if(time > self.teamheal_step + steptime)
\r
237 self.health += cvar("g_balance_vore_teamheal");
\r
238 self.teamheal_step = time;
\r
242 .float stomachkick_delay;
\r
243 void Vore_StomachKick()
\r
245 // allows prey to kick the predator's stomach and do some damage or attempt to escape
\r
246 if(self.eater.classname != "player")
\r
249 if(time > self.stomachkick_delay)
\r
252 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
253 Damage(self.eater, self, self, damage, DEATH_STOMACHKICK, self.eater.origin, '0 0 0');
\r
254 sound(self.eater, CHAN_PROJECTILE, "weapons/stomachkick.ogg", VOL_BASE, ATTN_NORM);
\r
256 if(cvar("g_balance_vore_kick_escapeprobability") >= random())
\r
257 Vore_Regurgitate(self);
\r
259 self.stomachkick_delay = time + cvar("g_balance_vore_kick_delay");
\r
263 .float gurglesound_finished, gurglesound_oldstomachload;
\r
264 void Vore_Gurglesound()
\r
266 if(time > self.gurglesound_finished || self.gurglesound_oldstomachload != self.stomach_load)
\r
268 GlobalSound(self.playersound_gurgle, CHAN_TRIGGER, VOICETYPE_GURGLE);
\r
270 self.gurglesound_finished = time + 11; // yes, hard coded sound length. I know it's bad but what can I do?
\r
271 self.gurglesound_oldstomachload = self.stomach_load;
\r
277 // if we are free, show our stomach load on the HUD. Otherwise, show the predator's
\r
278 if(self.eater.classname == "player")
\r
280 self.stat_stomachload = self.eater.stomach_load;
\r
281 self.stat_digesting = self.eater.digesting;
\r
282 self.stat_eaten = num_for_edict(self.eater);
\r
286 self.stat_stomachload = self.stomach_load;
\r
287 self.stat_digesting = self.digesting;
\r
288 self.stat_eaten = 0;
\r
291 // skip the vore system under some circumstances
\r
292 if(time < game_starttime)
\r
297 if(self.spectatee_status)
\r
299 if(time < self.system_delay)
\r
302 // --------------------------------
\r
303 // Code that addresses predators:
\r
304 // --------------------------------
\r
307 prey = Swallow_distance_check();
\r
309 // attempt to swallow our new prey if there's any in range
\r
310 if(self.BUTTON_ATCK && !self.BUTTON_REGURGITATE && self.swallow_delay < time)
\r
311 if(Swallow_condition_check(prey))
\r
312 Vore_Swallow(prey);
\r
314 // start / stop digestion on command, if the player has someone in their stomach
\r
315 if(self.BUTTON_DIGEST)
\r
317 if(self.stomach_load)
\r
319 if(time > self.digest_button_delay)
\r
321 self.digesting = !self.digesting;
\r
322 self.digest_button_delay = time + button_delay;
\r
325 else if(time > self.complain_swallow)
\r
327 play2(self, "weapons/unavailable.wav");
\r
328 sprint(self, "There is nothing to digest\n");
\r
329 self.complain_swallow = time + complain_delay;
\r
332 if(!self.stomach_load)
\r
333 self.digesting = FALSE;
\r
335 // release players from this player's stomach on command
\r
336 if(self.BUTTON_REGURGITATE)
\r
338 if(self.stomach_load)
\r
340 if(time > self.regurgitate_button_delay)
\r
342 self.regurgitate_prepare = time + cvar("g_balance_vore_regurgitate_delay");
\r
343 PlayerSound(self, playersound_regurgitate_prepare, CHAN_VOICE, VOICETYPE_PLAYERSOUND);
\r
344 self.regurgitate_button_delay = time + button_delay;
\r
347 else if(time > self.complain_swallow)
\r
349 play2(self, "weapons/unavailable.wav");
\r
350 sprint(self, "There is nothing to regurgitate\n");
\r
351 self.complain_swallow = time + complain_delay;
\r
355 if(cvar("g_vore_gurglesound"))
\r
356 Vore_Gurglesound();
\r
358 // --------------------------------
\r
359 // Code that addresses the prey:
\r
360 // --------------------------------
\r
362 if(self.eater.classname != "player")
\r
365 if(self.eater.deadflag || self.deadflag)
\r
366 Vore_Regurgitate(self);
\r
367 else if(self.eater.eater.classname == "player") // don't allow a player inside a player inside another player :)
\r
369 entity targeteater, oldself;
\r
370 targeteater = self.eater.eater;
\r
372 Vore_Regurgitate(self);
\r
373 if(random() < cvar("g_vore_stealprey"))
\r
374 if(Swallow_condition_check(self))
\r
377 self = targeteater;
\r
378 Vore_Swallow(oldself);
\r
382 else if(vlen(self.eater.velocity) > cvar("g_balance_vore_regurgitate_velocitylimit"))
\r
383 Vore_Regurgitate(self);
\r
385 // apply delayed regurgitating
\r
386 if(self.eater.regurgitate_prepare && time > self.eater.regurgitate_prepare)
\r
388 self.eater.regurgitate_prepare = 0;
\r
389 self.eater.complain_swallow = time + complain_delay;
\r
390 Vore_Regurgitate(self);
\r
393 if(self.eater.digesting == TRUE)
\r
395 if(teams_matter && self.team == self.eater.team)
\r
398 if(self.BUTTON_ATCK)
\r
399 Vore_StomachKick();
\r
401 Vore_CameraEffect_Apply();
\r