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 Vore_CameraEffect_Set(e);
\r
116 // drop keys (KH) and flags (CTF) when we get swallowed
\r
117 kh_Key_DropAll(e, FALSE);
\r
119 DropFlag(e.flagcarried, world, e.eater);
\r
121 if(stov(cvar_string("g_vore_regurgitatecolor_released")))
\r
122 e.colormod = stov(cvar_string("g_vore_regurgitatecolor_released"));
\r
124 PlayerSound(e.eater, playersound_swallow, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
125 setanim(e.eater, e.eater.anim_pain1, FALSE, TRUE, TRUE); // looks good for swallowing / regurgitating
\r
126 e.eater.stomach_load += 1;
\r
127 e.eater.regurgitate_prepare = 0;
\r
128 Vore_Weight_apply(e.eater);
\r
130 e.system_delay = e.eater.system_delay = time + system_delay_time;
\r
133 void Vore_Regurgitate(entity e)
\r
135 // this player is being released from their predator, apply the proper changes
\r
136 e.movetype = e.vore_oldmovetype;
\r
137 if(e.health > 0) // leave SOLID_NOT for dead bodies
\r
138 e.solid = e.vore_oldsolid;
\r
139 e.view_ofs_z = e.vore_oldview_ofs_z;
\r
140 e.alpha = default_player_alpha; // best way of hiding / showing the eaten player
\r
143 local vector oldforward, oldright, oldup;
\r
144 oldforward = v_forward;
\r
145 oldright = v_right;
\r
147 makevectors(e.eater.v_angle);
\r
148 e.velocity = v_forward * cvar("g_balance_vore_regurgitate_force");
\r
149 e.eater.velocity += -v_forward * cvar("g_balance_vore_regurgitate_eaterforce");
\r
150 v_forward = oldforward;
\r
151 v_right = oldright;
\r
154 PlayerSound(e.eater, playersound_regurgitate, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
155 setanim(e.eater, e.eater.anim_pain1, FALSE, TRUE, TRUE); // looks good for swallowing / regurgitating
\r
156 pointparticles(particleeffectnum("regurgitate"), e.eater.origin, '0 0 0', 1);
\r
157 e.eater.stomach_load -= 1;
\r
158 e.eater.regurgitate_prepare = 0;
\r
159 e.eater.swallow_delay = time + cvar("g_balance_vore_swallow_delay");
\r
160 Vore_Weight_apply(e.eater);
\r
162 e.system_delay = e.eater.system_delay = time + system_delay_time;
\r
166 void Vore_Gurglesound();
\r
167 void Vore_Disconnect()
\r
169 // frees prey from their predators when someone disconnects or goes spectating
\r
171 // prey disconnects or goes spectating while inside someone's belly:
\r
172 if(self.eater.classname == "player")
\r
174 self.view_ofs_z = self.vore_oldview_ofs_z;
\r
175 self.eater.stomach_load -= 1;
\r
176 Vore_Weight_apply(self.eater);
\r
177 self.eater = world;
\r
180 // pred disconnects or goes spectating with players in their belly:
\r
181 else if(self.stomach_load > 0)
\r
184 FOR_EACH_PLAYER(head)
\r
186 if(head.eater == self)
\r
187 Vore_Regurgitate(head);
\r
189 Vore_Gurglesound(); // stop the gurgling sound
\r
193 .float digestion_step;
\r
196 // apply digestion to prey
\r
197 if(time > self.eater.digestion_step + steptime)
\r
199 Damage(self, self.eater, self.eater, cvar("g_balance_vore_digestion_damage"), DEATH_DIGESTION, self.origin, '0 0 0');
\r
200 if(cvar("g_balance_vore_digestion_vampire") && self.eater.health < cvar("g_balance_vore_digestion_vampire_stable"))
\r
201 self.eater.health += cvar("g_balance_vore_digestion_vampire");
\r
203 if (self.eater.digestsound_finished < time)
\r
205 self.eater.digestsound_finished = time + 0.5;
\r
206 PlayerSound (self.eater, playersound_digest, CHAN_PLAYER, VOICETYPE_PLAYERSOUND);
\r
208 self.eater.digestion_step = time;
\r
211 if(self.health <= 0)
\r
212 if(stov(cvar_string("g_vore_regurgitatecolor_digested")))
\r
213 self.colormod = stov(cvar_string("g_vore_regurgitatecolor_digested"));
\r
216 .float teamheal_step;
\r
217 void Vore_Teamheal()
\r
219 if(cvar("g_balance_vore_teamheal") && self.health < cvar("g_balance_vore_teamheal_stable"))
\r
220 if(time > self.teamheal_step + steptime)
\r
222 self.health += cvar("g_balance_vore_teamheal");
\r
223 self.teamheal_step = time;
\r
227 .float stomachkick_delay;
\r
228 void Vore_StomachKick()
\r
230 // allows prey to kick the predator's stomach and do some damage or attempt to escape
\r
231 if(self.eater.classname != "player")
\r
234 if(time > self.stomachkick_delay)
\r
237 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
238 Damage(self.eater, self, self, damage, DEATH_STOMACHKICK, self.eater.origin, '0 0 0');
\r
239 sound(self.eater, CHAN_PROJECTILE, "weapons/stomachkick.ogg", VOL_BASE, ATTN_NORM);
\r
241 if(cvar("g_balance_vore_kick_escapeprobability") >= random())
\r
242 Vore_Regurgitate(self);
\r
244 self.stomachkick_delay = time + cvar("g_balance_vore_kick_delay");
\r
248 .float gurglesound_finished, gurglesound_oldstomachload;
\r
249 void Vore_Gurglesound()
\r
251 if(time > self.gurglesound_finished || self.gurglesound_oldstomachload != self.stomach_load)
\r
253 GlobalSound(self.playersound_gurgle, CHAN_TRIGGER, VOICETYPE_GURGLE);
\r
255 self.gurglesound_finished = time + 11; // yes, hard coded sound length. I know it's bad but what can I do?
\r
256 self.gurglesound_oldstomachload = self.stomach_load;
\r
262 // if we are free, show our stomach load on the HUD. Otherwise, show the predator's
\r
263 if(self.eater.classname == "player")
\r
265 self.stat_stomachload = self.eater.stomach_load;
\r
266 self.stat_digesting = self.eater.digesting;
\r
267 self.stat_eaten = num_for_edict(self.eater);
\r
271 self.stat_stomachload = self.stomach_load;
\r
272 self.stat_digesting = self.digesting;
\r
273 self.stat_eaten = 0;
\r
276 // skip the vore system under some circumstances
\r
277 if(time < game_starttime)
\r
282 if(self.spectatee_status)
\r
284 if(time < self.system_delay)
\r
287 // --------------------------------
\r
288 // Code that addresses predators:
\r
289 // --------------------------------
\r
292 prey = Swallow_distance_check();
\r
294 // attempt to swallow our new prey if there's any in range
\r
295 if(self.BUTTON_ATCK && !self.BUTTON_REGURGITATE && self.swallow_delay < time)
\r
296 if(Swallow_condition_check(prey))
\r
299 Vore_Swallow(prey);
\r
300 self.swallow_delay = time + cvar("g_balance_vore_swallow_delay");
\r
302 if(self.team == prey.team && teamplay)
\r
303 centerprint(self, "You have swallowed a team mate, use caution!");
\r
305 // block firing for a small amount of time when voring, or we'll be firing the next frame after we swallow
\r
306 self.weapon_delay = time + 0.25;
\r
309 // start / stop digestion on command, if the player has someone in their stomach
\r
310 if(self.BUTTON_DIGEST)
\r
312 if(self.stomach_load)
\r
314 if(time > self.digest_button_delay)
\r
316 self.digesting = !self.digesting;
\r
317 self.digest_button_delay = time + button_delay;
\r
320 else if(time > self.complain_swallow)
\r
322 play2(self, "weapons/unavailable.wav");
\r
323 sprint(self, "There is nothing to digest\n");
\r
324 self.complain_swallow = time + complain_delay;
\r
327 if(!self.stomach_load)
\r
328 self.digesting = FALSE;
\r
330 // release players from this player's stomach on command
\r
331 if(self.BUTTON_REGURGITATE)
\r
333 if(self.stomach_load)
\r
335 if(time > self.regurgitate_button_delay)
\r
337 self.regurgitate_prepare = time + cvar("g_balance_vore_regurgitate_delay");
\r
338 PlayerSound(self, playersound_regurgitate_prepare, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
339 self.regurgitate_button_delay = time + button_delay;
\r
342 else if(time > self.complain_swallow)
\r
344 play2(self, "weapons/unavailable.wav");
\r
345 sprint(self, "There is nothing to regurgitate\n");
\r
346 self.complain_swallow = time + complain_delay;
\r
350 if(cvar("g_vore_gurglesound"))
\r
351 Vore_Gurglesound();
\r
353 // --------------------------------
\r
354 // Code that addresses the prey:
\r
355 // --------------------------------
\r
357 if(self.eater.classname != "player")
\r
360 if(self.eater.deadflag || self.deadflag)
\r
361 Vore_Regurgitate(self);
\r
362 else if(self.eater.eater.classname == "player") // don't allow a player inside a player inside another player :)
\r
363 Vore_Regurgitate(self);
\r
364 else if(vlen(self.eater.velocity) > cvar("g_balance_vore_regurgitate_velocitylimit"))
\r
365 Vore_Regurgitate(self);
\r
367 // apply delayed regurgitating
\r
368 if(self.eater.regurgitate_prepare && time > self.eater.regurgitate_prepare)
\r
370 self.eater.regurgitate_prepare = 0;
\r
371 self.eater.complain_swallow = time + complain_delay;
\r
372 Vore_Regurgitate(self);
\r
375 if(self.eater.digesting == TRUE)
\r
377 if(teams_matter && self.team == self.eater.team)
\r
380 if(self.BUTTON_ATCK)
\r
381 Vore_StomachKick();
\r
383 Vore_CameraEffect_Apply();
\r