X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=data%2Fqcsrc%2Fserver%2Fvore.qc;h=cd795cec975f5bc26c60bf3ce85cff861fb8a5b7;hb=254ae82975010df10cac9fe7f43424b51820810d;hp=febc062e7cf86f2410a66f90941a1357992c6c31;hpb=07222cdef8ad94c7d60ebf53965ab36aa006c53d;p=voretournament%2Fvoretournament.git diff --git a/data/qcsrc/server/vore.qc b/data/qcsrc/server/vore.qc index febc062e..cd795cec 100644 --- a/data/qcsrc/server/vore.qc +++ b/data/qcsrc/server/vore.qc @@ -89,6 +89,18 @@ float Stomach_TeamMates_check(entity pred) return FALSE; } +float Stomach_HasLivePrey(entity pred) +{ + entity head; + FOR_EACH_PLAYER(head) + { + if(head.predator == pred) + if(head.deadflag == DEAD_NO) + return TRUE; + } + return FALSE; +} + float Vore_CanLeave() { if(self.stat_eaten) @@ -123,12 +135,6 @@ void Vore_SetPreyPositions(entity pred) // since prey have their predators set as an aiment, view_ofs will specify the real origin of prey, not just the view offset head.view_ofs = origin_apply; - head.view_ofs_z *= pred.scale; // stomach center depends on predator scale - - // change prey height based on scale - float prey_height; - prey_height = (head.scale - pred.scale) * cvar("g_healthsize_vore_pos"); - head.view_ofs_z += prey_height; } } } @@ -286,8 +292,8 @@ void Vore_Swallow(entity e) if(e.flagcarried) DropFlag(e.flagcarried, world, e.predator); - if(stov(cvar_string("g_vore_regurgitatecolor_release"))) - e.colormod = stov(cvar_string("g_vore_regurgitatecolor_release")); + if(stov(cvar_string("g_vore_regurgitatecolor_color_normal"))) + e.colormod = stov(cvar_string("g_vore_regurgitatecolor_color_normal")); if(teams_matter && e.team == e.predator.team) { @@ -354,6 +360,14 @@ void Vore_Regurgitate(entity e) e.solid = e.vore_oldsolid; e.view_ofs_z = PL_VIEW_OFS_z; + // if the prey has been fully digested, silently detach them + if(e.deadflag != DEAD_NO && e.health <= cvar("g_balance_vore_digestion_limit")) + { + e.predator = world; + e.modelindex = 0; // hide the dead body + return; + } + // apply velocities local vector oldforward, oldright, oldup; oldforward = v_forward; @@ -369,6 +383,10 @@ void Vore_Regurgitate(entity e) e.pusher = e.predator; // allows us to frag players by regurgitating them in deadly pits e.pushltime = time + cvar("g_maxpushtime"); + // if the dead body of the prey is below gibbing health, gib it + e.stat_eaten = 0; // necessary for gibs to show + PlayerGib(e, e.predator); + // regurgitated prey is given this amount of swallow progress, to simulate being more vulnerable if(cvar("g_balance_vore_swallow_speed_fill") && cvar("g_balance_vore_regurgitate_swallowprogress")) { @@ -383,7 +401,7 @@ void Vore_Regurgitate(entity e) regurgitate_dmg = cvar("g_balance_vore_regurgitate_damage"); if(cvar("g_healthsize")) regurgitate_dmg *= e.scale / e.predator.scale; - Damage(e.predator, e.predator, e.predator, regurgitate_dmg, DEATH_REGURGITATION, e.predator.origin, '0 0 0'); + Damage(e.predator, e, e, regurgitate_dmg, DEATH_REGURGITATION, e.predator.origin, '0 0 0'); } PlayerSound(e.predator, playersound_regurgitate, CHAN_VOICE, VOICETYPE_PLAYERSOUND); @@ -400,77 +418,20 @@ void Vore_Regurgitate(entity e) e.predator = world; } -void Vore_DeadPrey_Configure(entity e) -{ - // ran when the keepdeadprey feature is enabled and prey stays inside the stomach after dying - - if(e.fakeprey || !e.stat_eaten) // we already configured everything - return; - - // this entity is like e.predator but for dead prey, to avoid conflicts - e.fakepredator = e.predator; - e.fakeprey = TRUE; - Vore_SetPreyPositions(e.predator); - - // first release the prey from the predator, as dead prey needs to be attached differently - // the predator's stomach load is also decreased, as dead prey doesn't count any more - e.predator = world; - - // now put our dead prey inside the predator's stomach, but only as an effect - e.movetype = MOVETYPE_FOLLOW; - e.takedamage = DAMAGE_NO; - e.solid = SOLID_NOT; - e.aiment = e.fakepredator; -} - -void Vore_DeadPrey_Detach(entity e) -{ - // ran when dead prey must be detached from the stomach (eg: they are respawning) - // should only execute after Vore_DeadPrey_Configure has ran first - - if not(cvar("g_vore_keepdeadprey")) - return; - - e.fakepredator = world; - e.fakeprey = TRUE; // keep fakeprey status - e.stat_eaten = 0; - e.aiment = world; - e.movetype = MOVETYPE_TOSS; -} - -void Vore_PreyRelease(entity e, float pred_disconnect) -{ - if(pred_disconnect) - { - if(e.fakeprey) - Vore_DeadPrey_Detach(e); - else - Vore_Regurgitate(e); - } - else if(self.stat_eaten && !self.fakeprey) - { - // if the keepdeadprey feature is on, don't spit a dead prey's carcass out - if(e.deadflag != DEAD_NO && random() < cvar("g_vore_keepdeadprey")) - Vore_DeadPrey_Configure(e); - else - Vore_Regurgitate(e); - } -} - void Vore_Disconnect() { // frees prey from their predators when someone disconnects or goes spectating, or in other circumstances // prey disconnects or goes spectating while inside someone's belly if(self.stat_eaten) - Vore_PreyRelease(self, TRUE); + Vore_Regurgitate(self); // pred disconnects or goes spectating with players in their belly entity head; FOR_EACH_PLAYER(head) { - if(head.predator == self || head.fakepredator == self) - Vore_PreyRelease(head, TRUE); + if(head.predator == self) + Vore_Regurgitate(head); } Vore_GurgleSound(); // stop the gurgling sound @@ -482,23 +443,33 @@ void Vore_Digest() { // apply digestion to prey + if(self.predator.deadflag != DEAD_NO) // dead predators don't digest + { + self.predator.digesting = FALSE; + return; + } + if(self.health <= cvar("g_balance_vore_digestion_limit")) // don't digest below this amount of health + return; + if(time > self.digestion_step) { // if distributed digestion is enabled, reduce digestion strength by the amount of prey in our stomach - float vore_offset; - vore_offset = 1; + float damage, damage_offset; + + damage_offset = 1; if(cvar("g_balance_vore_digestion_distribute")) // apply distributed digestion damage - vore_offset *= self.predator.stomach_load / self.predator.stomach_maxload; + damage_offset *= self.predator.stomach_load / self.predator.stomach_maxload; if(cvar("g_healthsize") && cvar("g_balance_vore_digestion_scalediff")) // apply player scale to digestion damage - vore_offset *= pow(self.scale / self.predator.scale, cvar("g_balance_vore_digestion_scalediff")); - vore_offset = ceil(vore_offset); + damage_offset *= pow(self.scale / self.predator.scale, cvar("g_balance_vore_digestion_scalediff")); + damage_offset = ceil(damage_offset); - float damage; - damage = cvar("g_balance_vore_digestion_damage") / vore_offset; + damage = cvar("g_balance_vore_digestion_damage") / damage_offset; + if(cvar("g_balance_vore_digestion_damage_death") && self.deadflag != DEAD_NO) // amplify digestion damage for dead prey + damage *= cvar("g_balance_vore_digestion_damage_death"); Damage(self, self.predator, self.predator, damage, DEATH_DIGESTION, self.origin, '0 0 0'); if(cvar("g_balance_vore_digestion_vampire") && self.predator.health < cvar("g_balance_vore_digestion_vampire_stable")) - self.predator.health += cvar("g_balance_vore_digestion_vampire") / vore_offset; + self.predator.health += damage * cvar("g_balance_vore_digestion_vampire"); if (self.predator.digestsound_finished < time) { @@ -508,9 +479,8 @@ void Vore_Digest() self.digestion_step = time + steptime; } - if(self.deadflag != DEAD_NO) - if(stov(cvar_string("g_vore_regurgitatecolor_digest"))) - self.colormod = stov(cvar_string("g_vore_regurgitatecolor_digest")); + if(stov(cvar_string("g_vore_regurgitatecolor_color_digest"))) + self.colormod = stov(cvar_string("g_vore_regurgitatecolor_color_digest")); } .float teamheal_step; @@ -518,6 +488,9 @@ void Vore_Teamheal() { // apply teamheal + if(self.deadflag != DEAD_NO) + return; + if(cvar("g_balance_vore_teamheal") && self.health < cvar("g_balance_vore_teamheal_stable")) if(time > self.teamheal_step) { @@ -538,6 +511,9 @@ void Vore_StomachKick() { // allows prey to kick the predator's stomach and do some damage or attempt to escape + if(self.deadflag != DEAD_NO) + return; + if(time > self.stomachkick_delay && !self.kick_pressed) { float damage, vol; @@ -575,6 +551,9 @@ void Vore_StomachLeave() { // allows players to get out of their predator at will in some circumstances, such as team mates + if(self.deadflag != DEAD_NO) + return; + if(Vore_CanLeave()) Vore_Regurgitate(self); else if(time > self.complain_vore) @@ -592,7 +571,7 @@ void Vore_AutoTaunt() float taunt_time; // predator taunts - if(self.stomach_load && !Stomach_TeamMates_check(self)) + if(self.stomach_load && !Stomach_TeamMates_check(self) && Stomach_HasLivePrey(self)) { if(!self.taunt_soundtime) // taunt_soundtime becomes 0 once the taunt has played { @@ -607,7 +586,7 @@ void Vore_AutoTaunt() } // prey taunts - if(self.stat_eaten && !(teams_matter && self.team == self.predator.team)) + if(self.stat_eaten && !(teams_matter && self.team == self.predator.team) && self.deadflag == DEAD_NO) { if(!self.taunt_soundtime) // taunt_soundtime becomes 0 once the taunt has played { @@ -662,34 +641,49 @@ void Vore_SetSbarRings() } } +.float regurgitatecolor_particles_tick; void Vore() { // main vore code, this is where it all happens Vore_AutoTaunt(); - // wash the goo away from players once they leave the stomach if(!self.stat_eaten) - if(stov(cvar_string("g_vore_regurgitatecolor_release"))) + if(self.modelindex) // not if we're a gibbed dead body or not visible any more if(self.colormod) - if(cvar("g_vore_regurgitatecolor_release_fade")) + if(self.colormod != '1 1 1') { - self.colormod_x += cvar("g_vore_regurgitatecolor_release_fade") * frametime; - if(self.colormod_x > 1) - self.colormod_x = 1; - self.colormod_y += cvar("g_vore_regurgitatecolor_release_fade") * frametime; - if(self.colormod_y > 1) - self.colormod_y = 1; - self.colormod_z += cvar("g_vore_regurgitatecolor_release_fade") * frametime; - if(self.colormod_z > 1) - self.colormod_z = 1; + // slowly wash stomach fluids off players once they're out of the stomach + if(cvar("g_vore_regurgitatecolor_fade")) + if(self.deadflag == DEAD_NO) // not for dead bodies + { + float goo_fade; + goo_fade = cvar("g_vore_regurgitatecolor_fade") * frametime; + goo_fade *= 1 + self.waterlevel; // fade faster when underwater + + self.colormod_x += goo_fade; + if(self.colormod_x > 1) + self.colormod_x = 1; + self.colormod_y += goo_fade; + if(self.colormod_y > 1) + self.colormod_y = 1; + self.colormod_z += goo_fade; + if(self.colormod_z > 1) + self.colormod_z = 1; + } + + // constant particles falling off dirty players + if(cvar("g_vore_regurgitatecolor_particles")) + if(self.regurgitatecolor_particles_tick < time) + { + pointparticles(particleeffectnum("vore_regurgitate_constant"), self.origin, '0 0 0', 1); + self.regurgitatecolor_particles_tick = time + cvar("g_vore_regurgitatecolor_particles") * vlen(self.colormod); // particle time depends on how dirty the player is + } } // set all vore stats Vore_SetSbarRings(); - if(self.fakepredator.classname == "player") - self.stat_eaten = num_for_edict(self.fakepredator); - else if(self.predator.classname == "player") + if(self.predator.classname == "player") { self.stat_stomachload = self.predator.stomach_load; // necessary for the stomach board self.stat_stomachmaxload = self.predator.stomach_maxload; // necessary for the stomach board @@ -840,20 +834,29 @@ void Vore() if(!self.stat_eaten) return; - if(self.deadflag != DEAD_NO) // we're dead, do what we must + if(self.deadflag != DEAD_NO && self.health < cvar("g_balance_vore_digestion_limit")) // make sure health doesn't go below the limit + self.health = cvar("g_balance_vore_digestion_limit"); + + // automatically regurgitate prey that has reached their digestion limit + if(cvar("g_balance_vore_digestion_limit_regurgitate")) + if(self.health <= cvar("g_balance_vore_digestion_limit")) { - Vore_PreyRelease(self, FALSE); + Vore_Regurgitate(self); return; } - if(self.fakeprey) // detach dead prey if their predator died or got eaten - if(self.fakepredator.deadflag != DEAD_NO || self.fakepredator.stat_eaten) - Vore_DeadPrey_Detach(self); - if(self.predator.deadflag != DEAD_NO) // do we want to be in a dead furry x_x + // do we stick around inside dead furries? x_x + if(self.predator.deadflag != DEAD_NO) { - Vore_Regurgitate(self); - return; + if(!cvar("g_balance_vore_deadpredator") || !self.predator.modelindex) // if the predator is gibbed, we are out + { + Vore_Regurgitate(self); + return; + } + if(self.predator.regurgitate_prepare) // abort scheduled regurgitation + self.predator.regurgitate_prepare = 0; } + if(self.predator.stomach_load > self.predator.stomach_maxload) // the predator got beyond his capacity after eating, so some prey must pop out { Vore_Regurgitate(self);