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
73 step = 2 * frametime; // CVAR!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
\r
75 if(self.cameraeffect_current >= self.cameraeffect_target + step)
\r
76 self.cameraeffect_current -= step;
\r
77 else if(self.cameraeffect_current <= self.cameraeffect_target - step)
\r
78 self.cameraeffect_current += step;
\r
80 bprint(strcat(ftos(self.cameraeffect_current), "<<-----------\n"));
\r
81 self.view_ofs_z = self.vore_oldview_ofs_z / self.cameraeffect_current;
\r
84 void Vore_Weight_apply(entity e)
\r
86 // apply stomach weight that makes you heavier the more you eat
\r
87 // slowing the player is applied in cl_physics.qc
\r
88 if(e.stomach_load != e.vore_oldstomachload)
\r
89 e.gravity += 1 + (e.stomach_load * cvar("g_balance_vore_weight_gravity") - e.vore_oldstomachload);
\r
91 e.gravity = 0.00001; // 0 becomes 1 for .gravity, so do this to allow 0 gravity
\r
92 e.vore_oldstomachload = e.stomach_load;
\r
95 void Vore_Swallow(entity e)
\r
97 // this player is beening swallowed by another player, apply the proper changes
\r
98 e.vore_oldmovetype = e.movetype;
\r
99 e.vore_oldsolid = e.solid;
\r
100 e.vore_oldview_ofs_z = e.view_ofs_z;
\r
102 setorigin(e, e.eater.origin);
\r
103 e.velocity = '0 0 0';
\r
104 e.movetype = MOVETYPE_FOLLOW;
\r
105 e.solid = SOLID_NOT;
\r
106 e.alpha = -1; // best way of hiding / showing the eaten player
\r
107 e.aiment = e.eater; // follow the predator. Is automatically unset
\r
109 /*e.cameraeffect_current = e.view_ofs_z * 2;
\r
110 e.cameraeffect_target = e.view_ofs_z / 2; // best positioning for the stomach model*/
\r
112 Vore_CameraEffect_Set(e);
\r
114 // drop keys (KH) and flags (CTF) when we get swallowed
\r
115 kh_Key_DropAll(e, FALSE);
\r
117 DropFlag(e.flagcarried, world, e.eater);
\r
119 if(stov(cvar_string("g_vore_regurgitatecolor_released")))
\r
120 e.colormod = stov(cvar_string("g_vore_regurgitatecolor_released"));
\r
122 PlayerSound(e.eater, playersound_swallow, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
123 setanim(e.eater, e.eater.anim_pain1, FALSE, TRUE, TRUE); // looks good for swallowing \ regurgitating
\r
124 e.eater.stomach_load += 1;
\r
125 e.eater.regurgitate_prepare = 0;
\r
126 Vore_Weight_apply(e.eater);
\r
128 e.system_delay = e.eater.system_delay = time + system_delay_time;
\r
131 void Vore_Regurgitate(entity e)
\r
133 // this player is being released from their predator, apply the proper changes
\r
134 e.movetype = e.vore_oldmovetype;
\r
135 if(e.health > 0) // leave SOLID_NOT for dead bodies
\r
136 e.solid = e.vore_oldsolid;
\r
137 e.view_ofs_z = e.vore_oldview_ofs_z;
\r
138 e.alpha = default_player_alpha; // best way of hiding / showing the eaten player
\r
140 //e.view_ofs_z *= 2; // best positioning for the stomach model
\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 += 25;
\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 / attempt to escape, or bring the predator's digestion upon their self when there's no other option
\r
231 if(self.eater.classname != "player")
\r
234 // kick the predator's stomach and do damage, or escape if we are lucky
\r
235 if(self.BUTTON_ATCK)
\r
236 if(time > self.stomachkick_delay)
\r
239 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
240 Damage(self.eater, self, self, damage, DEATH_STOMACHKICK, self.eater.origin, '0 0 0');
\r
241 sound(self.eater, CHAN_PROJECTILE, "weapons/stomachkick.ogg", VOL_BASE, ATTN_NORM);
\r
243 if(cvar("g_balance_vore_kick_escapeprobability") >= random())
\r
244 Vore_Regurgitate(self);
\r
246 self.stomachkick_delay = time + cvar("g_balance_vore_kick_delay");
\r
249 // start the predator's digestion
\r
250 if(self.BUTTON_ATCK2)
\r
252 centerprint(self.eater, strcat(self.netname, " has triggered your digestion"));
\r
253 self.eater.digesting = TRUE;
\r
257 .float gurglesound_finished, gurglesound_oldstomachload;
\r
258 void Vore_Gurglesound()
\r
260 if(time > self.gurglesound_finished || self.gurglesound_oldstomachload != self.stomach_load)
\r
262 GlobalSound(self.playersound_gurgle, CHAN_TRIGGER, VOICETYPE_GURGLE);
\r
264 self.gurglesound_finished = time + 11; // yes, hard coded sound length. I know it's bad but what can I do?
\r
265 self.gurglesound_oldstomachload = self.stomach_load;
\r
271 // if we are free, show our stomach load on the HUD. Otherwise, show the predator's
\r
272 if(self.eater.classname == "player")
\r
274 self.stat_stomachload = self.eater.stomach_load;
\r
275 self.stat_digesting = self.eater.digesting;
\r
276 self.stat_eaten = num_for_edict(self.eater);
\r
280 self.stat_stomachload = self.stomach_load;
\r
281 self.stat_digesting = self.digesting;
\r
282 self.stat_eaten = 0;
\r
285 // skip the vore system under some circumstances
\r
286 if(time < game_starttime)
\r
291 if(self.spectatee_status)
\r
293 if(time < self.system_delay)
\r
296 // --------------------------------
\r
297 // Code that addresses predators:
\r
298 // --------------------------------
\r
301 prey = Swallow_distance_check();
\r
303 // attempt to swallow our new prey if there's any in range
\r
304 if(self.BUTTON_ATCK && !self.BUTTON_REGURGITATE && self.swallow_delay < time)
\r
305 if(Swallow_condition_check(prey))
\r
308 Vore_Swallow(prey);
\r
309 self.swallow_delay = time + cvar("g_balance_vore_swallow_delay");
\r
311 if(self.team == prey.team && teamplay)
\r
312 centerprint(self, "You have swallowed a team mate, use caution!");
\r
314 // block firing for a small amount of time when voring, or we'll be firing the next frame after we swallow
\r
315 self.weapon_delay = time + 0.25;
\r
318 // start / stop digestion on command, if the player has someone in their stomach
\r
319 if(self.BUTTON_DIGEST)
\r
321 if(self.stomach_load)
\r
323 if(time > self.digest_button_delay)
\r
325 self.digesting = !self.digesting;
\r
326 self.digest_button_delay = time + button_delay;
\r
329 else if(time > self.complain_swallow)
\r
331 play2(self, "weapons/unavailable.wav");
\r
332 sprint(self, "There is nothing to digest\n");
\r
333 self.complain_swallow = time + complain_delay;
\r
336 if(!self.stomach_load)
\r
337 self.digesting = FALSE;
\r
339 // release players from this player's stomach on command
\r
340 if(self.BUTTON_REGURGITATE)
\r
342 if(self.stomach_load)
\r
344 if(time > self.regurgitate_button_delay)
\r
346 self.regurgitate_prepare = time + cvar("g_balance_vore_regurgitate_delay");
\r
347 PlayerSound(self, playersound_regurgitate_prepare, CHAN_PAIN, VOICETYPE_PLAYERSOUND);
\r
348 self.regurgitate_button_delay = time + button_delay;
\r
351 else if(time > self.complain_swallow)
\r
353 play2(self, "weapons/unavailable.wav");
\r
354 sprint(self, "There is nothing to regurgitate\n");
\r
355 self.complain_swallow = time + complain_delay;
\r
359 if(cvar("g_vore_gurglesound"))
\r
360 Vore_Gurglesound();
\r
362 // --------------------------------
\r
363 // Code that addresses the prey:
\r
364 // --------------------------------
\r
366 if(self.eater.classname != "player")
\r
369 if(self.eater.deadflag || self.deadflag)
\r
370 Vore_Regurgitate(self);
\r
371 else if(self.eater.eater.classname == "player") // don't allow a player inside a player inside another player :)
\r
372 Vore_Regurgitate(self);
\r
373 else if(vlen(self.eater.velocity) > cvar("g_balance_vore_regurgitate_velocitylimit"))
\r
374 Vore_Regurgitate(self);
\r
376 // apply delayed regurgitating
\r
377 if(self.eater.regurgitate_prepare && time > self.eater.regurgitate_prepare)
\r
379 self.eater.regurgitate_prepare = 0;
\r
380 self.eater.complain_swallow = time + complain_delay;
\r
381 Vore_Regurgitate(self);
\r
384 if(self.eater.digesting == TRUE)
\r
386 if(teams_matter && self.team == self.eater.team)
\r
389 Vore_StomachKick();
\r
391 Vore_CameraEffect_Apply();
\r