]> de.git.xonotic.org Git - voretournament/voretournament.git/commitdiff
Merge branch 'master' into mirceakitsune/quantity_stomach_load
authorMirceaKitsune <sonichedgehog_hyperblast00@yahoo.com>
Mon, 18 Jul 2011 16:57:13 +0000 (19:57 +0300)
committerMirceaKitsune <sonichedgehog_hyperblast00@yahoo.com>
Mon, 18 Jul 2011 16:57:13 +0000 (19:57 +0300)
15 files changed:
data/balanceVT.cfg
data/qcsrc/client/Main.qc
data/qcsrc/client/main.qh
data/qcsrc/client/sbar.qc
data/qcsrc/common/constants.qh
data/qcsrc/menu/voret/dialog_multiplayer_create_mutators.c
data/qcsrc/server/bot/havocbot/vore_ai.qc
data/qcsrc/server/cl_client.qc
data/qcsrc/server/cl_physics.qc
data/qcsrc/server/cl_player.qc
data/qcsrc/server/defs.qh
data/qcsrc/server/g_world.qc
data/qcsrc/server/miscfunctions.qc
data/qcsrc/server/teamplay.qc
data/qcsrc/server/vore.qc

index f8de96c3f4a711302f9e2d609b9197614f3ba0fd..b422a16d38782ee798eb6836b135056e319fa906 100644 (file)
@@ -185,8 +185,13 @@ set g_balance_grabber_reload_time 2
 // }}}\r
 \r
 // {{{ stomach\r
+set g_balance_vore_action_delay 1 "how many seconds must pass before you can swallow or regurgitate again, after swallowing or regurgitating another player"\r
+set g_balance_vore_load_pred_capacity 100 "capacity percent a player's stomach has, influenced by player size"\r
+set g_balance_vore_load_pred_weight 1 "you get this heavier the more you eat, at 1 a full belly makes you two times heavier"\r
+set g_balance_vore_load_pred_speed 1 "you get this slower the more you eat, at 1 a full belly makes you two times slower"\r
+set g_balance_vore_load_pred_speedcap 800 "when a predator is going faster than this (at full stomach capacity), their prey is squeezed out of them"\r
+set g_balance_vore_load_prey_mass 30 "prey mass, influenced by player size"\r
 set g_balance_vore_swallow_range 140 "distance below which you can swallow another player when facing them"\r
-set g_balance_vore_swallow_limit 3 "how many players can fit in the stomach at a time, may range between 1 and 9"\r
 set g_balance_vore_swallow_speed_fill 2.5 "how long it takes to swallow a player, 0 is instant"\r
 set g_balance_vore_swallow_speed_fill_scalediff 0.5 "fill rate depends on predator size compared to prey size by this amount"\r
 set g_balance_vore_swallow_speed_fill_stomachload 1 "fill rate is influenced by the prey's stomach load"\r
@@ -198,23 +203,19 @@ set g_balance_vore_swallow_stealprey 0.7 "probability of stealing someone's prey
 set g_balance_vore_swallow_dropweapon 0.6 "probability of dropping your weapon when swallowed. 0 = never and 1 = always, does not apply to team mates"\r
 set g_balance_vore_swallow_punchangle 12 "your view gets tilted by this amount when swallowing someone"\r
 set g_balance_vore_regurgitate_damage 5 "predators take this amount of damage whenever regurgitating someone (influenced by player scale difference)"\r
-set g_balance_vore_regurgitate_speedcap 3400 "when a predator is going faster than this, their prey is squeezed out of them, multiplied by stomach load"\r
 set g_balance_vore_regurgitate_swallowprogress 0.5 "regurgitated prey is given this amount of swallow progress, to simulate being more vulnerable (if slow swallowing is enabled)"\r
 set g_balance_vore_regurgitate_force 600 "regurgitated players rocket out at this speed, in the direction the predator is facing"\r
 set g_balance_vore_regurgitate_predatorforce 450 "players are pushed back by this amount when regurgitating someone, opposite of the direction they are facing"\r
 set g_balance_vore_regurgitate_delay 0.5 "regurgitation delay"\r
 set g_balance_vore_regurgitate_punchangle 12 "your view gets tilted by this amount when regurgitating someone"\r
-set g_balance_vore_action_delay 1 "how many seconds must pass before you can swallow or regurgitate again, after swallowing or regurgitating another player"\r
 set g_balance_vore_digestion_damage 4 "amount of damage applied to victims during digestion"\r
 set g_balance_vore_digestion_vampire 1 "amount of health you gain from digestion"\r
 set g_balance_vore_digestion_vampire_stable 150 "maximum amount of health you can gain from digestion (best kept equal or less than g_balance_health_rotstable)"\r
 set g_balance_vore_digestion_distribute 1 "if enabled, digestion is reduced by the amount of prey you have. eg: having 2 prey will reduce digestion strength by 2"\r
 set g_balance_vore_digestion_scalediff 0.5 "if enabled, digestion damage is affected by the size of the predator compared to the size of the prey by this amount"\r
 set g_balance_vore_teamheal 1 "when enabled, having a team mate in your stomach will keep healing them by this amount"\r
