Allow Separate GrayCon Flee rate.

Added following Rules:

Combat:FleeGray - If true FleeGrayHPRatio will be used.
Combat:FleeGrayHPRatio - HP % when a Gray NPC begins to flee.
This commit is contained in:
Trust 2018-07-22 18:22:07 -04:00
parent f15ba46c24
commit 6b02d50a8c
5 changed files with 83 additions and 48 deletions

View File

@ -419,6 +419,8 @@ RULE_BOOL(Combat, UseIntervalAC, true)
RULE_INT(Combat, PetAttackMagicLevel, 30)
RULE_BOOL(Combat, EnableFearPathing, true)
RULE_REAL(Combat, FleeMultiplier, 2.0) // Determines how quickly a NPC will slow down while fleeing. Decrease multiplier to slow NPC down quicker.
RULE_BOOL(Combat, FleeGray, true) // If true FleeGrayHPRatio will be used.
RULE_INT(Combat, FleeGrayHPRatio, 50) //HP % when a Gray NPC begins to flee.
RULE_INT(Combat, FleeHPRatio, 25) //HP % when a NPC begins to flee.
RULE_BOOL(Combat, FleeIfNotAlone, false) // If false, mobs won't flee if other mobs are in combat with it.
RULE_BOOL(Combat, AdjustProcPerMinute, true)

View File

@ -424,7 +424,7 @@ Mob* EntityList::AICheckNPCtoNPCAggro(Mob* sender, float iAggroRange, float iAss
return nullptr;
}
int EntityList::GetHatedCount(Mob *attacker, Mob *exclude)
int EntityList::GetHatedCount(Mob *attacker, Mob *exclude, bool inc_gray_con)
{
// Return a list of how many non-feared, non-mezzed, non-green mobs, within aggro range, hate *attacker
if (!attacker)
@ -434,20 +434,25 @@ int EntityList::GetHatedCount(Mob *attacker, Mob *exclude)
for (auto it = npc_list.begin(); it != npc_list.end(); ++it) {
NPC *mob = it->second;
if (!mob || (mob == exclude))
if (!mob || (mob == exclude)) {
continue;
}
if (!mob->IsEngaged())
if (!mob->IsEngaged()) {
continue;
}
if (mob->IsFeared() || mob->IsMezzed())
if (mob->IsFeared() || mob->IsMezzed()) {
continue;
}
if (attacker->GetLevelCon(mob->GetLevel()) == CON_GRAY)
if (!inc_gray_con && attacker->GetLevelCon(mob->GetLevel()) == CON_GRAY) {
continue;
}
if (!mob->CheckAggro(attacker))
if (!mob->CheckAggro(attacker)) {
continue;
}
float AggroRange = mob->GetAggroRange();
@ -455,14 +460,12 @@ int EntityList::GetHatedCount(Mob *attacker, Mob *exclude)
AggroRange *= AggroRange;
if (DistanceSquared(mob->GetPosition(), attacker->GetPosition()) > AggroRange)
if (DistanceSquared(mob->GetPosition(), attacker->GetPosition()) > AggroRange) {
continue;
}
Count++;
}
return Count;
}
void EntityList::AIYellForHelp(Mob* sender, Mob* attacker) {

View File

@ -416,7 +416,7 @@ public:
void CheckClientAggro(Client *around);
Mob* AICheckNPCtoNPCAggro(Mob* sender, float iAggroRange, float iAssistRange);
int GetHatedCount(Mob *attacker, Mob *exclude);
int GetHatedCount(Mob *attacker, Mob *exclude, bool inc_gray_con);
void AIYellForHelp(Mob* sender, Mob* attacker);
bool AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint32 iSpellTypes);
bool Merc_AICheckCloseBeneficialSpells(Merc* caster, uint8 iChance, float iRange, uint32 iSpellTypes);

View File

