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 if(self.cameraeffect_current >= self.cameraeffect_target + step)
\r
78 self.cameraeffect_current -= step;
\r
79 else if(self.cameraeffect_current <= self.cameraeffect_target - step)
\r
80 self.cameraeffect_current += step;
\r
83 self.cameraeffect_current = self.cameraeffect_target;
\r
85 self.view_ofs_z = self.vore_oldview_ofs_z / self.cameraeffect_current;
\r
88 void Vore_Weight_apply(entity e)
\r
90 // apply stomach weight that makes you heavier the more you eat
\r
91 // slowing the player is applied in cl_physics.qc
\r
92 if(e.stomach_load != e.vore_oldstomachload)
\r
93 e.gravity += 1 + (e.stomach_load * cvar("g_balance_vore_weight_gravity") - e.vore_oldstomachload);
\r
95 e.gravity = 0.00001; // 0 becomes 1 for .gravity, so do this to allow 0 gravity
\r
96 e.vore_oldstomachload = e.stomach_load;
\r
99 void Vore_Swallow(entity e)
\r
101 // this player is beening swallowed by another player, apply the proper changes
\r
102 e.vore_oldmovetype = e.movetype;
\r
103 e.vore_oldsolid = e.solid;
\r
104 e.vore_oldview_ofs_z = e.view_ofs_z;
\r
106 setorigin(e, e.eater.origin);
\r
107 e.velocity = '0 0 0';
\r
108 e.movetype = MOVETYPE_FOLLOW;
\r
109 e.solid = SOLID_NOT;
\r
110 e.alpha = -1; // best way of hiding / showing the eaten player
\r
111 e.aiment = e.eater; // follow the predator. Is automatically unset
\r
113 /*e.cameraeffect_current = e.view_ofs_z * 2;
\r
114 e.cameraeffect_target = e.view_ofs_z / 2; // best positioning for the stomach model*/
\r
116 Vore_CameraEffect_Set(e);
\r
118 // drop keys (KH) and flags (CTF) when we get swallowed
\r
119 kh_Key_DropAll(e, FALSE);
\r
121 DropFlag(e.flagcarried, world, e.eater);
\r
123 if(stov(cvar_string("g_vore_regurgitatecolor_released")))
\r
124 e.colormod = stov(cvar_string("g_vore_regurgitatecolor_released"));
\r
126 PlayerSound(e.eater, playersound_swallow, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
127 setanim(e.eater, e.eater.anim_pain1, FALSE, TRUE, TRUE); // looks good for swallowing \ regurgitating
\r
128 e.eater.stomach_load += 1;
\r
129 e.eater.regurgitate_prepare = 0;
\r
130 Vore_Weight_apply(e.eater);
\r
132 e.system_delay = e.eater.system_delay = time + system_delay_time;
\r
135 void Vore_Regurgitate(entity e)
\r
137 // this player is being released from their predator, apply the proper changes
\r
138 e.movetype = e.vore_oldmovetype;
\r
139 if(e.health > 0) // leave SOLID_NOT for dead bodies
\r
140 e.solid = e.vore_oldsolid;
\r
141 e.view_ofs_z = e.vore_oldview_ofs_z;
\r
142 e.alpha = default_player_alpha; // best way of hiding / showing the eaten player
\r
144 //e.view_ofs_z *= 2; // best positioning for the stomach model
\r
147 local vector oldforward, oldright, oldup;
\r
148 oldforward = v_forward;
\r
149 oldright = v_right;
\r
151 makevectors(e.eater.v_angle);
\r
152 e.velocity = v_forward * cvar("g_balance_vore_regurgitate_force");
\r
153 e.eater.velocity += -v_forward * cvar("g_balance_vore_regurgitate_eaterforce");
\r
154 v_forward = oldforward;
\r
155 v_right = oldright;
\r
158 PlayerSound(e.eater, playersound_regurgitate, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
159 setanim(e.eater, e.eater.anim_pain1, FALSE, TRUE, TRUE); // looks good for swallowing \ regurgitating
\r
160 pointparticles(particleeffectnum("regurgitate"), e.eater.origin, '0 0 0', 1);
\r
161 e.eater.stomach_load -= 1;
\r
162 e.eater.regurgitate_prepare = 0;
\r
163 e.eater.swallow_delay = time + cvar("g_balance_vore_swallow_delay");
\r
164 Vore_Weight_apply(e.eater);
\r
166 e.system_delay = e.eater.system_delay = time + system_delay_time;
\r
170 void Vore_Gurglesound();
\r
171 void Vore_Disconnect()
\r
173 // frees prey from their predators when someone disconnects or goes spectating
\r
175 // prey disconnects or goes spectating while inside someone's belly:
\r
176 if(self.eater.classname == "player")
\r
178 self.view_ofs_z += 25;
\r
179 self.eater.stomach_load -= 1;
\r
180 Vore_Weight_apply(self.eater);
\r
181 self.eater = world;
\r
184 // pred disconnects or goes spectating with players in their belly:
\r
185 else if(self.stomach_load > 0)
\r
188 FOR_EACH_PLAYER(head)
\r
190 if(head.eater == self)
\r
191 Vore_Regurgitate(head);
\r
193 Vore_Gurglesound(); // stop the gurgling sound
\r
197 .float digestion_step;
\r
200 // apply digestion to prey
\r
201 if(time > self.eater.digestion_step + steptime)
\r
203 Damage(self, self.eater, self.eater, cvar("g_balance_vore_digestion_damage"), DEATH_DIGESTION, self.origin, '0 0 0');
\r
204 if(cvar("g_balance_vore_digestion_vampire") && self.eater.health < cvar("g_balance_vore_digestion_vampire_stable"))
\r
205 self.eater.health += cvar("g_balance_vore_digestion_vampire");
\r
207 if (self.eater.digestsound_finished < time)
\r
209 self.eater.digestsound_finished = time + 0.5;
\r
210 PlayerSound (self.eater, playersound_digest, CHAN_PLAYER, VOICETYPE_PLAYERSOUND);
\r
212 self.eater.digestion_step = time;
\r
215 if(self.health <= 0)
\r
216 if(stov(cvar_string("g_vore_regurgitatecolor_digested")))
\r
217 self.colormod = stov(cvar_string("g_vore_regurgitatecolor_digested"));
\r
220 .float teamheal_step;
\r
221 void Vore_Teamheal()
\r
223 if(cvar("g_balance_vore_teamheal") && self.health < cvar("g_balance_vore_teamheal_stable"))
\r
224 if(time > self.teamheal_step + steptime)
\r
226 self.health += cvar("g_balance_vore_teamheal");
\r
227 self.teamheal_step = time;
\r
231 .float stomachkick_delay;
\r
232 void Vore_StomachKick()
\r
234 // 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
235 if(self.eater.classname != "player")
\r
238 // kick the predator's stomach and do damage, or escape if we are lucky
\r
239 if(self.BUTTON_ATCK)
\r
240 if(time > self.stomachkick_delay)
\r
243 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
244 Damage(self.eater, self, self, damage, DEATH_STOMACHKICK, self.eater.origin, '0 0 0');
\r
245 sound(self.eater, CHAN_PROJECTILE, "weapons/stomachkick.ogg", VOL_BASE, ATTN_NORM);
\r
247 if(cvar("g_balance_vore_kick_escapeprobability") >= random())
\r
248 Vore_Regurgitate(self);
\r
250 self.stomachkick_delay = time + cvar("g_balance_vore_kick_delay");
\r
253 // start the predator's digestion
\r
254 if(self.BUTTON_ATCK2)
\r
256 centerprint(self.eater, strcat(self.netname, " has triggered your digestion"));
\r
257 self.eater.digesting = TRUE;
\r
261 .float gurglesound_finished, gurglesound_oldstomachload;
\r
262 void Vore_Gurglesound()
\r
264 if(time > self.gurglesound_finished || self.gurglesound_oldstomachload != self.stomach_load)
\r
266 GlobalSound(self.playersound_gurgle, CHAN_TRIGGER, VOICETYPE_GURGLE);
\r
268 self.gurglesound_finished = time + 11; // yes, hard coded sound length. I know it's bad but what can I do?
\r
269 self.gurglesound_oldstomachload = self.stomach_load;
\r
275 // if we are free, show our stomach load on the HUD. Otherwise, show the predator's
\r
276 if(self.eater.classname == "player")
\r
278 self.stat_stomachload = self.eater.stomach_load;
\r
279 self.stat_digesting = self.eater.digesting;
\r
280 self.stat_eaten = num_for_edict(self.eater);
\r
284 self.stat_stomachload = self.stomach_load;
\r
285 self.stat_digesting = self.digesting;
\r
286 self.stat_eaten = 0;
\r
289 // skip the vore system under some circumstances
\r
290 if(time < game_starttime)
\r
295 if(self.spectatee_status)
\r
297 if(time < self.system_delay)
\r
300 // --------------------------------
\r
301 // Code that addresses predators:
\r
302 // --------------------------------
\r
305 prey = Swallow_distance_check();
\r
307 // attempt to swallow our new prey if there's any in range
\r
308 if(self.BUTTON_ATCK && !self.BUTTON_REGURGITATE && self.swallow_delay < time)
\r
309 if(Swallow_condition_check(prey))
\r
312 Vore_Swallow(prey);
\r
313 self.swallow_delay = time + cvar("g_balance_vore_swallow_delay");
\r
315 if(self.team == prey.team && teamplay)
\r
316 centerprint(self, "You have swallowed a team mate, use caution!");
\r
318 // block firing for a small amount of time when voring, or we'll be firing the next frame after we swallow
\r
319 self.weapon_delay = time + 0.25;
\r
322 // start / stop digestion on command, if the player has someone in their stomach
\r
323 if(self.BUTTON_DIGEST)
\r
325 if(self.stomach_load)
\r
327 if(time > self.digest_button_delay)
\r
329 self.digesting = !self.digesting;
\r
330 self.digest_button_delay = time + button_delay;
\r
333 else if(time > self.complain_swallow)
\r
335 play2(self, "weapons/unavailable.wav");
\r
336 sprint(self, "There is nothing to digest\n");
\r
337 self.complain_swallow = time + complain_delay;
\r
340 if(!self.stomach_load)
\r
341 self.digesting = FALSE;
\r
343 // release players from this player's stomach on command
\r
344 if(self.BUTTON_REGURGITATE)
\r
346 if(self.stomach_load)
\r
348 if(time > self.regurgitate_button_delay)
\r
350 self.regurgitate_prepare = time + cvar("g_balance_vore_regurgitate_delay");
\r
351 PlayerSound(self, playersound_regurgitate_prepare, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
352 self.regurgitate_button_delay = time + button_delay;
\r
355 else if(time > self.complain_swallow)
\r
357 play2(self, "weapons/unavailable.wav");
\r
358 sprint(self, "There is nothing to regurgitate\n");
\r
359 self.complain_swallow = time + complain_delay;
\r
363 if(cvar("g_vore_gurglesound"))
\r
364 Vore_Gurglesound();
\r
366 // --------------------------------
\r
367 // Code that addresses the prey:
\r
368 // --------------------------------
\r
370 if(self.eater.classname != "player")
\r
373 if(self.eater.deadflag || self.deadflag)
\r
374 Vore_Regurgitate(self);
\r
375 else if(self.eater.eater.classname == "player") // don't allow a player inside a player inside another player :)
\r
376 Vore_Regurgitate(self);
\r
377 else if(vlen(self.eater.velocity) > cvar("g_balance_vore_regurgitate_velocitylimit"))
\r
378 Vore_Regurgitate(self);
\r
380 // apply delayed regurgitating
\r
381 if(self.eater.regurgitate_prepare && time > self.eater.regurgitate_prepare)
\r
383 self.eater.regurgitate_prepare = 0;
\r
384 self.eater.complain_swallow = time + complain_delay;
\r
385 Vore_Regurgitate(self);
\r
388 if(self.eater.digesting == TRUE)
\r
390 if(teams_matter && self.team == self.eater.team)
\r
393 Vore_StomachKick();
\r
395 Vore_CameraEffect_Apply();
\r