-set g_balance_vore_teamheal_stable 150 "maximum amount of health you can gain from a teamheal (best kept equal or less than g_balance_health_rotstable)"\r
-set g_balance_vore_weight_gravity 1 "you get this heavier the more you eat, at 1 each meal makes you two times heavier"\r
-set g_balance_vore_weight_speed 0.15 "you get this slower the more you eat, at 0.5 each meal makes you two times slower"\r
-set g_balance_vore_kick_damage 25 "amount of damage you can do during stomach kick"\r
+set g_balance_vore_teamheal_stable 150 "maximum amount of health you can gain from a teamheal (best kept equal or less than g_balance_health_rotstable)"
+set g_balance_vore_kick_damage 25 "amount of damage you can do during stomach kick"
 set g_balance_vore_kick_delay 0.6 "how many seconds must pass before you can perform another stomach kick"\r
 set g_balance_vore_kick_force 420 "predators are pushed by this amount when stomach kicked, in the direction their prey is facing"\r
 set g_balance_vore_kick_repress 0 "require pressing the fire key each kick rather than holding it down"\r
index 90dce734b673441ad82db7c2dcb771a03272f977..d9449353761b1a90205c748fcb0e4ec61cf1f0c3 100644 (file)
@@ -1054,7 +1054,6 @@ void Ent_Init()
        g_weaponswitchdelay = ReadByte() / 255.0;\r
 \r
        g_vore = ReadShort();\r
-       g_balance_vore_swallow_limit = ReadShort();\r
        g_healthsize = ReadShort();\r
        g_healthsize_min = ReadShort();\r
        g_healthsize_max = ReadShort();\r
index b5801490c5b69385e3678cbdc1d4b750597113d9..245ed88606c3b26393aae8993e1f34843a525dcb 100644 (file)
@@ -167,7 +167,6 @@ float armorblockpercent;
 float g_weaponswitchdelay;\r
 \r
 float g_vore;\r
-float g_balance_vore_swallow_limit;\r
 float g_healthsize, g_healthsize_min, g_healthsize_max;\r
 float armor_max;\r
 float teamheal_max;\r
index 6aec0e8ea76638bba84975c553e5eacf077303b2..deecd121d76665def44f64f95d19020912ca9a24 100644 (file)
@@ -122,7 +122,7 @@ void Sbar_DrawXNum (vector pos, float num, float digits, float showminusplus, fl
        drawstring(pos, final_num, vsize, rgb, alpha, dflags);\r
 }\r
 \r
