]> git.xonotic.org Git - voretournament/voretournament.git/blobdiff - data/qcsrc/server/vore.qc
Consumable items now add to stomach load as well
[voretournament/voretournament.git] / data / qcsrc / server / vore.qc
index 274dae6a4ad3b90aed8cfcd558118b6cc20464af..22528981ec0f88161868326a7f5f3af0d44b1d4d 100644 (file)
@@ -89,6 +89,18 @@ float Stomach_TeamMates_check(entity pred)
        return FALSE;\r
 }\r
 \r
+float Stomach_HasLivePrey(entity pred)\r
+{\r
+       entity head;\r
+       FOR_EACH_PLAYER(head)\r
+       {\r
+               if(head.predator == pred)\r
+               if(head.deadflag == DEAD_NO)\r
+                       return TRUE;\r
+       }\r
+       return FALSE;\r
+}\r
+\r
 float Vore_CanLeave()\r
 {\r
        if(self.stat_eaten)\r
@@ -109,7 +121,6 @@ void Vore_SetPreyPositions(entity pred)
        // pred is the predator and head is the prey\r
 \r
        local entity head;\r
-       local vector origin_apply;\r
 \r
        // In order to allow prey to see each other in the stomach, we must position each occupant differently,\r
        // else all players overlap in the center. To do this, we use a random origin on all players in the same stomach.\r
@@ -117,18 +128,10 @@ void Vore_SetPreyPositions(entity pred)
        {\r
                if(head.predator == pred)\r
                {\r
-                       origin_apply_x = PL_PREY_VIEW_OFS_x + crandom() * cvar("g_vore_neighborprey_distance");\r
-                       origin_apply_y = PL_PREY_VIEW_OFS_y + crandom() * cvar("g_vore_neighborprey_distance");\r
-                       origin_apply_z = PL_PREY_VIEW_OFS_z;\r
-\r
                        // since prey have their predators set as an aiment, view_ofs will specify the real origin of prey, not just the view offset\r
-                       head.view_ofs = origin_apply;\r
-                       head.view_ofs_z *= pred.scale; // stomach center depends on predator scale\r
-\r
-                       // change prey height based on scale\r
-                       float prey_height;\r
-                               prey_height = (head.scale - pred.scale) * cvar("g_healthsize_vore_pos");\r
-                       head.view_ofs_z += prey_height;\r
+                       head.view_ofs_x = PL_PREY_VIEW_OFS_x + crandom() * cvar("g_vore_neighborprey_distance");\r
+                       head.view_ofs_y = PL_PREY_VIEW_OFS_y + crandom() * cvar("g_vore_neighborprey_distance");\r
+                       head.view_ofs_z = PL_PREY_VIEW_OFS_z;\r
                }\r
        }\r
 }\r
@@ -149,6 +152,8 @@ void Vore_StomachLoad_Apply()
 {\r
        // apply stomach weight that makes you heavier and larger the more you eat\r
        // slowing the player is done in cl_physics.qc\r
+       if(self.classname != "player")\r
+               return;\r
 \r
        entity e;\r
        float prey_mass;\r
@@ -170,6 +175,11 @@ void Vore_StomachLoad_Apply()
                        self.stomach_load += floor(prey_mass);\r
                }\r
        }\r
+       for(e = world; (e = find(e, classname, "consumable")); )\r
+       {\r
+               if(e.predator == self)\r
+                       self.stomach_load += floor(self.dmg);\r
+       }\r
 \r
        // apply weight\r
        self.gravity = 1 + (self.stomach_load / self.stomach_maxload) * cvar("g_balance_vore_load_pred_weight");\r
@@ -273,6 +283,7 @@ void Vore_Swallow(entity e)
 \r
        e.vore_oldmovetype = e.movetype;\r
        e.vore_oldsolid = e.solid;\r
+       e.punchvector_z = cvar("g_balance_vore_swallow_prey_punchvector");\r
 \r
        e.predator = self;\r
        setorigin(e, e.predator.origin);\r
@@ -299,7 +310,7 @@ void Vore_Swallow(entity e)
 \r
        PlayerSound(e.predator, playersound_swallow, CHAN_VOICE, VOICETYPE_PLAYERSOUND);\r
        setanim(e.predator, e.predator.anim_pain1, FALSE, TRUE, TRUE); // looks good for swallowing / regurgitating\r
-       e.predator.punchangle_x -= cvar("g_balance_vore_swallow_punchangle");\r
+       e.predator.punchangle_x -= cvar("g_balance_vore_swallow_predator_punchangle");\r
        e.predator.regurgitate_prepare = 0;\r
        e.predator.spawnshieldtime = 0; // lose spawn shield when we vore\r
        e.predator.hitsound += 1; // play this for team mates too, as we could be swallowing them to heal them\r
