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 /*e.cameraeffect_current = e.view_ofs_z * 2;
\r
115 e.cameraeffect_target = e.view_ofs_z / 2; // best positioning for the stomach model*/
\r
117 Vore_CameraEffect_Set(e);
\r
119 // drop keys (KH) and flags (CTF) when we get swallowed
\r
120 kh_Key_DropAll(e, FALSE);
\r
122 DropFlag(e.flagcarried, world, e.eater);
\r
124 if(stov(cvar_string("g_vore_regurgitatecolor_released")))
\r
125 e.colormod = stov(cvar_string("g_vore_regurgitatecolor_released"));
\r
127 PlayerSound(e.eater, playersound_swallow, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
128 setanim(e.eater, e.eater.anim_pain1, FALSE, TRUE, TRUE); // looks good for swallowing \ regurgitating
\r
129 e.eater.stomach_load += 1;
\r
130 e.eater.regurgitate_prepare = 0;
\r
131 Vore_Weight_apply(e.eater);
\r
133 e.system_delay = e.eater.system_delay = time + system_delay_time;
\r
136 void Vore_Regurgitate(entity e)
\r
138 // this player is being released from their predator, apply the proper changes
\r
139 e.movetype = e.vore_oldmovetype;
\r
140 if(e.health > 0) // leave SOLID_NOT for dead bodies
\r
141 e.solid = e.vore_oldsolid;
\r
142 e.view_ofs_z = e.vore_oldview_ofs_z;
\r
143 e.alpha = default_player_alpha; // best way of hiding / showing the eaten player
\r
145 //e.view_ofs_z *= 2; // best positioning for the stomach model
\r
148 local vector oldforward, oldright, oldup;
\r
149 oldforward = v_forward;
\r
150 oldright = v_right;
\r
152 makevectors(e.eater.v_angle);
\r
153 e.velocity = v_forward * cvar("g_balance_vore_regurgitate_force");
\r
154 e.eater.velocity += -v_forward * cvar("g_balance_vore_regurgitate_eaterforce");
\r
155 v_forward = oldforward;
\r
156 v_right = oldright;
\r
159 PlayerSound(e.eater, playersound_regurgitate, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
160 setanim(e.eater, e.eater.anim_pain1, FALSE, TRUE, TRUE); // looks good for swallowing \ regurgitating
\r
161 pointparticles(particleeffectnum("regurgitate"), e.eater.origin, '0 0 0', 1);
\r
162 e.eater.stomach_load -= 1;
\r
163 e.eater.regurgitate_prepare = 0;
\r
164 e.eater.swallow_delay = time + cvar("g_balance_vore_swallow_delay");
\r
165 Vore_Weight_apply(e.eater);
\r
167 e.system_delay = e.eater.system_delay = time + system_delay_time;
\r
171 void Vore_Gurglesound();
\r
172 void Vore_Disconnect()
\r
174 // frees prey from their predators when someone disconnects or goes spectating
\r
176 // prey disconnects or goes spectating while inside someone's belly:
\r
177 if(self.eater.classname == "player")
\r
179 self.view_ofs_z += 25;
\r
180 self.eater.stomach_load -= 1;
\r
181 Vore_Weight_apply(self.eater);
\r
182 self.eater = world;
\r
185 // pred disconnects or goes spectating with players in their belly:
\r
186 else if(self.stomach_load > 0)
\r
189 FOR_EACH_PLAYER(head)
\r
191 if(head.eater == self)
\r
192 Vore_Regurgitate(head);
\r
194 Vore_Gurglesound(); // stop the gurgling sound
\r
198 .float digestion_step;
\r
201 // apply digestion to prey
\r
202 if(time > self.eater.digestion_step + steptime)
\r
204 Damage(self, self.eater, self.eater, cvar("g_balance_vore_digestion_damage"), DEATH_DIGESTION, self.origin, '0 0 0');
\r
205 if(cvar("g_balance_vore_digestion_vampire") && self.eater.health < cvar("g_balance_vore_digestion_vampire_stable"))
\r
206 self.eater.health += cvar("g_balance_vore_digestion_vampire");
\r
208 if (self.eater.digestsound_finished < time)
\r
210 self.eater.digestsound_finished = time + 0.5;
\r
211 PlayerSound (self.eater, playersound_digest, CHAN_PLAYER, VOICETYPE_PLAYERSOUND);
\r
213 self.eater.digestion_step = time;
\r
216 if(self.health <= 0)
\r
217 if(stov(cvar_string("g_vore_regurgitatecolor_digested")))
\r
218 self.colormod = stov(cvar_string("g_vore_regurgitatecolor_digested"));
\r
221 .float teamheal_step;
\r
222 void Vore_Teamheal()
\r
224 if(cvar("g_balance_vore_teamheal") && self.health < cvar("g_balance_vore_teamheal_stable"))
\r
225 if(time > self.teamheal_step + steptime)
\r
227 self.health += cvar("g_balance_vore_teamheal");
\r
228 self.teamheal_step = time;
\r
232 .float stomachkick_delay;
\r
233 void Vore_StomachKick()
\r
235 // 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
236 if(self.eater.classname != "player")
\r
239 // kick the predator's stomach and do damage, or escape if we are lucky
\r
240 if(self.BUTTON_ATCK)
\r
241 if(time > self.stomachkick_delay)
\r
244 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
245 Damage(self.eater, self, self, damage, DEATH_STOMACHKICK, self.eater.origin, '0 0 0');
\r
246 sound(self.eater, CHAN_PROJECTILE, "weapons/stomachkick.ogg", VOL_BASE, ATTN_NORM);
\r
248 if(cvar("g_balance_vore_kick_escapeprobability") >= random())
\r
249 Vore_Regurgitate(self);
\r
251 self.stomachkick_delay = time + cvar("g_balance_vore_kick_delay");
\r
254 // start the predator's digestion
\r
255 if(self.BUTTON_ATCK2)
\r
257 centerprint(self.eater, strcat(self.netname, " has triggered your digestion"));
\r
258 self.eater.digesting = TRUE;
\r
262 .float gurglesound_finished, gurglesound_oldstomachload;
\r
263 void Vore_Gurglesound()
\r
265 if(time > self.gurglesound_finished || self.gurglesound_oldstomachload != self.stomach_load)
\r
267 GlobalSound(self.playersound_gurgle, CHAN_TRIGGER, VOICETYPE_GURGLE);
\r
269 self.gurglesound_finished = time + 11; // yes, hard coded sound length. I know it's bad but what can I do?
\r
270 self.gurglesound_oldstomachload = self.stomach_load;
\r
276 // if we are free, show our stomach load on the HUD. Otherwise, show the predator's
\r
277 if(self.eater.classname == "player")
\r
279 self.stat_stomachload = self.eater.stomach_load;
\r
280 self.stat_digesting = self.eater.digesting;
\r
281 self.stat_eaten = num_for_edict(self.eater);
\r
285 self.stat_stomachload = self.stomach_load;
\r
286 self.stat_digesting = self.digesting;
\r
287 self.stat_eaten = 0;
\r
290 // skip the vore system under some circumstances
\r
291 if(time < game_starttime)
\r
296 if(self.spectatee_status)
\r
298 if(time < self.system_delay)
\r
301 // --------------------------------
\r
302 // Code that addresses predators:
\r
303 // --------------------------------
\r
306 prey = Swallow_distance_check();
\r
308 // attempt to swallow our new prey if there's any in range
\r
309 if(self.BUTTON_ATCK && !self.BUTTON_REGURGITATE && self.swallow_delay < time)
\r
310 if(Swallow_condition_check(prey))
\r
313 Vore_Swallow(prey);
\r
314 self.swallow_delay = time + cvar("g_balance_vore_swallow_delay");
\r
316 if(self.team == prey.team && teamplay)
\r
317 centerprint(self, "You have swallowed a team mate, use caution!");
\r
319 // block firing for a small amount of time when voring, or we'll be firing the next frame after we swallow
\r
320 self.weapon_delay = time + 0.25;
\r
323 // start / stop digestion on command, if the player has someone in their stomach
\r
324 if(self.BUTTON_DIGEST)
\r
326 if(self.stomach_load)
\r
328 if(time > self.digest_button_delay)
\r
330 self.digesting = !self.digesting;
\r
331 self.digest_button_delay = time + button_delay;
\r
334 else if(time > self.complain_swallow)
\r
336 play2(self, "weapons/unavailable.wav");
\r
337 sprint(self, "There is nothing to digest\n");
\r
338 self.complain_swallow = time + complain_delay;
\r
341 if(!self.stomach_load)
\r
342 self.digesting = FALSE;
\r
344 // release players from this player's stomach on command
\r
345 if(self.BUTTON_REGURGITATE)
\r
347 if(self.stomach_load)
\r
349 if(time > self.regurgitate_button_delay)
\r
351 self.regurgitate_prepare = time + cvar("g_balance_vore_regurgitate_delay");
\r
352 PlayerSound(self, playersound_regurgitate_prepare, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
353 self.regurgitate_button_delay = time + button_delay;
\r
356 else if(time > self.complain_swallow)
\r
358 play2(self, "weapons/unavailable.wav");
\r
359 sprint(self, "There is nothing to regurgitate\n");
\r
360 self.complain_swallow = time + complain_delay;
\r
364 if(cvar("g_vore_gurglesound"))
\r
365 Vore_Gurglesound();
\r
367 // --------------------------------
\r
368 // Code that addresses the prey:
\r
369 // --------------------------------
\r
371 if(self.eater.classname != "player")
\r
374 if(self.eater.deadflag || self.deadflag)
\r
375 Vore_Regurgitate(self);
\r
376 else if(self.eater.eater.classname == "player") // don't allow a player inside a player inside another player :)
\r
377 Vore_Regurgitate(self);
\r
378 else if(vlen(self.eater.velocity) > cvar("g_balance_vore_regurgitate_velocitylimit"))
\r
379 Vore_Regurgitate(self);
\r
381 // apply delayed regurgitating
\r
382 if(self.eater.regurgitate_prepare && time > self.eater.regurgitate_prepare)
\r
384 self.eater.regurgitate_prepare = 0;
\r
385 self.eater.complain_swallow = time + complain_delay;
\r
386 Vore_Regurgitate(self);
\r
389 if(self.eater.digesting == TRUE)
\r
391 if(teams_matter && self.team == self.eater.team)
\r
394 Vore_StomachKick();
\r
396 Vore_CameraEffect_Apply();
\r