@ -31,87 +31,117 @@ extern Zone* zone;
//this is called whenever we are damaged to process possible fleeing
void Mob::CheckFlee() {
//if were allready fleeing, dont need to check more...
if(flee_mode && currently_fleeing)
// if mob is dead why would you run?
if(GetHP() == 0) {
return;
}
// if were already fleeing, don't need to check more...
if(flee_mode && currently_fleeing) {
return;
}
//dont bother if we are immune to fleeing
if(GetSpecialAbility(IMMUNE_FLEEING) || spellbonuses.ImmuneToFlee)
if(GetSpecialAbility(IMMUNE_FLEEING) || spellbonuses.ImmuneToFlee) {
return;
}
if(!flee_timer.Check())
return; //only do all this stuff every little while, since
//its not essential that we start running RIGHT away
//see if were possibly hurt enough
float ratio = GetHPRatio();
float fleeratio = GetSpecialAbility(FLEE_PERCENT);
fleeratio = fleeratio > 0 ? fleeratio : RuleI(Combat, FleeHPRatio);
if(ratio >= fleeratio)
// Check if Flee Timer is cleared
if(!flee_timer.Check()) {
return;
}
//we might be hurt enough, check con now..
int hpratio = GetIntHPRatio();
int fleeratio = GetSpecialAbility(FLEE_PERCENT); // if a special flee_percent exists
Mob *hate_top = GetHateTop();
// Sanity Check for race conditions
if(hate_top == nullptr) {
return;
}
// If no special flee_percent check for Gray or Other con rates
if(GetLevelCon(hate_top->GetLevel(), GetLevel()) == CON_GRAY && fleeratio == 0 && RuleB(Combat, FleeGray)) {
fleeratio = RuleI(Combat, FleeGrayHPRatio);
} else if(fleeratio == 0) {
fleeratio = RuleI(Combat, FleeHPRatio );
}
// Mob does not have low enough health to flee
if(hpratio >= fleeratio) {
return;
}
// Sanity Check this should never happen...
if(!hate_top) {
//this should never happen...
StartFleeing();
return;
}
float other_ratio = hate_top->GetHPRatio();
int other_ratio = hate_top->GetIntHPRatio();
// If the Client is nearing death the NPC will not flee and instead try to kill the client.
if(other_ratio < 20) {
//our hate top is almost dead too... stay and fight
return;
}
//base our flee ratio on our con. this is how the
//attacker sees the mob, since this is all we can observe
// Flee Chance checking based on con.
uint32 con = GetLevelCon(hate_top->GetLevel(), GetLevel());
float run_ratio;
int flee_chance;
switch(con) {
//these values are not 100% researched
case CON_GRAY:
run_ratio = fleeratio;
flee_chance = 100;
break;
case CON_GREEN:
run_ratio = fleeratio * 9 / 10;
flee_chance = 90;
break;
case CON_LIGHTBLUE:
run_ratio = fleeratio * 9 / 10;
flee_chance = 90;
break;
case CON_BLUE:
run_ratio = fleeratio * 8 / 10;
flee_chance = 80;
break;
default:
run_ratio = fleeratio * 7 / 10;
flee_chance = 70;
break;
}
if(ratio < run_ratio)
{
if (RuleB(Combat, FleeIfNotAlone) ||
GetSpecialAbility(ALWAYS_FLEE) ||
(!RuleB(Combat, FleeIfNotAlone) && (entity_list.GetHatedCount(hate_top, this) == 0)))
StartFleeing();
// If we got here we are allowed to roll on flee chance if there is not other hated NPC's in the area.
if(RuleB(Combat, FleeIfNotAlone) || GetSpecialAbility(ALWAYS_FLEE) || zone->random.Roll(flee_chance) && entity_list.GetHatedCount(hate_top, this, true) == 0) {
currently_fleeing = true;
StartFleeing();
}
}
void Mob::ProcessFlee()
{
//Stop fleeing if effect is applied after they start to run.
//When ImmuneToFlee effect fades it will turn fear back on and check if it can still flee.
if (flee_mode && (GetSpecialAbility(IMMUNE_FLEEING) || spellbonuses.ImmuneToFlee) &&
!spellbonuses.IsFeared && !spellbonuses.IsBlind) {
!spellbonuses.IsFeared && !spellbonuses.IsBlind) {
currently_fleeing = false;
return;
}
//see if we are still dying, if so, do nothing
float fleeratio = GetSpecialAbility(FLEE_PERCENT);
fleeratio = fleeratio > 0 ? fleeratio : RuleI(Combat, FleeHPRatio);
if (GetHPRatio() < fleeratio)
int hpratio = GetIntHPRatio();
int fleeratio = GetSpecialAbility(FLEE_PERCENT); // if a special flee_percent exists
Mob *hate_top = GetHateTop();
// If no special flee_percent check for Gray or Other con rates
if(GetLevelCon(hate_top->GetLevel(), GetLevel()) == CON_GRAY && fleeratio == 0 && RuleB(Combat, FleeGray)) {
fleeratio = RuleI(Combat, FleeGrayHPRatio);
} else if(fleeratio == 0) {
fleeratio = RuleI(Combat, FleeHPRatio );
}
// Mob is still too low. Keep Running
if(hpratio < fleeratio) {
return;
}
//we are not dying anymore... see what we do next

View File

@ -1414,7 +1414,7 @@ void Merc::AI_Process() {
if(DivineAura())
return;
int hateCount = entity_list.GetHatedCount(this, nullptr);
int hateCount = entity_list.GetHatedCount(this, nullptr, false);
if(GetHatedCount() < hateCount) {
SetHatedCount(hateCount);