@@ -353,6 +364,15 @@ void Vore_Regurgitate(entity e)
        if(e.health > 0) // leave SOLID_NOT for dead bodies\r
                e.solid = e.vore_oldsolid;\r
        e.view_ofs_z = PL_VIEW_OFS_z;\r
+       e.punchvector_z = -cvar("g_balance_vore_regurgitate_prey_punchvector");\r
+\r
+       // if the prey has been fully digested, silently detach them\r
+       if(e.deadflag != DEAD_NO && e.health <= cvar("g_balance_vore_digestion_limit"))\r
+       {\r
+               e.predator = world;\r
+               e.modelindex = 0; // hide the dead body\r
+               return;\r
+       }\r
 \r
        // apply velocities\r
        local vector oldforward, oldright, oldup;\r
@@ -369,6 +389,10 @@ void Vore_Regurgitate(entity e)
        e.pusher = e.predator; // allows us to frag players by regurgitating them in deadly pits\r
        e.pushltime = time + cvar("g_maxpushtime");\r
 \r
+       // if the dead body of the prey is below gibbing health, gib it\r
+       e.stat_eaten = 0; // necessary for gibs to show\r
+       PlayerGib(e, e.predator);\r
+\r
        // regurgitated prey is given this amount of swallow progress, to simulate being more vulnerable\r
        if(cvar("g_balance_vore_swallow_speed_fill") && cvar("g_balance_vore_regurgitate_swallowprogress"))\r
        {\r
@@ -383,13 +407,13 @@ void Vore_Regurgitate(entity e)
                regurgitate_dmg = cvar("g_balance_vore_regurgitate_damage");\r
                if(cvar("g_healthsize"))\r
                        regurgitate_dmg *= e.scale / e.predator.scale;\r
-               Damage(e.predator, e.predator, e.predator, regurgitate_dmg, DEATH_REGURGITATION, e.predator.origin, '0 0 0');\r
+               Damage(e.predator, e, e, regurgitate_dmg, DEATH_REGURGITATION, e.predator.origin, '0 0 0');\r
        }\r
 \r
        PlayerSound(e.predator, playersound_regurgitate, CHAN_VOICE, VOICETYPE_PLAYERSOUND);\r
        setanim(e.predator, e.predator.anim_pain1, FALSE, TRUE, TRUE); // looks good for swallowing / regurgitating\r
        pointparticles(particleeffectnum("vore_regurgitate"), e.predator.origin, '0 0 0', 1);\r
-       e.predator.punchangle_x += cvar("g_balance_vore_regurgitate_punchangle");\r
+       e.predator.punchangle_x += cvar("g_balance_vore_regurgitate_predator_punchangle");\r
        e.predator.regurgitate_prepare = 0;\r
        e.predator.action_delay = time + cvar("g_balance_vore_action_delay");\r
        Vore_SetPreyPositions(e.predator);\r