-void Sbar_DrawXNum_Colored (vector pos, float x, float lettersize, float alpha)\r
+vector Sbar_NumColor (float x)\r
 {\r
        if(x > 200) {\r
                color_x = 0;\r
@@ -144,17 +144,17 @@ void Sbar_DrawXNum_Colored (vector pos, float x, float lettersize, float alpha)
                color_y = 1;\r
                color_z = 0.2 + (x-50)*0.02 * 0.8; // blue value between 0.2 -> 1\r
        }\r
-       else if(x > 20) {\r
+       else if(x > 25) {\r
                color_x = 1;\r
-               color_y = (x-20)*90/27/100; // green value between 0 -> 1\r
-               color_z = (x-20)*90/27/100 * 0.2; // blue value between 0 -> 0.2\r
+               color_y = (x-25)*90/27/100; // green value between 0 -> 1\r
+               color_z = (x-25)*90/27/100 * 0.2; // blue value between 0 -> 0.2\r
        }\r
        else {\r
                color_x = 1;\r
                color_y = 0;\r
                color_z = 0;\r
        }\r
-       Sbar_DrawXNum(pos, x, 3, 0, lettersize, color, alpha, DRAWFLAG_NORMAL);\r
+       return color;\r
 }\r
 \r
 void Cmd_Sbar_SetFields(float argc);\r
@@ -3027,15 +3027,28 @@ void Sbar_Draw (void)
                        drawpic(bottomleft - '0 256 0', "gfx/hud/bg_stomach_status", '256 256 0', StomachStatus_ColorFade(hl_color), cvar("sbar_stomachboard_status_alpha") * sbar_alpha_fg, DRAWFLAG_NORMAL);\r
                        drawstring(bottomleft - '-80 173 0', hl_string, '11 11 0', '1 1 1', sbar_alpha_fg, DRAWFLAG_NORMAL);\r
 \r
-                       float stomach_load;\r
-                       stomach_load = getstati(STAT_VORE_LOAD); // shows the predator's stomach load when we are eaten, and ours otherwise\r
+                       float stomach_load, stomach_maxload; // shows the predator's stomach load when we are eaten, and ours otherwise\r
+                       stomach_load = getstati(STAT_VORE_LOAD);\r
+                       stomach_maxload = getstati(STAT_VORE_MAXLOAD);\r
 \r
                        vector status_pos;\r
-                       string status_text;\r
-                       status_text = strcat(ftos(bound(0, stomach_load, 9)), "/", ftos(bound(0, g_balance_vore_swallow_limit, 9)));\r
-                       status_pos = bottomleft - '-44 171 0';\r
-                       status_pos -= '1 0 0' * stringwidth(status_text, FALSE, '22 22 0') * 0.5;\r
-                       drawstring(status_pos, status_text, '22 22 0', '1 1 1', sbar_alpha_fg, DRAWFLAG_NORMAL);\r
+                       string status_text, status_color;\r
+                       float status_size;\r
+                       status_color = rgb_to_hexcolor(Sbar_NumColor(stomach_maxload));\r
+                       if(stomach_load)\r
+                       {\r
+                               status_text = strcat(ftos(stomach_load), "^8/", status_color, ftos(stomach_maxload), "%");\r
+                               status_pos = bottomleft - '-44 168 0';\r
+                               status_size = 16;\r
+                       }\r
+                       else if(g_healthsize) // no point in showing it otherwise\r
+                       {\r
+                               status_text = strcat(status_color, ftos(stomach_maxload), "%");\r
+                               status_pos = bottomleft - '-44 170 0';\r
+                               status_size = 20;\r
+                       }\r
+                       status_pos -= '1 0 0' * stringwidth(status_text, TRUE, '1 0 0' * status_size) * 0.5;\r
+                       drawcolorcodedstring(status_pos, status_text, '1 1 0' * status_size, sbar_alpha_fg, DRAWFLAG_NORMAL);\r
 \r
                        if(getstati(STAT_VORE_DIGESTING)) // we are currently digesting\r
                                drawpic(bottomleft - '-35 149 0', "gfx/hud/sb_digestion", '16 16 0', '0 1 0', sbar_alpha_fg, DRAWFLAG_NORMAL);\r
@@ -3107,14 +3120,14 @@ void Sbar_Draw (void)
                {\r
                        drawpic(armor_pos + '-8 -13.5 0', "gfx/hud/sb_armor", '16 16 0', '1 1 1', sbar_alpha_fg, DRAWFLAG_NORMAL);\r
                        armor_pos -= '1 0 0' * stringwidth(ftos(x), FALSE, '12 12 0') * 0.5;\r
-                       Sbar_DrawXNum_Colored(armor_pos, x, 12, sbar_alpha_fg);\r
+                       Sbar_DrawXNum(armor_pos, x, 3, 0, 12, Sbar_NumColor(x), sbar_alpha_fg, DRAWFLAG_NORMAL);\r
                }\r
 \r
                // health\r
                x = health;\r
                drawpic(health_pos + '-11 16 0', "gfx/hud/sb_health", '32 32 0', '1 1 1', sbar_alpha_fg, DRAWFLAG_NORMAL);\r
                health_pos -= '1 0 0' * stringwidth(ftos(x), FALSE, '22 22 0') * 0.5;\r
-               Sbar_DrawXNum_Colored(health_pos, x, 22, sbar_alpha_fg);\r
+               Sbar_DrawXNum(health_pos, x, 3, 0, 22, Sbar_NumColor(x), sbar_alpha_fg, DRAWFLAG_NORMAL);\r
 \r
                // ammo\r
                pos_x = bottom_x + 140;\r
index 44f19165628906b02041ddb79bec533dc1518ab9..ea23f8619dcdc7570a2877d4865ba6d3d090bc50 100644 (file)
@@ -281,21 +281,21 @@ const float STAT_WEAPON_CLIPLOAD = 49;
 const float STAT_WEAPON_CLIPSIZE = 50;\r
 const float STAT_LAST_PICKUP = 51;\r
 const float STAT_VORE_LOAD = 52;\r
-const float STAT_VORE_DIGESTING = 53;\r
-const float STAT_VORE_EATEN = 54;\r
-const float STAT_VORE_CANLEAVE = 55;\r
-const float STAT_VORE_CANSWALLOW = 56;\r
-const float STAT_SBRING1_TYPE = 57;\r
-const float STAT_SBRING1_CLIP = 58;\r
-const float STAT_SBRING2_TYPE = 59;\r
-const float STAT_SBRING2_CLIP = 60;\r
+const float STAT_VORE_MAXLOAD = 53;\r
+const float STAT_VORE_DIGESTING = 54;\r
+const float STAT_VORE_EATEN = 55;\r
+const float STAT_VORE_CANLEAVE = 56;\r
+const float STAT_VORE_CANSWALLOW = 57;\r
+const float STAT_SBRING1_TYPE = 58;\r
+const float STAT_SBRING1_CLIP = 59;\r
+const float STAT_SBRING2_TYPE = 60;\r
+const float STAT_SBRING2_CLIP = 61;\r
+const float STAT_HUD = 62;\r
+const float HUD_NORMAL = 0;\r
 const float CTF_STATE_ATTACK = 1;\r
 const float CTF_STATE_DEFEND = 2;\r
 const float CTF_STATE_COMMANDER = 3;\r
 \r
-const float STAT_HUD = 61;\r
-const float HUD_NORMAL = 0;\r
-\r
 // moved that here so the client knows the max.\r
 // # of maps, I'll use arrays for them :P\r
 #define MAPVOTE_COUNT 10\r
index c32f4d90f551f44df4db60d5fc3c9eebf81be864..e6bf101b8833914c1a5da09b314215fa60830125 100644 (file)
@@ -45,7 +45,7 @@ string toStringVoretMutatorsDialog(entity me)
                s = strcat(s, ", Reverse scoring");\r
        if(cvar("g_balance_vore_digestion_damage") >= 1000)\r
                s = strcat(s, ", Instant digestion");\r
-       if(cvar("g_balance_vore_weight_gravity") < 0)\r
+       if(cvar("g_balance_vore_load_pred_weight") < 0)\r
                s = strcat(s, ", Lighten");\r
        if(s == "")\r
                return "None";\r
@@ -113,7 +113,7 @@ void fillVoretMutatorsDialog(entity me)
                setDependent(e, "g_vore_digestion", 1, 1);\r
        me.TR(me);\r
                me.TDempty(me, 0.2);\r
-               me.TD(me, 1, 2, e = makeVoretCheckBoxEx(-0.25, 1, "g_balance_vore_weight_gravity", "Lighten")); // must contain default cvar value for off position\r
+               me.TD(me, 1, 2, e = makeVoretCheckBoxEx(-0.25, 1, "g_balance_vore_load_pred_weight", "Lighten")); // must contain default cvar value for off position\r
 \r
        me.gotoRC(me, me.rows - 1, 0);\r
                me.TD(me, 1, me.columns, e = makeVoretButton("OK", '0 0 0'));\r
index b46f5a2f55d8884bb251358205787d9a986484c6..7c35ff944e003894938f6318019af41659d696bf 100644 (file)
@@ -141,9 +141,9 @@ void Vore_AI()
                if(!cvar("g_vore_reversescoring")) // when reverse scoring is on, it's in the interest of the prey to get eaten, so the predator has nothing to fear
                {
                        if(skill >= 3) // make bots aware of this from skill 3 and up
-                               fear *= 1 + self.stomach_load; // the bigger our stomach, the less we want to put someone else in there
+                               fear *= 1 + self.stomach_load / self.stomach_maxload; // the bigger our stomach, the less we want to put someone else in there
                        if(skill >= 5) // make bots aware of this from skill 5 and up
-                               fear *= 1 + prey.stomach_load; // predators fear prey that have a large stomach
+                               fear *= 1 + prey.stomach_load / prey.stomach_maxload; // predators fear prey that have a large stomach
 
                        if(cvar("g_healthsize"))
                                fear *= (prey.scale / self.scale); // predators fear larger prey and are courageous toward smaller prey
index 2503070e54b0c3f2bf17237a92d8b20c163b00e1..eca3ad9fd69755e9f50e240400ea232a973df46b 100644 (file)
@@ -436,9 +436,9 @@ string setmodel_state()
        newmodel_extension = substring(self.playermodel, strlen(self.playermodel) - 4, 4);\r
 \r
        float vore_state;\r
-       if(self.stomach_load > ceil(g_balance_vore_swallow_limit * 0.6))\r
+       if(self.stomach_load > self.stomach_maxload * 0.6)\r
                vore_state = 3;\r
-       else if(self.stomach_load > ceil(g_balance_vore_swallow_limit * 0.3))\r
+       else if(self.stomach_load > self.stomach_maxload * 0.3)\r
                vore_state = 2;\r
        else if(self.stomach_load)\r
                vore_state = 1;\r
@@ -1053,7 +1053,6 @@ float ClientInit_SendEntity(entity to, float sf)
        WriteByte(MSG_ENTITY, cvar("g_balance_weaponswitchdelay") * 255.0);\r
 \r
        WriteShort(MSG_ENTITY, cvar("g_vore"));\r
-       WriteShort(MSG_ENTITY, g_balance_vore_swallow_limit);\r
        WriteShort(MSG_ENTITY, cvar("g_healthsize"));\r
        WriteShort(MSG_ENTITY, cvar("g_healthsize_min"));\r
        WriteShort(MSG_ENTITY, cvar("g_healthsize_max"));\r
@@ -2107,6 +2106,7 @@ void SpectateCopy(entity spectatee) {
        self.stomach_load = spectatee.stomach_load;\r
        self.stat_eaten = spectatee.stat_eaten;\r
        self.stat_stomachload = spectatee.stat_stomachload;\r
+       self.stomach_maxload = spectatee.stomach_maxload;\r
        self.stat_digesting = spectatee.stat_digesting;\r
        self.stat_canleave = spectatee.stat_canleave;\r
        self.stat_canswallow = spectatee.stat_canswallow;\r
index 4394bdba850ac7c34a431509b44069c102c25036..df1c3a458a88cf48de4c1fa80d17ab1530758b7e 100644 (file)
@@ -507,8 +507,8 @@ void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float acce
        if(speedclamp)\r
                accelqw = -accelqw;\r
 \r
-       if(cvar("g_balance_vore_weight_gravity") > 0) // apply stomach weight\r
-               wishspeed *= 1 - bound(0, self.stomach_load * cvar("g_balance_vore_weight_speed"), 1);\r
+       if(cvar("g_balance_vore_load_pred_weight") > 0) // apply stomach weight\r
+               wishspeed /= 1 + (self.stomach_load / self.stomach_maxload) * cvar("g_balance_vore_load_pred_speed");\r
        if(cvar("g_healthsize")) // if we are smaller or larger, we run slower or faster\r
                wishspeed *= (1 - cvar("g_healthsize_movementfactor")) + cvar("g_healthsize_movementfactor") * self.scale; \r
        if(self.swallow_progress_prey) // cut speed based on swallow progress for prey\r
index 829a6501b777bf234d15110d7ad8a240b123fef3..411499c4c9e3af876f7418628526183bd6fe549c 100644 (file)
@@ -1332,7 +1332,7 @@ void GlobalSound(string sample, float chan, float voicetype)
                        break;\r
                case VOICETYPE_GURGLE:\r
                        if(self.stomach_load)\r
-                               sound(self, chan, sample, vol * self.stomach_load / g_balance_vore_swallow_limit, ATTN_NORM);\r
+                               sound(self, chan, sample, bound(0, vol * (self.stomach_load / self.stomach_maxload), 1), ATTN_NORM);\r
                        else\r
                                stopsound(self, chan);\r
                        break;\r
index 364e2fcc9d9f69cae90a135b920a5d89a114011b..11d295d25c38c62a3523f210b5b8c5690bcab154 100644 (file)
@@ -21,7 +21,6 @@ float ctf_score_value(string parameter);
 \r
 float g_dm, g_domination, g_ctf, g_tdm, g_keyhunt, g_onslaught, g_assault, g_arena, g_ca, g_lms, g_race, g_cts, g_rpg;\r
 float g_cloaked, g_footsteps, g_jump_grunt, g_midair, g_norecoil, g_vampire, g_bloodloss;\r
-float g_balance_vore_swallow_limit;\r
 float g_warmup_limit;\r
 float g_warmup_allguns;\r
 float g_warmup_allow_timeout;\r
@@ -70,10 +69,10 @@ float maxclients;
 .entity fakepredator;\r
 .float swallow_progress_prey, swallow_progress_pred;\r
 .float digesting;\r
-.float stomach_load;\r
+.float stomach_load, stomach_maxload;\r
 .float weapon_delay;\r
 .float fakeprey;\r
-.float stat_eaten, stat_stomachload, stat_digesting, stat_canleave, stat_canswallow;\r
+.float stat_eaten, stat_stomachload, stat_stomachmaxload, stat_digesting, stat_canleave, stat_canswallow;\r
 .float dropweapon_check;\r
 \r
 // Fields\r
index ababcf9357ba377b5b54941352a20596caea085f..331e3a685333246da39732e92820c4d11ea2fb88 100644 (file)
@@ -659,6 +659,7 @@ void spawnfunc_worldspawn (void)
        addstat(STAT_LAST_PICKUP, AS_FLOAT, last_pickup);\r
        addstat(STAT_WINNING, AS_FLOAT, winning);\r
        addstat(STAT_VORE_LOAD, AS_INT, stat_stomachload);\r
+       addstat(STAT_VORE_MAXLOAD, AS_INT, stomach_maxload);\r
        addstat(STAT_VORE_CANSWALLOW, AS_INT, stat_canswallow);\r
        addstat(STAT_VORE_DIGESTING, AS_INT, stat_digesting);\r
        addstat(STAT_VORE_EATEN, AS_INT, stat_eaten);\r
index 2f36d6073eb03ecbf85862c12395cb15aba0be5b..d8c72f49cb03da9f54469147ba68ac5063bbcca4 100644 (file)
@@ -1017,7 +1017,6 @@ void readlevelcvars(void)
        g_norecoil = cvar("g_norecoil");\r
        g_vampire = cvar("g_vampire");\r
        g_bloodloss = cvar("g_bloodloss");\r
-       g_balance_vore_swallow_limit = bound(1, cvar("g_balance_vore_swallow_limit"), 9); // may only range between 1 and 9\r
        sv_maxidle = cvar("sv_maxidle");\r
        sv_maxidle_spectatorsareidle = cvar("sv_maxidle_spectatorsareidle");\r
        sv_pogostick = cvar("sv_pogostick");\r
index 492fbf5c015934ea16c3e39e0b5fd953f256800e..05a793c91e989604bc97fb7ad1fc1016b10f83aa 100644 (file)
@@ -492,7 +492,7 @@ void PrintWelcomeMessage(entity pl)
                modifications = strcat(modifications, ", Reverse scoring");\r
        if(cvar("g_balance_vore_digestion_damage") >= 1000)\r
                modifications = strcat(modifications, ", Instant digestion");\r
-       if(cvar("g_balance_vore_weight_gravity") < 0)\r
+       if(cvar("g_balance_vore_load_pred_weight") < 0)\r
                modifications = strcat(modifications, ", Lighten");\r
        modifications = substring(modifications, 2, strlen(modifications) - 2);\r
 \r
index 90b0bfaefe7cf3ddc13316b3d4b7935fcb5556c2..078c5b4fd76f3501e4fab6617e158fe0370b2636 100644 (file)
@@ -1,7 +1,7 @@
 .float regurgitate_prepare;\r
 .float stomachkick_delay, system_delay, action_delay, digest_button_delay_time, regurgitate_button_delay_time;\r
 .float complain_vore;\r
-.float vore_oldmovetype, vore_oldsolid, vore_oldstomachload;\r
+.float vore_oldmovetype, vore_oldsolid;\r
 \r
 const float system_delay_time = 0.1;\r
 const float complain_delay_time = 1;\r
@@ -40,15 +40,19 @@ float Swallow_condition_check(entity prey)
        if(prey.classname == "player" && !prey.stat_eaten && prey.deadflag == DEAD_NO) // we can't swallow someone who's already in someone else's stomach\r
        if(self.classname == "player" && !self.stat_eaten && self.deadflag == DEAD_NO) // we can't swallow players while inside someone's stomach ourselves\r
        if(!self.BUTTON_REGURGITATE && time > self.action_delay)\r
-       if not(vlen(self.velocity) > cvar("g_balance_vore_regurgitate_speedcap") / (1 + self.stomach_load))\r
        {\r
+               float prey_mass;\r
+               prey_mass = cvar("g_balance_vore_load_prey_mass");\r
+               if(cvar("g_healthsize"))\r
+                       prey_mass *= prey.scale;\r
+\r
                string swallow_complain;\r
                if(teams_matter && prey.team == self.team && !cvar("g_vore_teamvore"))\r
                        swallow_complain = "You cannot swallow your team mates\n";\r
                else if(!cvar("g_vore_spawnshield") && prey.spawnshieldtime > time)\r
                        swallow_complain = "You cannot swallow someone protected by the spawn shield\n";\r
-               else if(self.stomach_load >= g_balance_vore_swallow_limit)\r
-                       swallow_complain = strcat("You cannot swallow more than ^2", ftos(g_balance_vore_swallow_limit), "^7 players at a time\n");\r
+               else if(self.stomach_load + prey_mass > self.stomach_maxload)\r
+                       swallow_complain = strcat("You don't have any room to swallow this player. Their mass is ^3", ftos(prey_mass), "^7 and your remaining capacity is ^3", ftos(self.stomach_maxload - self.stomach_load), "\n");\r
                else if(cvar("g_vore_biggergut") && prey.stomach_load > self.stomach_load)\r
                        swallow_complain = "You cannot swallow someone with a bigger stomach than yours\n";\r
                else if(cvar("g_vore_biggersize") && prey.scale > self.scale)\r
@@ -100,65 +104,31 @@ float Vore_CanLeave()
 }\r
 \r
 // position the camera properly for prey\r
-void Vore_SetPreyPositions()\r
+void Vore_SetPreyPositions(entity pred)\r
 {\r
-       // self is the predator and head is the prey\r
+       // pred is the predator and head is the prey\r
 \r
        local entity head;\r
        local vector origin_apply;\r
-       local float position_counter;\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 run a loop on all players in the same stomach.\r
-       // For each player, the origin is updated, then a new origin is used for the next player.\r
-       // This requires that no more than 9 players may be in the stomach at a time!\r
+       // else all players overlap in the center. To do this, we use a random origin on all players in the same stomach.\r
        FOR_EACH_PLAYER(head)\r
        {\r
-               if(head.predator == self)\r
+               if(head.predator == pred)\r
                {\r
-                       switch(position_counter)\r
-                       {\r
-                               case 0:\r
-                                       origin_apply = '0 0 0'; // first occupant sits in the middle\r
-                                       break;\r
-                               case 1:\r
-                                       origin_apply = '1 0 0'; // second occupant sits in the front\r
-                                       break;\r
-                               case 2:\r
-                                       origin_apply = '-1 0 0'; // third occupant sits in the back\r
-                                       break;\r
-                               case 3:\r
-                                       origin_apply = '0 1 0'; // fourth occupant sits in the right\r
-                                       break;\r
-                               case 4:\r
-                                       origin_apply = '0 -1 0'; // fifth occupant sits in the left\r
-                                       break;\r
-                               case 5:\r
-                                       origin_apply = '1 1 0'; // sixth occupant sits in the front-right\r
-                                       break;\r
-                               case 6:\r
-                                       origin_apply = '-1 1 0'; // seventh occupant sits in the back-right\r
-                                       break;\r
-                               case 7:\r
-                                       origin_apply = '1 -1 0'; // eigth occupant sits in the front-left\r
-                                       break;\r
-                               case 8:\r
-                                       origin_apply = '-1 -1 0'; // ninth occupant sits in the back-left\r
-                                       break;\r
-                               default:\r
-                                       break;\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 = PL_PREY_VIEW_OFS + origin_apply * cvar("g_vore_neighborprey_distance");\r
-                       head.view_ofs_z *= self.scale; // stomach center depends on predator scale\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 - self.scale) * cvar("g_healthsize_vore_pos");\r
+                               prey_height = (head.scale - pred.scale) * cvar("g_healthsize_vore_pos");\r
                        head.view_ofs_z += prey_height;\r
-\r
-                       position_counter += 1;\r
                }\r
        }\r
 }\r
@@ -175,16 +145,36 @@ void Vore_GurgleSound()
        }\r
 }\r
 \r
-void Vore_WeightApply(entity e)\r
+void Vore_StomachLoad_Apply()\r
 {\r
-       // apply stomach weight that makes you heavier the more you eat\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
 \r
-       if(e.stomach_load != e.vore_oldstomachload)\r
-               e.gravity += 1 + (e.stomach_load * cvar("g_balance_vore_weight_gravity") - e.vore_oldstomachload);\r
-       if(e.gravity == 0)\r
-               e.gravity = 0.00001; // 0 becomes 1 for gravity, so do this to allow 0 gravity\r
-       e.vore_oldstomachload = e.stomach_load;\r
+       entity e;\r
+       float prey_mass;\r
+\r
+       // apply the stomach capacity of the predator\r
+       self.stomach_maxload = cvar("g_balance_vore_load_pred_capacity");\r
+       if(cvar("g_healthsize"))\r
+               self.stomach_maxload *= self.scale;\r
+       self.stomach_maxload = floor(self.stomach_maxload);\r
+\r
+       self.stomach_load = 0; // start from zero\r
+       FOR_EACH_PLAYER(e)\r
+       {\r
+               if(e.predator == self)\r
+               {\r
+                       prey_mass = cvar("g_balance_vore_load_prey_mass");\r
+                       if(cvar("g_healthsize"))\r
+                               prey_mass *= e.scale;\r
+                       self.stomach_load += floor(prey_mass);\r
+               }\r
+       }\r
+\r
+       // apply weight\r
+       self.gravity = 1 + (self.stomach_load / self.stomach_maxload) * cvar("g_balance_vore_load_pred_weight");\r
+       if(!self.gravity && self.stomach_load)\r
+               self.gravity = 0.00001; // 0 becomes 1 for gravity, so do this to allow 0 gravity\r
 }\r
 \r
 void Vore_AutoDigest(entity e)\r
@@ -310,12 +300,11 @@ void Vore_Swallow(entity e)
        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.stomach_load += 1;\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
-       Vore_WeightApply(e.predator);\r
        Vore_AutoDigest(e.predator);\r
+       Vore_SetPreyPositions(e.predator);\r
 \r
        // block firing for a small amount of time, or we'll be firing the next frame after we swallow\r
        e.predator.weapon_delay = time + button_delay_time;\r
@@ -401,10 +390,9 @@ void Vore_Regurgitate(entity e)
        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.stomach_load -= 1;\r
        e.predator.regurgitate_prepare = 0;\r
        e.predator.action_delay = time + cvar("g_balance_vore_action_delay");\r
-       Vore_WeightApply(e.predator);\r
+       Vore_SetPreyPositions(e.predator);\r
 \r
        // block firing for a small amount of time, or we'll be firing the next frame\r
        e.weapon_delay = time + button_delay_time;\r
@@ -422,11 +410,10 @@ void Vore_DeadPrey_Configure(entity e)
        // this entity is like e.predator but for dead prey, to avoid conflicts\r
        e.fakepredator = e.predator;\r
        e.fakeprey = TRUE;\r
+       Vore_SetPreyPositions(e.predator);\r
 \r
        // first release the prey from the predator, as dead prey needs to be attached differently\r
        // the predator's stomach load is also decreased, as dead prey doesn't count any more\r
-       e.predator.stomach_load -= 1;\r
-       Vore_WeightApply(e.predator);\r
        e.predator = world;\r
 \r
        // now put our dead prey inside the predator's stomach, but only as an effect\r
@@ -497,23 +484,21 @@ void Vore_Digest()
 \r
        if(time > self.digestion_step)\r
        {\r
-               // if distributed digestion is enabled, reduce digestion strength by the number of prey in our stomach\r
-               float reduce;\r
-               if(cvar("g_balance_vore_digestion_distribute"))\r
-                       reduce = self.predator.stomach_load;\r
-               else\r
-                       reduce = 1;\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
+               if(cvar("g_balance_vore_digestion_distribute")) // apply distributed digestion damage\r
+                       vore_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
 \r
                float damage;\r
-               damage = cvar("g_balance_vore_digestion_damage") / reduce;\r
-\r
-               // apply player scale to digestion damage\r
-               if(cvar("g_healthsize") && cvar("g_balance_vore_digestion_scalediff"))\r
-                       damage *= pow(self.predator.scale / self.scale, cvar("g_balance_vore_digestion_scalediff"));\r
+               damage = cvar("g_balance_vore_digestion_damage") / vore_offset;\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") / reduce;\r
+                       self.predator.health += cvar("g_balance_vore_digestion_vampire") / vore_offset;\r
 \r
                if (self.predator.digestsound_finished < time)\r
                {\r
@@ -707,12 +692,14 @@ void Vore()
        else if(self.predator.classname == "player")\r
        {\r
                self.stat_stomachload = self.predator.stomach_load; // necessary for the stomach board\r
+               self.stat_stomachmaxload = self.predator.stomach_maxload; // necessary for the stomach board\r
                self.stat_digesting = self.predator.digesting; // necessary for the stomach board\r
                self.stat_eaten = num_for_edict(self.predator);\r
        }\r
        else\r
        {\r
                self.stat_stomachload = self.stomach_load;\r
+               self.stat_stomachmaxload = self.stomach_maxload;\r
                self.stat_digesting = self.digesting;\r
                self.stat_eaten = 0;\r
        }\r
@@ -759,6 +746,9 @@ void Vore()
                }\r
        }\r
 \r
+       // set the predator's stomach load and capacity\r
+       Vore_StomachLoad_Apply();\r
+\r
        // apply delays and skip the vore system under some circumstances\r
        if(!cvar("g_vore")) // the vore system is disabled\r
        {\r
@@ -847,26 +837,34 @@ void Vore()
 // Code that addresses the prey:\r
 // --------------------------------\r
 \r
-       Vore_SetPreyPositions();\r
-\r
-       // keepdeadprey - detach dead prey if their predator died or got swallowed\r
-       if(self.fakeprey)\r
-       if(self.fakepredator.deadflag != DEAD_NO || self.fakepredator.stat_eaten)\r
-               Vore_DeadPrey_Detach(self);\r
-\r
        if(!self.stat_eaten)\r
                return;\r
 \r
-       if(self.deadflag != DEAD_NO)\r
+       if(self.deadflag != DEAD_NO) // we're dead, do what we must\r
        {\r
                Vore_PreyRelease(self, FALSE);\r
                return;\r
        }\r
 \r
-       if(self.predator.deadflag != DEAD_NO)\r
+       if(self.fakeprey) // detach dead prey if their predator died or got eaten\r
+       if(self.fakepredator.deadflag != DEAD_NO || self.fakepredator.stat_eaten)\r
+               Vore_DeadPrey_Detach(self);\r
+       if(self.predator.deadflag != DEAD_NO) // do we want to be in a dead furry x_x\r
+       {\r
+               Vore_Regurgitate(self);\r
+               return;\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
-       else if(vlen(self.predator.velocity) > cvar("g_balance_vore_regurgitate_speedcap") / (1 + self.predator.stomach_load))\r
+               return;\r
+       }\r
+       if(cvar("g_balance_vore_load_pred_speedcap") && vlen(self.predator.velocity) >= cvar("g_balance_vore_load_pred_speedcap") / (self.predator.stomach_load / self.predator.stomach_maxload)) // predator's going too fast, gets sick and throws up\r
+       {\r
+dprint(strcat(ftos(cvar("g_balance_vore_load_pred_speedcap") / (self.predator.stomach_load / self.predator.stomach_maxload)), " --------\n"));\r
                Vore_Regurgitate(self);\r
+               return;\r
+       }\r
 \r
        // apply delayed regurgitating if it was scheduled\r
        if(self.predator.regurgitate_prepare && time > self.predator.regurgitate_prepare)\r