EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Development::Feature Requests (https://www.eqemulator.org/forums/forumdisplay.php?f=612)
-   -   Request/Question - always aggros npc (https://www.eqemulator.org/forums/showthread.php?t=41234)

ChaosSlayerZ 03-24-2017 10:11 AM

Request/Question - always aggros npc
 
Forgive me if I am out of date on this but here is what I know:

Back when I was actively messing with the server, I learned that in order to make npc always aggro on a player regardless of a level (like lev 5 undead aggro on lev 50 players) you had to set their INT below 75. Which is a bit awkward and obscure and most people don't even know this. I know npc stats probably not used for much, but wouldn't it be better to change that and set it with proper npc Flag instead, like we do for Special Attacks? (http://wiki.eqemulator.org/p?NPC_Spe...tacks&frm=Main)

Thank You!

GRUMPY 03-24-2017 01:13 PM

Could this ruletype help ?
Code:

RULE_INT(Aggro, IntAggroThreshold, 75) // Int <= this will aggro regardless of level difference.

ChaosSlayerZ 03-24-2017 01:25 PM

Yeah, but I think its sort of weird assigning it to a stat score rather than having a special attack flag.

GRUMPY 03-24-2017 01:44 PM

Quote:

Originally Posted by ChaosSlayerZ (Post 253774)
Yeah, but I think its sort of weird assigning it to a stat score rather than having a special attack flag.

Yes, I agree with you. It is a weird way of doing it.

ghanja 03-24-2017 03:09 PM

Quote:

Originally Posted by ChaosSlayerZ (Post 253774)
Yeah, but I think its sort of weird assigning it to a stat score rather than having a special attack flag.

I experienced a brain fart initially. So the request is to make it a special attack. Hmm.

ChaosSlayerZ 03-24-2017 05:02 PM

Quote:

Originally Posted by ghanja (Post 253781)
I experienced a brain fart initially. So the request is to make it a special attack. Hmm.

Exactly ;) Like the similar things here:
http://wiki.eqemulator.org/p?NPC_Spe...tacks&frm=Main

Coenxai 04-13-2017 01:24 AM

This is a pretty basic change guys.

You'll need to add the special ability. Here's an example:

Code:

common.h

        IGNORE_ROOT_AGGRO_RULES = 42,
        CASTING_RESIST_DIFF = 43,
        COUNTER_AVOID_DAMAGE = 44,
        PROX_AGGRO = 45,
        ALWAYS_AGGRO = 46, <-----
        MAX_SPECIAL_ATTACK = 47

Then, just add it in where it fits your goal. Such as:

Code:

aggro.cpp

Mob::CheckWillAggro

  ...

        if (RuleB(Aggro, UseLevelAggro) && ((
                ( GetLevel() >= 18 )
                ||(GetBodyType() == BT_Undead)
                ||( mob->IsClient() && mob->CastToClient()->IsSitting() )
                ||( mob->GetLevelCon(GetLevel()) != CON_GREEN )
                ||( GetSpecialAbility(ALWAYS_AGGRO) ))

After that, add the special ability to the NPC's that you desire. Voilą.

That function is so abhorrent it deserves an award.

The_Beast 04-13-2017 02:37 AM

How does this current rule fit into that ? Because I'm ok, with it so far.
Code:

RULE_BOOL(Aggro, UseLevelAggro, true) // Level 18+ and Undead will aggro regardless of level difference. (this will disable Rule:IntAggroThreshold if set to true)

tdanger84 04-13-2017 07:47 AM

you would have to have pretty low intelligence to attack a a lvl 50 at lvl 5. maybe that's the reasoning? =p

ChaosSlayerZ 04-13-2017 10:18 PM

Quote:

Originally Posted by Coenxai (Post 254193)
This is a pretty basic change guys.

You'll need to add the special ability. Here's an example:

Code:

common.h

        IGNORE_ROOT_AGGRO_RULES = 42,
        CASTING_RESIST_DIFF = 43,
        COUNTER_AVOID_DAMAGE = 44,
        PROX_AGGRO = 45,
        ALWAYS_AGGRO = 46, <-----
        MAX_SPECIAL_ATTACK = 47

Then, just add it in where it fits your goal. Such as:

Code:

aggro.cpp

Mob::CheckWillAggro

  ...

        if (RuleB(Aggro, UseLevelAggro) && ((
                ( GetLevel() >= 18 )
                ||(GetBodyType() == BT_Undead)
                ||( mob->IsClient() && mob->CastToClient()->IsSitting() )
                ||( mob->GetLevelCon(GetLevel()) != CON_GREEN )
                ||( GetSpecialAbility(ALWAYS_AGGRO) ))

After that, add the special ability to the NPC's that you desire. Voilą.

That function is so abhorrent it deserves an award.



Thank You Coenxai!
Would be great our devs would add this to the official source! ;)

BTW the mob doesn't necessarily needs to be Undead ;)
It can be any type of mob that's needs to be always aggro ;)

Coenxai 04-13-2017 11:04 PM

Delete this post.

Coenxai 04-13-2017 11:05 PM

Quote:

Originally Posted by The_Beast (Post 254195)
How does this current rule fit into that ? Because I'm ok, with it so far.
Code:

RULE_BOOL(Aggro, UseLevelAggro, true) // Level 18+ and Undead will aggro regardless of level difference. (this will disable Rule:IntAggroThreshold if set to true)

It will aggro regardless of BodyType with the special ability. Undead will aggro regardless of special ability.

ChaosSlayerZ 04-14-2017 12:11 AM

Quote:

Originally Posted by Coenxai (Post 254211)
It will aggro regardless of BodyType with the special ability. Undead will aggro regardless of special ability.



actually it would be better if Undead don't always aggro automatically - because you may want undead that don't aggro. (not all undead on live were always aggro - there was a number of undead in various places/levels that obeyed level difference green status)
So its better to have all mobs without default rules, and then apply the "always aggro" flag where actually needed.

Coenxai 04-14-2017 12:17 AM

Quote:

Originally Posted by ChaosSlayerZ (Post 254212)
actually it would be better if Undead don't always aggro automatically - because you may want undead that don't aggro. (not all undead on live were always aggro - there was a number of undead in various places/levels that obeyed level difference green status)
So its better to have all mobs without default rules, and then apply the "always aggro" flag where actually needed.

You can have a mob of type BT_Undead that doesn't aggro. This purely relates to FACTION_THREATENLY && FACTION_SCOWLS.

I'm going to post slightly more readable aggro code.

I didn't test this properly but it should work.
Code:

aggro.cpp

bool Mob::CheckWillAggro(Mob *mob) {

        if(!mob)
                return false;

        if (mob->IsClient()) {
                if (!mob->CastToClient()->ClientFinishedLoading() || mob->CastToClient()->IsHoveringForRespawn() || mob->CastToClient()->zoning || !mob->CastToClient()->Connected()
                        || mob->CastToClient()->GetGM() || mob->CastToClient()->IsLD() || mob->CastToClient()->IsBecomeNPC() || mob->IsInvisible(this))
                        return false;
        }

        Mob *ownr = mob->GetOwner();
        if (ownr && ownr->IsClient() && !ownr->CastToClient()->ClientFinishedLoading() || mob == ownr)
                return false;

        // Don't aggro new clients if we are already engaged unless PROX_AGGRO is set. WHY ARE WE CHECKING COMBAT AND AGGRO RANGE? THIS SHOULD BE COMBINED.
        if (IsEngaged() && !GetSpecialAbility(PROX_AGGRO) || GetSpecialAbility(PROX_AGGRO) && !CombatRange(mob)) {
                Log(Logs::Moderate, Logs::Aggro, "%s is in combat, and does not have prox_aggro, or does and is out of combat range with %s", GetName(), mob->GetName());
                return false;
        }

        float AggroRange, t1, t2, t3;

        AggroRange = GetAggroRange();
        t1 = mob->GetX() - GetX();
        t2 = mob->GetY() - GetY();
        t3 = mob->GetZ() - GetZ();

        if (t1 < 0)
                t1 = 0 - t1;
        if (t2 < 0)
                t2 = 0 - t2;
        if (t3 < 0)
                t3 = 0 - t3;

        if ((t1 > AggroRange) || (t2 > AggroRange) || (t3 > AggroRange))
                return false;

        float dist2 = DistanceSquared(mob->GetPosition(), m_Position);
        float AggroRange2 = AggroRange*AggroRange;

        if (dist2 > AggroRange2)
                return false;

        FACTION_VALUE fv = mob->GetReverseFactionCon(this);
        uint8 MyLevel = GetLevel();

        int heroicCHA_mod = mob->itembonuses.HeroicCHA/25; // 800 Heroic CHA cap
        if(heroicCHA_mod > THREATENLY_ARRGO_CHANCE)
                heroicCHA_mod = THREATENLY_ARRGO_CHANCE;

        if (MyLevel >= RuleI(Aggro, LevelAggro) || (GetBodyType() == BT_Undead && MyLevel >= RuleI(Aggro, UndeadLevelAggro)) || GetINT() <= RuleI(Aggro, IntAggroThreshold)
                || mob->IsClient() && mob->CastToClient()->IsSitting() || GetSpecialAbility(ALWAYS_AGGRO) || mob->GetLevelCon(GetLevel()) != CON_GREEN) {
                if (fv == FACTION_SCOWLS || fv == FACTION_THREATENLY && zone->random.Roll(THREATENLY_ARRGO_CHANCE - heroicCHA_mod)
                        || (mob->GetPrimaryFaction() != GetPrimaryFaction() && mob->GetPrimaryFaction() == -4 && GetOwner() == nullptr)) {
                        if (CheckLosFN(mob)) {
                                Log(Logs::Detail, Logs::Aggro, "Check aggro for %s target %s.", GetName(), mob->GetName());
                                return(mod_will_aggro(mob, this));
                        }
                }
        }

        Log(Logs::Detail, Logs::Aggro, "InZone: %d | Dist^2: %f | Range^2: %f | Faction: %d | Con: %d | Int: %d | MyLevel: %d", mob->InZone(), dist2, AggroRange2, fv, GetINT(), GetLevelCon(mob->GetLevel()), MyLevel);

        return false;
}

Code:

ruletypes.h

RULE_CATEGORY(Aggro)
RULE_BOOL(Aggro, SmartAggroList, true)
RULE_INT(Aggro, SittingAggroMod, 35) //35%
RULE_INT(Aggro, MeleeRangeAggroMod, 10) //10%
RULE_INT(Aggro, CurrentTargetAggroMod, 0) //0% -- will prefer our current target to any other; makes it harder for our npcs to switch targets.
RULE_INT(Aggro, CriticallyWoundedAggroMod, 100) //100%
RULE_INT(Aggro, SpellAggroMod, 100)
RULE_INT(Aggro, SongAggroMod, 33)
RULE_INT(Aggro, PetSpellAggroMod, 10)
RULE_REAL(Aggro, TunnelVisionAggroMod, 0.75) //people not currently the top hate generate this much hate on a Tunnel Vision mob
RULE_INT(Aggro, MaxScalingProcAggro, 400) // Set to -1 for no limit. Maxmimum amount of aggro that HP scaling SPA effect in a proc will add.
RULE_INT(Aggro, IntAggroThreshold, 75) // Int <= this will aggro regardless of level difference.
RULE_BOOL(Aggro, AllowTickPulling, false) // tick pulling is an exploit in an NPC's call for help fixed sometime in 2006 on live
RULE_BOOL(Aggro, UseLevelAggro, true)
RULE_INT(Aggro, LevelAggro, 18)
RULE_INT(Aggro, UndeadLevelAggro, 6)
RULE_INT(Aggro, ClientAggroCheckInterval, 6) // Interval in which clients actually check for aggro - in seconds
RULE_CATEGORY_END()

Code:

common.h

  ...

        COUNTER_AVOID_DAMAGE = 44,
        PROX_AGGRO = 45,
        ALWAYS_AGGRO = 46, <---
        MAX_SPECIAL_ATTACK = 47


ChaosSlayerZ 04-14-2017 12:31 AM

I am not exactly sure what BT_Undead is? and how its different from just Undead?

Coenxai 04-14-2017 12:41 AM

Quote:

Originally Posted by ChaosSlayerZ (Post 254214)
I am not exactly sure what BT_Undead is? and how its different from just Undead?

BT is just BodyType -- so when I said BT_Undead, I'm basically just saying undead.

You can set up multiple factions to function differently. For instance, here are some factions that I use:

Undead KoS (-32000)
Undead KoS Assist (-32000, assist other undead in trouble)
Undead (0, won't attack, yay!)
Undead Assist (0, won't attack, yay! assist other undead in trouble)
NonNec KoS (undead that's KoS to everyone except necromancers)

That code I mentioned will only take the KoS conned mobs and make them attack higher level players if they exceed the undead threshold. Make sense?
Code:

RULE_INT(Aggro, UndeadLevelAggro, 6)
(GetBodyType() == BT_Undead && MyLevel >= RuleI(Aggro, UndeadLevelAggro))


ChaosSlayerZ 04-14-2017 01:02 AM

OK I see, yeah by Undead I always refer to the body type and not faction, since faction can be anything and can have any type of mobs of it ;)


Basically what I am saying that body type of a mob should be irrelevant to the rule.
If mob is KOS (by faction) and has the Always Aggro FLAG - it always aggros.

So it can be NON Undead and always aggro
Or it can Undead and don't aggro (because of level difference)

Just to be clear ;)

Coenxai 04-14-2017 01:27 AM

It will always aggro if it is threatenly or scowl, bodytype has nothing to do with it -- the ONLY exception is if it ISN'T KoS

Did you want ALWAYS_AGGRO to apply to indifferent (ally, etc.) mobs too?

ChaosSlayerZ 04-14-2017 01:54 AM

Quote:

Originally Posted by Coenxai (Post 254218)
It will always aggro if it is threatenly or scowl, bodytype has nothing to do with it -- the ONLY exception is if it ISN'T KoS

Did you want ALWAYS_AGGRO to apply to indifferent (ally, etc.) mobs too?


OK, I am sorry if I confusing you ;)

So let go over this again.
Normally, if we have a normal mob, that belongs to some faction and your faction is BAD (KOS or so) it will aggro. Unless you are much higher level than him.

Now, the FLAG that we are discussing should allow this mob to aggro (because of my BAD faction) even if it is out of level.

This FLAG should work instead of "Low INT" system that we currently have, because using INT stat for this is kind of stupid.

Thats what I am trying to say =)

Undead were only mentioned because it is USUALLY the type of mobs on LIVE that aggros out of level.

Obviously if mob is NOT KOS, it has no reason to aggro (unless I attack it)

But what will happen if mob is out of level range, my faction is good, BUT I attacked its friend? Normally mob will not assist because I am out of level, but mob with this FLAG should still assist because it sort of "fearless"


Sorry again if I am giving you a headache, I just want to make sure you getting me right ;)

Coenxai 04-14-2017 03:24 AM

Okay, let me try this again.

If it has the ALWAYS_AGGRO special ability. It will *ALWAYS* aggro if it's KoS. It doesn't matter the body type, level, intelligence, etc. It WILL aggro if this is set in my code.

Now, assisting (or yelling for help) is different, and it will require an additional change.

Code:

aggro.cpp

void EntityList::AIYellForHelp(Mob* sender, Mob* attacker)

  ...

                //if they are in range, make sure we are not green...
                        //then jump in if they are our friend
                        if(mob->GetSpecialAbility(ALWAYS_ASSIST) || mob->GetLevel() >= 50 || attacker->GetLevelCon(mob->GetLevel()) != CON_GREEN)

Code:

common.h

        PROX_AGGRO = 45,
        ALWAYS_AGGRO = 46,
        ALWAYS_ASSIST = 47,
        MAX_SPECIAL_ATTACK = 48

TO RECAP:

If a mob is set to (46) and it's KoS. It will ALWAYS ATTACK REGARDLESS OF ANYTHING.

If a mob is set to (47). It will ALWAYS ASSIST ITS FACTION REGARDLESS OF ANYTHING.

If it's set to both 46 and 47 it will always do both.

ChaosSlayerZ 04-14-2017 10:05 AM

Awesome ;)
Thank You so much!

Coenxai 04-14-2017 02:50 PM

No problem

ChaosSlayerZ 02-01-2019 05:07 PM

BUMP!

Begging the devs to implement this into official code instead of Level or INT setting.

jmac 03-17-2019 07:33 AM

I just set all rats in misty to faction 1291 kos aggressive and they agro (lvl 1) on my lvl 70

ChaosSlayerZ 03-17-2019 11:00 AM

Quote:

Originally Posted by jmac (Post 261919)
I just set all rats in misty to faction 1291 kos aggressive and they agro (lvl 1) on my lvl 70

Thats NOT why they aggro.


All times are GMT -4. The time now is 01:38 PM.

Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.