@@ -425,23 +449,33 @@ void Vore_Digest()
 {\r
        // apply digestion to prey\r
 \r
+       if(self.predator.deadflag != DEAD_NO) // dead predators don't digest\r
+       {\r
+               self.predator.digesting = FALSE;\r
+               return;\r
+       }\r
+       if(self.health <= cvar("g_balance_vore_digestion_limit")) // don't digest below this amount of health\r
+               return;\r
+\r
        if(time > self.digestion_step)\r
        {\r
                // if distributed digestion is enabled, reduce digestion strength by the amount of prey in our stomach\r
-               float vore_offset;\r
-               vore_offset = 1;\r
+               float damage, damage_offset;\r
+\r
+               damage_offset = 1;\r
                if(cvar("g_balance_vore_digestion_distribute")) // apply distributed digestion damage\r
-                       vore_offset *= self.predator.stomach_load / self.predator.stomach_maxload;\r
+                       damage_offset *= self.predator.stomach_load / self.predator.stomach_maxload;\r
                if(cvar("g_healthsize") && cvar("g_balance_vore_digestion_scalediff")) // apply player scale to digestion damage\r
-                       vore_offset *= pow(self.scale / self.predator.scale, cvar("g_balance_vore_digestion_scalediff"));\r
-               vore_offset = ceil(vore_offset);\r
+                       damage_offset *= pow(self.scale / self.predator.scale, cvar("g_balance_vore_digestion_scalediff"));\r
+               damage_offset = ceil(damage_offset);\r
 \r
-               float damage;\r
-               damage = cvar("g_balance_vore_digestion_damage") / vore_offset;\r
+               damage = cvar("g_balance_vore_digestion_damage") / damage_offset;\r
+               if(cvar("g_balance_vore_digestion_damage_death") && self.deadflag != DEAD_NO) // amplify digestion damage for dead prey\r
+                       damage *= cvar("g_balance_vore_digestion_damage_death");\r
 \r
                Damage(self, self.predator, self.predator, damage, DEATH_DIGESTION, self.origin, '0 0 0');\r
                if(cvar("g_balance_vore_digestion_vampire") && self.predator.health < cvar("g_balance_vore_digestion_vampire_stable"))\r
-                       self.predator.health += cvar("g_balance_vore_digestion_vampire") / vore_offset;\r
+                       self.predator.health += damage * cvar("g_balance_vore_digestion_vampire");\r
 \r
                if (self.predator.digestsound_finished < time)\r
                {\r
@@ -460,6 +494,9 @@ void Vore_Teamheal()
 {\r
        // apply teamheal\r
 \r
+       if(self.deadflag != DEAD_NO)\r
+               return;\r
+\r
        if(cvar("g_balance_vore_teamheal") && self.health < cvar("g_balance_vore_teamheal_stable"))\r
        if(time > self.teamheal_step)\r
        {\r
@@ -480,6 +517,9 @@ void Vore_StomachKick()
 {\r
        // allows prey to kick the predator's stomach and do some damage or attempt to escape\r
 \r
+       if(self.deadflag != DEAD_NO)\r
+               return;\r
+\r
        if(time > self.stomachkick_delay && !self.kick_pressed)\r
        {\r
                float damage, vol;\r
@@ -517,6 +557,9 @@ void Vore_StomachLeave()
 {\r
        // allows players to get out of their predator at will in some circumstances, such as team mates\r
 \r
+       if(self.deadflag != DEAD_NO)\r
+               return;\r
+\r
        if(Vore_CanLeave())\r
                Vore_Regurgitate(self);\r
        else if(time > self.complain_vore)\r
@@ -534,7 +577,7 @@ void Vore_AutoTaunt()
        float taunt_time;\r
 \r
        // predator taunts\r
-       if(self.stomach_load && !Stomach_TeamMates_check(self))\r
+       if((self.swallow_progress_pred || (self.stomach_load && Stomach_HasLivePrey(self))) && !Stomach_TeamMates_check(self))\r
        {\r
                if(!self.taunt_soundtime) // taunt_soundtime becomes 0 once the taunt has played\r
                {\r
@@ -549,7 +592,7 @@ void Vore_AutoTaunt()
        }\r
 \r
        // prey taunts\r
-       if(self.stat_eaten && !(teams_matter && self.team == self.predator.team))\r
+       if((self.swallow_progress_prey || (self.stat_eaten && !(teams_matter && self.team == self.predator.team))) && self.deadflag == DEAD_NO)\r
        {\r
                if(!self.taunt_soundtime) // taunt_soundtime becomes 0 once the taunt has played\r
                {\r
@@ -797,17 +840,29 @@ void Vore()
        if(!self.stat_eaten)\r
                return;\r
 \r
-       if(self.deadflag != DEAD_NO) // we're dead, do what we must\r
+       if(self.deadflag != DEAD_NO && self.health < cvar("g_balance_vore_digestion_limit")) // make sure health doesn't go below the limit\r
+               self.health = cvar("g_balance_vore_digestion_limit");\r
+\r
+       // automatically regurgitate prey that has reached their digestion limit\r
+       if(cvar("g_balance_vore_digestion_limit_regurgitate"))\r
+       if(self.health <= cvar("g_balance_vore_digestion_limit"))\r
        {\r
                Vore_Regurgitate(self);\r
                return;\r
        }\r
 \r
-       if(self.predator.deadflag != DEAD_NO) // do we want to be in a dead furry x_x\r
+       // do we stick around inside dead furries? x_x\r
+       if(self.predator.deadflag != DEAD_NO)\r
        {\r
-               Vore_Regurgitate(self);\r
-               return;\r
+               if(!cvar("g_balance_vore_deadpredator") || !self.predator.modelindex) // if the predator is gibbed, we are out\r
+               {\r
+                       Vore_Regurgitate(self);\r
+                       return;\r
+               }\r
+               if(self.predator.regurgitate_prepare) // abort scheduled regurgitation\r
+                       self.predator.regurgitate_prepare = 0;\r
        }\r
+\r
        if(self.predator.stomach_load > self.predator.stomach_maxload) // the predator got beyond his capacity after eating, so some prey must pop out\r
        {\r
                Vore_Regurgitate(self);\r
@@ -848,4 +903,7 @@ void Vore()
        // Ugly workaround for a Keyhunt issue. Your team's key can still be given to you while in the stomach\r
        // (at round start), which is pretty ugly and wrong. So attempt to drop keys each frame for prey\r
        kh_Key_DropAll(self, FALSE);\r
+\r
+       // always position camera at the center of the stomach, to reduce probability of the view poking out\r
+       self.view_ofs_z = PL_PREY_VIEW_OFS_z * self.predator.scale;\r
 }
\ No newline at end of file