-.float status_teamhealing; // 0 = can't team heal, 1 = can team heal, 2 = team healing currently
-
-entity Swallow_distance_check_bot(entity e)
-{
- // check if we can swallow a player instead of firing our weapon
- vector w_shotorg, w_shotdir;
- w_shotorg = self.origin + self.view_ofs;
- w_shotdir = v_forward;
-
- WarpZone_traceline_antilag(e, w_shotorg, w_shotorg + w_shotdir * cvar("g_balance_vore_swallow_range"), FALSE, e, ANTILAG_LATENCY(e));
- if(trace_fraction < 1)
- if(trace_ent.classname == "player")
- return trace_ent;
- return world;
-}
+.float status_teamhealing; // 0 = can't team heal, 1 = can team heal, 2 = team healing right now
float Swallow_condition_check_bot(entity prey)
{
- // checks the necessary conditions for a bot to swallow another player
- if(prey != self && prey.classname == "player" && prey.eater.classname != "player" && prey.deadflag == DEAD_NO && !prey.BUTTON_CHAT) // we can't swallow someone who's already in someone else's stomach
- if(self.eater.classname != "player" && self.stomach_load < cvar("g_balance_vore_swallow_limit") && self.deadflag == DEAD_NO) // we can't swallow players while inside someone's stomach ourselves
- if not(cvar("g_vore_biggergut") && prey.stomach_load > self.stomach_load)
+ // checks the necessary conditions for a bot to swallow a player
+
+ if(Swallow_condition_check(prey)) // check the normal conditions of the vore system
+ if not(prey.BUTTON_CHAT) // don't eat players who are chatting
if(self.health > cvar("g_balance_vore_kick_damage_max")) // explained below
return TRUE;
return FALSE;
void Vore_AI_Teamheal(entity prey)
{
- // allows bots to take advantage of the teamheal feature, and use it to heal damaged team mates
+ // allows bots to use the teamheal feature and heal damaged team mates
+ // the prey entity is only used when it's available (a player is detected in range)
entity head;
- if not(teamplay)
+ if not(teams_matter && cvar("g_balance_vore_teamheal"))
return;
- if(self.deadflag != DEAD_NO || self.eater.classname == "player" || self.flagcarried || self.digesting) // a flag carrier can't waste time on team healing
+ if(self.deadflag != DEAD_NO || self.predator.classname == "player" || self.flagcarried || self.digesting) // a flag carrier can't waste time on team healing
{
self.status_teamhealing = 0;
return;
}
+ // if a teamheal is ongoing, decide whether or not to abandon it when seeing a foe we can attack
+ // this only causes the bot to regurgitate their team mate when seeing an enemy, with the hope that our enemy will still be there once we can swallow
+ // the higher the skill, the greater the chance a bot will abandon a team heal for an enemy
+ if(self.status_teamhealing > 1)
+ if(Swallow_condition_check_bot(prey))
+ if(prey.team != self.team)
+ if(random() * 10 < cvar("bot_ai_vore_teamhealabandon") * skill / self.bot_voreteamheal) // there are 10 bot skill steps
+ self.BUTTON_REGURGITATE = TRUE; // release the team mate
+
// decide if we can teamheal or not
if(self.stomach_load)
{
- self.status_teamhealing = 2; // consider a team mate is in our stomach and therefore we are teamhealing, until proven otherwise below
+ self.status_teamhealing = 2; // consider a team mate is in our stomach and we are teamhealing, until proven otherwise below
FOR_EACH_PLAYER(head)
{
- if(head.eater == self)
+ if(head.predator == self)
if(head.team != self.team)
{
self.status_teamhealing = 0; // there's a foe in our stomach, we can't teamheal now
else
self.status_teamhealing = 1; // if our stomach is empty, it means we can decide to teamheal
- // now that we're decided if we can teamheal or not, lets go ahead and do so:
+ // now that we're decided if we can teamheal or not, lets go ahead and do so
- // if we are holding a team mate that's been healed to the maximum amount, we can release them
- // not sure if this should be merged with the FOR_EACH_PLAYER check above. That would save an extra loop, but would be less correct
+ // if we are holding a team mate that's been healed to the limit, we can release them
FOR_EACH_PLAYER(head)
{
- if(head.eater == self) // head is automatically a team mate, or we wouldn't be reaching this part of the code
+ if(head.predator == self) // head is automatically a team mate, or we wouldn't be reaching this part of the code
if(head.health >= cvar("g_balance_vore_teamheal_stable"))
self.BUTTON_REGURGITATE = TRUE; // release the team mate
}
- // check if we can heal a damaged team mate we came across, and if so swallow them
- if(prey.classname == "player" && prey.team == self.team)
+ // check if we can heal a team mate we come across, and if so swallow them
+ if(prey.team == self.team)
+ if(Swallow_condition_check_bot(prey))
if(prey.health < cvar("g_balance_vore_teamheal_stable"))
+ if not(prey.digesting) // if our team mate is digesting someone, he likely wouldn't want us ruining his frag
if not(prey.flagcarried) // don't eat the flag carrier and ruin his job
- if(Swallow_condition_check_bot(prey))
- self.BUTTON_ATCK = TRUE; // swallow
+ self.BUTTON_ATCK = TRUE; // swallow the team mate
}
-.float swallow_retry, decide_delay1, decide_delay2;
+.float decide_swallow, decide_pred, decide_prey;
void Vore_AI()
{
+ // main vore AI code
+
if(cvar("bot_nofire") || !skill)
return;
// Predator bot behavior:
// --------------------------------
- // finding and swallowing a victim:
+ // finding and swallowing a player
- // aim toward the nearest possible victim. The greater the skill the quicker the aim. This only does the aiming, checking and swallowing is handled below
+ // aim toward the nearest possible victim. The greater the skill, the quicker the aim
+ // this only does the aiming, checking and swallowing is handled below
entity scan;
scan = findradius(self.origin, cvar("g_balance_vore_swallow_range"));
if(Swallow_condition_check_bot(scan))
// now do the actual checking and swallowing
entity prey;
- float random_try;
- float decide_prey, decide_pred;
+ float randomtry_pred, randomtry_prey;
+ float decide_pred_time, decide_prey_time;
- prey = Swallow_distance_check_bot(self);
+ prey = Swallow_player_check();
- // check if we should run the Teamhealing AI rather than continuing with the normal vore
+ // check if we should run the Teamhealing AI rather than continuing with the normal vore AI
Vore_AI_Teamheal(prey);
if(self.status_teamhealing > 1) // if we are teamhealing, there's nothing to do from here on
return;
- random_try = random() * 10; // there are 10 bot skill steps
+ randomtry_pred = randomtry_prey = random() * 10; // there are 10 bot skill steps
if(prey.items & IT_STRENGTH) // avoid eating bots that have the Strenght powerup
- random_try /= cvar("bot_ai_vore_decide_fear");
+ randomtry_pred /= cvar("bot_ai_vore_fear") * self.bot_vorefear;
if(prey.items & IT_INVINCIBLE) // avoid eating bots that have the Invincible powerup
- random_try /= cvar("bot_ai_vore_decide_fear");
- decide_prey = cvar("bot_ai_vore_decide_prey") / (skill * 2 + 1);
- decide_pred = cvar("bot_ai_vore_decide_pred") / (skill * 2 + 1);
+ randomtry_pred /= cvar("bot_ai_vore_fear") * self.bot_vorefear;
+ decide_pred_time = cvar("bot_ai_vore_decide_pred") / (skill * 2 + 1) / self.bot_vorethink;
+ decide_prey_time = cvar("bot_ai_vore_decide_prey") / (skill * 2 + 1) / self.bot_vorethink;
- if(time > self.swallow_retry)
+ if(time > self.decide_swallow)
if(Swallow_condition_check_bot(prey))
{
// the greater the skill, the higher the chance bots will swallow someone each attempt
- if(skill >= random_try)
- if not(teamplay && prey.team == self.team)
+ if(skill >= randomtry_pred)
+ if not(teams_matter && prey.team == self.team)
{
self.BUTTON_ATCK = TRUE; // swallow
- self.decide_delay1 = time + decide_pred; // time before the bot decides what to do with their prey
+ self.decide_pred = time + decide_pred_time; // time before the bot decides what to do with their prey
}
- self.swallow_retry = time + 0.5; // bots retry swallowing every 0.5 seconds, otherwise each frame would be random chance
+ self.decide_swallow = time + cvar("bot_ai_vore_decide_swallow") / (skill + 1);
}
// deciding what to do with a victim:
- if(self.stomach_load > 0 && time > self.decide_delay1)
+ if(self.stomach_load && time > self.decide_pred)
{
- // if the predator's health is smaller than the maximum amount of damage a stomach kick can do, regurgitate the player(s)
- // otherwise the predator is putting himself at risk by keeping someone inside
+ // if the predator's health is smaller than the maximum damage a stomach kick can do, regurgitate the player(s)
+ // otherwise the predator is putting himself at risk by keeping you inside
if(self.health <= cvar("g_balance_vore_kick_damage_max"))
self.BUTTON_REGURGITATE = TRUE;
else if(!self.digesting)
{
// the higher the skill, the faster bots will start to digest you
- if(skill >= random_try)
+ if(skill >= randomtry_pred)
self.BUTTON_DIGEST = TRUE; // digest
- self.decide_delay1 = time + decide_pred; // time before the bot decides what to do with their prey
+ self.decide_pred = time + decide_pred_time; // time before the bot decides what to do with their prey
}
}
// Prey bot behavior:
// --------------------------------
- // all we can do in the stomach is kick and do some damage / try to escape
- if(self.eater.classname == "player" && time > self.decide_delay2)
+ // all we can do in the stomach is kick and do some damage / try to escape, or leave if the circumstances allow it and we should
+
+ if(self.predator.classname == "player" && time > self.decide_prey)
{
- // the higher the skill, the more the bot will kick in your stomack
- if(skill >= random_try)
- if not(teamplay && prey.team == self.team) // if someone from the same team somehow made it in the belly, don't kick the eater
- self.BUTTON_ATCK = TRUE; // kick
+ if not(teams_matter && self.team == self.predator.team)
+ {
+ // the higher the skill, the more the bot will kick in your stomack
+ if(skill >= randomtry_prey)
+ if not(teams_matter && self.team == self.predator.team) // if someone from the same team is in the belly, don't kick the predator
+ self.BUTTON_ATCK = TRUE; // kick
+ }
+
+ // if a bot can willingly leave the predator, do so unless there's a reason not to
+ if(self.stat_canleave)
+ {
+ if(self.predator.digesting) // our predator is digesting, so get out of him regardless of who he is
+ self.BUTTON_JUMP = TRUE; // leave
+ else if not(teams_matter && self.team == self.predator.team && cvar("g_balance_vore_teamheal") && self.health < cvar("g_balance_vore_teamheal_stable")) // we are being team healed, don't leave
+ self.BUTTON_JUMP = TRUE; // leave
+ }
- self.decide_delay2 = time + decide_prey; // time before the bot decides what to do with their predator
+ self.decide_prey = time + decide_prey_time; // time before the bot decides what to do with their predator
}
}
\ No newline at end of file