diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 9d0aa9231..ca7a29f25 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -404,6 +404,7 @@ 9148|2020_01_28_corpse_guild_consent_id.sql|SHOW COLUMNS FROM `character_corpses` LIKE 'guild_consent_id'|empty| 9149|2020_02_06_globalloot.sql|SHOW COLUMNS FROM `global_loot` LIKE 'hot_zone'|empty| 9150|2020_02_06_aa_reset_on_death.sql|SHOW COLUMNS FROM `aa_ability` LIKE 'reset_on_death'|empty| +9151|2020_03_05_npc_always_aggro.sql|SHOW COLUMNS FROM `npc_types` LIKE 'always_aggros_foes'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2020_03_05_npc_always_aggro.sql b/utils/sql/git/required/2020_03_05_npc_always_aggro.sql new file mode 100644 index 000000000..d9e6351a3 --- /dev/null +++ b/utils/sql/git/required/2020_03_05_npc_always_aggro.sql @@ -0,0 +1 @@ +ALTER TABLE `npc_types` ADD COLUMN `always_aggros_foes` tinyint(4) NOT NULL DEFAULT 0; diff --git a/zone/aggro.cpp b/zone/aggro.cpp index ff0077353..fac15457e 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -139,7 +139,7 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) { if (RuleB(Aggro, UseLevelAggro)) { - if (GetLevel() < RuleI(Aggro, MinAggroLevel) && mob->GetLevelCon(GetLevel()) == CON_GRAY && GetBodyType() != 3) + if (GetLevel() < RuleI(Aggro, MinAggroLevel) && mob->GetLevelCon(GetLevel()) == CON_GRAY && GetBodyType() != 3 && !AlwaysAggrosFoes()) { towho->Message(Chat::White, "...%s is red to me (basically)", mob->GetName(), dist2, iAggroRange2); return; @@ -147,7 +147,7 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) { } else { - if(GetINT() > RuleI(Aggro, IntAggroThreshold) && mob->GetLevelCon(GetLevel()) == CON_GRAY ) { + if(GetINT() > RuleI(Aggro, IntAggroThreshold) && mob->GetLevelCon(GetLevel()) == CON_GRAY && !AlwaysAggrosFoes()) { towho->Message(Chat::White, "...%s is red to me (basically)", mob->GetName(), dist2, iAggroRange2); return; @@ -318,7 +318,7 @@ bool Mob::CheckWillAggro(Mob *mob) { //old InZone check taken care of above by !mob->CastToClient()->Connected() ( ( GetLevel() >= RuleI(Aggro, MinAggroLevel)) - ||(GetBodyType() == 3) + ||(GetBodyType() == 3) || AlwaysAggrosFoes() ||( mob->IsClient() && mob->CastToClient()->IsSitting() ) ||( mob->GetLevelCon(GetLevel()) != CON_GRAY) @@ -352,6 +352,7 @@ bool Mob::CheckWillAggro(Mob *mob) { //old InZone check taken care of above by !mob->CastToClient()->Connected() ( ( GetINT() <= RuleI(Aggro, IntAggroThreshold) ) + || AlwaysAggrosFoes() ||( mob->IsClient() && mob->CastToClient()->IsSitting() ) ||( mob->GetLevelCon(GetLevel()) != CON_GRAY) @@ -383,6 +384,7 @@ bool Mob::CheckWillAggro(Mob *mob) { LogAggro("Dist^2: [{}]\n", dist2); LogAggro("Range^2: [{}]\n", iAggroRange2); LogAggro("Faction: [{}]\n", fv); + LogAggro("AlwaysAggroFlag: [{}]\n", AlwaysAggrosFoes()); LogAggro("Int: [{}]\n", GetINT()); LogAggro("Con: [{}]\n", GetLevelCon(mob->GetLevel())); diff --git a/zone/beacon.cpp b/zone/beacon.cpp index 81b964290..ac4beaacc 100644 --- a/zone/beacon.cpp +++ b/zone/beacon.cpp @@ -56,7 +56,7 @@ Beacon::Beacon(Mob *at_mob, int lifetime) :Mob ( nullptr, nullptr, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, at_mob->GetPosition(), 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, EQEmu::TintProfile(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, EQEmu::TintProfile(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false ), remove_timer(lifetime), spell_timer(0) diff --git a/zone/client.cpp b/zone/client.cpp index 6bd9941f8..8b60b391a 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -121,7 +121,8 @@ Client::Client(EQStreamInterface* ieqs) 0, 0, 0, - 0 + 0, + false ), hpupdate_timer(2000), camp_timer(29000), diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 0ac100997..5858d5acc 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -154,7 +154,7 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP in_npc->GetPosition(), in_npc->GetInnateLightType(), in_npc->GetTexture(),in_npc->GetHelmTexture(), 0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,EQEmu::TintProfile(),0xff,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - (*in_npctypedata)->use_model), + (*in_npctypedata)->use_model, false), corpse_decay_timer(in_decaytime), corpse_rez_timer(0), corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)), @@ -260,8 +260,9 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( 0, // uint8 in_bracertexture, 0, // uint8 in_handtexture, 0, // uint8 in_legtexture, - 0, - 0 // uint8 in_feettexture, + 0, // uint8 in_feettexture, + 0, // uint8 in_usemodel, + 0 // bool in_always_aggros_foes ), corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)), corpse_rez_timer(RuleI(Character, CorpseResTimeMS)), @@ -500,7 +501,8 @@ EQEmu::TintProfile(), 0, 0, 0, -0), +0, +false), corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)), corpse_rez_timer(RuleI(Character, CorpseResTimeMS)), corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)), diff --git a/zone/encounter.cpp b/zone/encounter.cpp index e0ec83d90..7d37844b6 100644 --- a/zone/encounter.cpp +++ b/zone/encounter.cpp @@ -36,7 +36,7 @@ Encounter::Encounter(const char* enc_name) :Mob ( nullptr, nullptr, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, glm::vec4(0,0,0,0), 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, EQEmu::TintProfile(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, EQEmu::TintProfile(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false ) { encounter_name[0] = 0; diff --git a/zone/mob.cpp b/zone/mob.cpp index c7b7559da..2e3d3d290 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -93,7 +93,8 @@ Mob::Mob( uint8 in_handtexture, uint8 in_legtexture, uint8 in_feettexture, - uint16 in_usemodel + uint16 in_usemodel, + bool in_always_aggros_foes ) : attack_timer(2000), attack_dw_timer(2000), @@ -275,6 +276,7 @@ Mob::Mob( qglobal = 0; spawned = false; rare_spawn = false; + always_aggros_foes = in_always_aggros_foes; InitializeBuffSlots(); diff --git a/zone/mob.h b/zone/mob.h index 7c095a001..2a89ba384 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -161,7 +161,8 @@ public: uint8 in_handtexture, uint8 in_legtexture, uint8 in_feettexture, - uint16 in_usemodel + uint16 in_usemodel, + bool in_always_aggros_foes ); virtual ~Mob(); @@ -578,6 +579,7 @@ public: inline const GravityBehavior GetFlyMode() const { return flymode; } bool IsBoat() const; bool IsControllableBoat() const; + inline const bool AlwaysAggrosFoes() const { return always_aggros_foes; } //Group virtual bool HasRaid() = 0; @@ -1389,6 +1391,7 @@ protected: Timer ranged_timer; float attack_speed; //% increase/decrease in attack speed (not haste) int attack_delay; //delay between attacks in 10ths of seconds + bool always_aggros_foes; int16 slow_mitigation; // Allows for a slow mitigation (100 = 100%, 50% = 50%) Timer tic_timer; Timer mana_timer; diff --git a/zone/npc.cpp b/zone/npc.cpp index 0b22bab3a..307e7a926 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -113,7 +113,8 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi npc_type_data->handtexture, npc_type_data->legtexture, npc_type_data->feettexture, - npc_type_data->use_model + npc_type_data->use_model, + npc_type_data->always_aggros_foes ), attacked_timer(CombatEventTimer_expire), swarm_timer(100), diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index ea4287f9d..3b03d2563 100755 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2506,7 +2506,8 @@ const NPCType *ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load "npc_types.rare_spawn, " "npc_types.stuck_behavior, " "npc_types.model, " - "npc_types.flymode " + "npc_types.flymode, " + "npc_types.always_aggros_foes " "FROM npc_types %s", where_condition.c_str() ); @@ -2703,11 +2704,12 @@ const NPCType *ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load temp_npctype_data->charm_avoidance_rating = atoi(row[105]); temp_npctype_data->charm_atk = atoi(row[106]); - temp_npctype_data->skip_global_loot = atoi(row[107]) != 0; - temp_npctype_data->rare_spawn = atoi(row[108]) != 0; - temp_npctype_data->stuck_behavior = atoi(row[109]); - temp_npctype_data->use_model = atoi(row[110]); - temp_npctype_data->flymode = atoi(row[111]); + temp_npctype_data->skip_global_loot = atoi(row[107]) != 0; + temp_npctype_data->rare_spawn = atoi(row[108]) != 0; + temp_npctype_data->stuck_behavior = atoi(row[109]); + temp_npctype_data->use_model = atoi(row[110]); + temp_npctype_data->flymode = atoi(row[111]); + temp_npctype_data->always_aggros_foes = atoi(row[112]); temp_npctype_data->skip_auto_scale = false; // hardcoded here for now diff --git a/zone/zonedump.h b/zone/zonedump.h index 6010c9480..80508f233 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -147,6 +147,7 @@ struct NPCType int8 stuck_behavior; uint16 use_model; int8 flymode; + bool always_aggros_foes; }; namespace player_lootitem {