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
108 setorigin(e, e.eater.origin);
\r
109 e.velocity = '0 0 0';
\r
110 e.movetype = MOVETYPE_FOLLOW;
\r
111 e.solid = SOLID_NOT;
\r
112 e.alpha = -1; // best way of hiding / showing the eaten player
\r
113 e.aiment = e.eater; // follow the predator. Is automatically unset
\r
115 Vore_CameraEffect_Set(e);
\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 if(stov(cvar_string("g_vore_regurgitatecolor_released")))
\r
123 e.colormod = stov(cvar_string("g_vore_regurgitatecolor_released"));
\r
125 if(e.eater.team == e.team && teamplay)
\r
126 centerprint(e.eater, "^4You have swallowed a team mate, use caution!");
\r
128 PlayerSound(e.eater, playersound_swallow, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
129 setanim(e.eater, e.eater.anim_pain1, FALSE, TRUE, TRUE); // looks good for swallowing / regurgitating
\r
130 e.eater.stomach_load += 1;
\r
131 e.eater.regurgitate_prepare = 0;
\r
132 Vore_Weight_apply(e.eater);
\r
134 // block firing for a small amount of time when voring, or we'll be firing the next frame after we swallow
\r
135 e.eater.weapon_delay = time + button_delay;
\r
136 e.eater.swallow_delay = time + cvar("g_balance_vore_swallow_delay");
\r
137 e.system_delay = e.eater.system_delay = time + system_delay_time;
\r
140 void Vore_Regurgitate(entity e)
\r
142 // this player is being released from their predator, apply the proper changes
\r
143 e.movetype = e.vore_oldmovetype;
\r
144 if(e.health > 0) // leave SOLID_NOT for dead bodies
\r
145 e.solid = e.vore_oldsolid;
\r
146 e.view_ofs_z = e.vore_oldview_ofs_z;
\r
147 e.alpha = default_player_alpha; // best way of hiding / showing the eaten player
\r
150 local vector oldforward, oldright, oldup;
\r
151 oldforward = v_forward;
\r
152 oldright = v_right;
\r
154 makevectors(e.eater.v_angle);
\r
155 e.velocity = v_forward * cvar("g_balance_vore_regurgitate_force");
\r
156 e.eater.velocity += -v_forward * cvar("g_balance_vore_regurgitate_eaterforce");
\r
157 v_forward = oldforward;
\r
158 v_right = oldright;
\r
161 PlayerSound(e.eater, playersound_regurgitate, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
162 setanim(e.eater, e.eater.anim_pain1, FALSE, TRUE, TRUE); // looks good for swallowing / regurgitating
\r
163 pointparticles(particleeffectnum("regurgitate"), e.eater.origin, '0 0 0', 1);
\r
164 e.eater.stomach_load -= 1;
\r
165 e.eater.regurgitate_prepare = 0;
\r
166 e.eater.swallow_delay = time + cvar("g_balance_vore_swallow_delay");
\r
167 Vore_Weight_apply(e.eater);
\r
169 e.system_delay = e.eater.system_delay = time + system_delay_time;
\r
173 void Vore_Gurglesound();
\r
174 void Vore_Disconnect()
\r
176 // frees prey from their predators when someone disconnects or goes spectating
\r
178 // prey disconnects or goes spectating while inside someone's belly:
\r
179 if(self.eater.classname == "player")
\r
181 self.view_ofs_z = self.vore_oldview_ofs_z;
\r
182 self.eater.stomach_load -= 1;
\r
183 Vore_Weight_apply(self.eater);
\r
184 self.eater = world;
\r
187 // pred disconnects or goes spectating with players in their belly:
\r
188 else if(self.stomach_load > 0)
\r
191 FOR_EACH_PLAYER(head)
\r
193 if(head.eater == self)
\r
194 Vore_Regurgitate(head);
\r
196 Vore_Gurglesound(); // stop the gurgling sound
\r
200 .float digestion_step;
\r
203 // apply digestion to prey
\r
204 if(time > self.eater.digestion_step + steptime)
\r
206 Damage(self, self.eater, self.eater, cvar("g_balance_vore_digestion_damage"), DEATH_DIGESTION, self.origin, '0 0 0');
\r
207 if(cvar("g_balance_vore_digestion_vampire") && self.eater.health < cvar("g_balance_vore_digestion_vampire_stable"))
\r
208 self.eater.health += cvar("g_balance_vore_digestion_vampire");
\r
210 if (self.eater.digestsound_finished < time)
\r
212 self.eater.digestsound_finished = time + 0.5;
\r
213 PlayerSound (self.eater, playersound_digest, CHAN_PLAYER, VOICETYPE_PLAYERSOUND);
\r
215 self.eater.digestion_step = time;
\r
218 if(self.health <= 0)
\r
219 if(stov(cvar_string("g_vore_regurgitatecolor_digested")))
\r
220 self.colormod = stov(cvar_string("g_vore_regurgitatecolor_digested"));
\r
223 .float teamheal_step;
\r
224 void Vore_Teamheal()
\r
226 if(cvar("g_balance_vore_teamheal") && self.health < cvar("g_balance_vore_teamheal_stable"))
\r
227 if(time > self.teamheal_step + steptime)
\r
229 self.health += cvar("g_balance_vore_teamheal");
\r
230 self.teamheal_step = time;
\r
234 .float stomachkick_delay;
\r
235 void Vore_StomachKick()
\r
237 // allows prey to kick the predator's stomach and do some damage or attempt to escape
\r
238 if(self.eater.classname != "player")
\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
255 .float gurglesound_finished, gurglesound_oldstomachload;
\r
256 void Vore_Gurglesound()
\r
258 if(time > self.gurglesound_finished || self.gurglesound_oldstomachload != self.stomach_load)
\r
260 GlobalSound(self.playersound_gurgle, CHAN_TRIGGER, VOICETYPE_GURGLE);
\r
262 self.gurglesound_finished = time + 11; // yes, hard coded sound length. I know it's bad but what can I do?
\r
263 self.gurglesound_oldstomachload = self.stomach_load;
\r
269 // if we are free, show our stomach load on the HUD. Otherwise, show the predator's
\r
270 if(self.eater.classname == "player")
\r
272 self.stat_stomachload = self.eater.stomach_load;
\r
273 self.stat_digesting = self.eater.digesting;
\r
274 self.stat_eaten = num_for_edict(self.eater);
\r
278 self.stat_stomachload = self.stomach_load;
\r
279 self.stat_digesting = self.digesting;
\r
280 self.stat_eaten = 0;
\r
283 // skip the vore system under some circumstances
\r
284 if(time < game_starttime)
\r
289 if(self.spectatee_status)
\r
291 if(time < self.system_delay)
\r
294 // --------------------------------
\r
295 // Code that addresses predators:
\r
296 // --------------------------------
\r
299 prey = Swallow_distance_check();
\r
301 // attempt to swallow our new prey if there's any in range
\r
302 if(self.BUTTON_ATCK && !self.BUTTON_REGURGITATE && self.swallow_delay < time)
\r
303 if(Swallow_condition_check(prey))
\r
304 Vore_Swallow(prey);
\r
306 // start / stop digestion on command, if the player has someone in their stomach
\r
307 if(self.BUTTON_DIGEST)
\r
309 if(self.stomach_load)
\r
311 if(time > self.digest_button_delay)
\r
313 self.digesting = !self.digesting;
\r
314 self.digest_button_delay = time + button_delay;
\r
317 else if(time > self.complain_swallow)
\r
319 play2(self, "weapons/unavailable.wav");
\r
320 sprint(self, "There is nothing to digest\n");
\r
321 self.complain_swallow = time + complain_delay;
\r
324 if(!self.stomach_load)
\r
325 self.digesting = FALSE;
\r
327 // release players from this player's stomach on command
\r
328 if(self.BUTTON_REGURGITATE)
\r
330 if(self.stomach_load)
\r
332 if(time > self.regurgitate_button_delay)
\r
334 self.regurgitate_prepare = time + cvar("g_balance_vore_regurgitate_delay");
\r
335 PlayerSound(self, playersound_regurgitate_prepare, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
336 self.regurgitate_button_delay = time + button_delay;
\r
339 else if(time > self.complain_swallow)
\r
341 play2(self, "weapons/unavailable.wav");
\r
342 sprint(self, "There is nothing to regurgitate\n");
\r
343 self.complain_swallow = time + complain_delay;
\r
347 if(cvar("g_vore_gurglesound"))
\r
348 Vore_Gurglesound();
\r
350 // --------------------------------
\r
351 // Code that addresses the prey:
\r
352 // --------------------------------
\r
354 if(self.eater.classname != "player")
\r
357 if(self.eater.deadflag || self.deadflag)
\r
358 Vore_Regurgitate(self);
\r
359 else if(self.eater.eater.classname == "player") // don't allow a player inside a player inside another player :)
\r
361 entity targeteater, oldself;
\r
362 targeteater = self.eater.eater;
\r
364 Vore_Regurgitate(self);
\r
365 if(1 == 1) //cvar!!!!!!!!!!!!!!!!
\r
366 if(Swallow_condition_check(self))
\r
369 self = targeteater;
\r
370 Vore_Swallow(oldself);
\r
374 else if(vlen(self.eater.velocity) > cvar("g_balance_vore_regurgitate_velocitylimit"))
\r
375 Vore_Regurgitate(self);
\r
377 // apply delayed regurgitating
\r
378 if(self.eater.regurgitate_prepare && time > self.eater.regurgitate_prepare)
\r
380 self.eater.regurgitate_prepare = 0;
\r
381 self.eater.complain_swallow = time + complain_delay;
\r
382 Vore_Regurgitate(self);
\r
385 if(self.eater.digesting == TRUE)
\r
387 if(teams_matter && self.team == self.eater.team)
\r
390 if(self.BUTTON_ATCK)
\r
391 Vore_StomachKick();
\r
393 Vore_CameraEffect_Apply();
\r