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.eater.team == e.team && teamplay)
\r
128 centerprint(e.eater, "^3You have swallowed a team mate, use caution!");
\r
130 PlayerSound(e.eater, playersound_swallow, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
131 setanim(e.eater, e.eater.anim_pain1, FALSE, TRUE, TRUE); // looks good for swallowing / regurgitating
\r
132 e.eater.stomach_load += 1;
\r
133 e.eater.regurgitate_prepare = 0;
\r
134 Vore_Weight_apply(e.eater);
\r
136 // block firing for a small amount of time when voring, or we'll be firing the next frame after we swallow
\r
137 e.eater.weapon_delay = time + button_delay;
\r
138 e.eater.swallow_delay = time + cvar("g_balance_vore_swallow_delay");
\r
139 e.system_delay = e.eater.system_delay = time + system_delay_time;
\r
142 void Vore_Regurgitate(entity e)
\r
144 // this player is being released from their predator, apply the proper changes
\r
145 e.movetype = e.vore_oldmovetype;
\r
146 if(e.health > 0) // leave SOLID_NOT for dead bodies
\r
147 e.solid = e.vore_oldsolid;
\r
148 e.view_ofs_z = e.vore_oldview_ofs_z;
\r
149 e.alpha = default_player_alpha; // best way of hiding / showing the eaten player
\r
152 local vector oldforward, oldright, oldup;
\r
153 oldforward = v_forward;
\r
154 oldright = v_right;
\r
156 makevectors(e.eater.v_angle);
\r
157 e.velocity = v_forward * cvar("g_balance_vore_regurgitate_force");
\r
158 e.eater.velocity += -v_forward * cvar("g_balance_vore_regurgitate_eaterforce");
\r
159 v_forward = oldforward;
\r
160 v_right = oldright;
\r
163 e.pusher = e.eater; // so we can frag players by regurgitating them in deadly pits
\r
164 e.pushltime = time + cvar("g_maxpushtime");
\r
166 PlayerSound(e.eater, playersound_regurgitate, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
167 setanim(e.eater, e.eater.anim_pain1, FALSE, TRUE, TRUE); // looks good for swallowing / regurgitating
\r
168 pointparticles(particleeffectnum("regurgitate"), e.eater.origin, '0 0 0', 1);
\r
169 e.eater.stomach_load -= 1;
\r
170 e.eater.regurgitate_prepare = 0;
\r
171 e.eater.swallow_delay = time + cvar("g_balance_vore_swallow_delay");
\r
172 Vore_Weight_apply(e.eater);
\r
174 e.system_delay = e.eater.system_delay = time + system_delay_time;
\r
178 void Vore_Gurglesound();
\r
179 void Vore_Disconnect()
\r
181 // frees prey from their predators when someone disconnects or goes spectating
\r
183 // prey disconnects or goes spectating while inside someone's belly:
\r
184 if(self.eater.classname == "player")
\r
186 self.view_ofs_z = self.vore_oldview_ofs_z;
\r
187 self.eater.stomach_load -= 1;
\r
188 Vore_Weight_apply(self.eater);
\r
189 self.eater = world;
\r
192 // pred disconnects or goes spectating with players in their belly:
\r
193 else if(self.stomach_load > 0)
\r
196 FOR_EACH_PLAYER(head)
\r
198 if(head.eater == self)
\r
199 Vore_Regurgitate(head);
\r
201 Vore_Gurglesound(); // stop the gurgling sound
\r
205 .float digestion_step;
\r
208 // apply digestion to prey
\r
209 if(time > self.eater.digestion_step + steptime)
\r
211 Damage(self, self.eater, self.eater, cvar("g_balance_vore_digestion_damage"), DEATH_DIGESTION, self.origin, '0 0 0');
\r
212 if(cvar("g_balance_vore_digestion_vampire") && self.eater.health < cvar("g_balance_vore_digestion_vampire_stable"))
\r
213 self.eater.health += cvar("g_balance_vore_digestion_vampire");
\r
215 if (self.eater.digestsound_finished < time)
\r
217 self.eater.digestsound_finished = time + 0.5;
\r
218 PlayerSound (self.eater, playersound_digest, CHAN_PLAYER, VOICETYPE_PLAYERSOUND);
\r
220 self.eater.digestion_step = time;
\r
223 if(self.health <= 0)
\r
224 if(stov(cvar_string("g_vore_regurgitatecolor_digested")))
\r
225 self.colormod = stov(cvar_string("g_vore_regurgitatecolor_digested"));
\r
228 .float teamheal_step;
\r
229 void Vore_Teamheal()
\r
231 if(cvar("g_balance_vore_teamheal") && self.health < cvar("g_balance_vore_teamheal_stable"))
\r
232 if(time > self.teamheal_step + steptime)
\r
234 self.health += cvar("g_balance_vore_teamheal");
\r
235 self.teamheal_step = time;
\r
239 .float stomachkick_delay;
\r
240 void Vore_StomachKick()
\r
242 // allows prey to kick the predator's stomach and do some damage or attempt to escape
\r
243 if(self.eater.classname != "player")
\r
246 if(time > self.stomachkick_delay)
\r
249 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
250 Damage(self.eater, self, self, damage, DEATH_STOMACHKICK, self.eater.origin, '0 0 0');
\r
251 sound(self.eater, CHAN_PROJECTILE, "weapons/stomachkick.ogg", VOL_BASE, ATTN_NORM);
\r
253 if(cvar("g_balance_vore_kick_escapeprobability") >= random())
\r
254 Vore_Regurgitate(self);
\r
256 self.stomachkick_delay = time + cvar("g_balance_vore_kick_delay");
\r
260 .float gurglesound_finished, gurglesound_oldstomachload;
\r
261 void Vore_Gurglesound()
\r
263 if(time > self.gurglesound_finished || self.gurglesound_oldstomachload != self.stomach_load)
\r
265 GlobalSound(self.playersound_gurgle, CHAN_TRIGGER, VOICETYPE_GURGLE);
\r
267 self.gurglesound_finished = time + 11; // yes, hard coded sound length. I know it's bad but what can I do?
\r
268 self.gurglesound_oldstomachload = self.stomach_load;
\r
274 // if we are free, show our stomach load on the HUD. Otherwise, show the predator's
\r
275 if(self.eater.classname == "player")
\r
277 self.stat_stomachload = self.eater.stomach_load;
\r
278 self.stat_digesting = self.eater.digesting;
\r
279 self.stat_eaten = num_for_edict(self.eater);
\r
283 self.stat_stomachload = self.stomach_load;
\r
284 self.stat_digesting = self.digesting;
\r
285 self.stat_eaten = 0;
\r
288 // skip the vore system under some circumstances
\r
289 if(time < game_starttime)
\r
294 if(self.spectatee_status)
\r
296 if(time < self.system_delay)
\r
299 // --------------------------------
\r
300 // Code that addresses predators:
\r
301 // --------------------------------
\r
304 prey = Swallow_distance_check();
\r
306 // attempt to swallow our new prey if there's any in range
\r
307 if(self.BUTTON_ATCK && !self.BUTTON_REGURGITATE && self.swallow_delay < time)
\r
308 if(Swallow_condition_check(prey))
\r
309 Vore_Swallow(prey);
\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_VOICE, 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
366 entity targeteater, oldself;
\r
367 targeteater = self.eater.eater;
\r
369 Vore_Regurgitate(self);
\r
370 if(random() < cvar("g_vore_stealprey"))
\r
371 if(Swallow_condition_check(self))
\r
374 self = targeteater;
\r
375 Vore_Swallow(oldself);
\r
379 else if(vlen(self.eater.velocity) > cvar("g_balance_vore_regurgitate_velocitylimit"))
\r
380 Vore_Regurgitate(self);
\r
382 // apply delayed regurgitating
\r
383 if(self.eater.regurgitate_prepare && time > self.eater.regurgitate_prepare)
\r
385 self.eater.regurgitate_prepare = 0;
\r
386 self.eater.complain_swallow = time + complain_delay;
\r
387 Vore_Regurgitate(self);
\r
390 if(self.eater.digesting == TRUE)
\r
392 if(teams_matter && self.team == self.eater.team)
\r
395 if(self.BUTTON_ATCK)
\r
396 Vore_StomachKick();
\r
398 Vore_CameraEffect_Apply();
\r