Add Support to define a valid HP range for NPC casting

These will allow us to define a valid HP range (HP of the caster) that
an NPC will cast a spell. For example NPC casting a defensive spell at
This commit is contained in:
Michael Cook (mackal) 2018-02-01 18:32:40 -05:00
parent d71dbd1751
commit 3c794cfc07
9 changed files with 37 additions and 12 deletions

View File

@ -30,7 +30,7 @@
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9115
#define CURRENT_BINARY_DATABASE_VERSION 9117
#ifdef BOTS
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9017
#else

View File

@ -370,6 +370,7 @@
9114|2017_07_22_aura.sql|SHOW TABLES LIKE 'auras'|empty|
9115|2017_10_28_traps.sql|SHOW COLUMNS FROM `traps` LIKE 'triggered_number'|empty|
9116|2017_12_16_GroundSpawn_Respawn_Timer.sql|SHOW COLUMNS FROM `ground_spawns` WHERE Field = 'respawn_timer' AND Type = 'int(11) unsigned'|empty|
9117|2018_02_01_NPC_Spells_Min_Max_HP.sql|SHOW COLUMNS FROM `npc_spells_entries` LIKE 'min_hp'|empty|
# Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not

View File

@ -0,0 +1,2 @@
ALTER TABLE `npc_spells_entries` ADD `min_hp` SMALLINT(5) DEFAULT '0';
ALTER TABLE `npc_spells_entries` ADD `max_hp` SMALLINT(5) DEFAULT '0';

View File

@ -420,7 +420,12 @@ void Lua_NPC::ModifyNPCStat(const char *stat, const char *value) {
void Lua_NPC::AddAISpell(int priority, int spell_id, int type, int mana_cost, int recast_delay, int resist_adjust) {
Lua_Safe_Call_Void();
self->AddSpellToNPCList(priority, spell_id, type, mana_cost, recast_delay, resist_adjust);
self->AddSpellToNPCList(priority, spell_id, type, mana_cost, recast_delay, resist_adjust, 0, 0);
}
void Lua_NPC::AddAISpell(int priority, int spell_id, int type, int mana_cost, int recast_delay, int resist_adjust, int min_hp, int max_hp) {
Lua_Safe_Call_Void();
self->AddSpellToNPCList(priority, spell_id, type, mana_cost, recast_delay, resist_adjust, min_hp, max_hp);
}
void Lua_NPC::RemoveAISpell(int spell_id) {
@ -585,6 +590,7 @@ luabind::scope lua_register_npc() {
.def("SetSwarmTarget", (void(Lua_NPC::*)(int))&Lua_NPC::SetSwarmTarget)
.def("ModifyNPCStat", (void(Lua_NPC::*)(const char*,const char*))&Lua_NPC::ModifyNPCStat)
.def("AddAISpell", (void(Lua_NPC::*)(int,int,int,int,int,int))&Lua_NPC::AddAISpell)
.def("AddAISpell", (void(Lua_NPC::*)(int,int,int,int,int,int,int,int))&Lua_NPC::AddAISpell)
.def("RemoveAISpell", (void(Lua_NPC::*)(int))&Lua_NPC::RemoveAISpell)
.def("SetSpellFocusDMG", (void(Lua_NPC::*)(int))&Lua_NPC::SetSpellFocusDMG)
.def("SetSpellFocusHeal", (void(Lua_NPC::*)(int))&Lua_NPC::SetSpellFocusHeal)

View File

@ -110,6 +110,7 @@ public:
void SetSwarmTarget(int target);
void ModifyNPCStat(const char *stat, const char *value);
void AddAISpell(int priority, int spell_id, int type, int mana_cost, int recast_delay, int resist_adjust);
void AddAISpell(int priority, int spell_id, int type, int mana_cost, int recast_delay, int resist_adjust, int min_hp, int max_hp);
void RemoveAISpell(int spell_id);
void SetSpellFocusDMG(int focus);
void SetSpellFocusHeal(int focus);

View File

@ -91,6 +91,13 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes, bool bInnates
// we define an innate spell as a spell with priority 0
continue;
}
if (AIspells[i].min_hp != 0 && GetIntHPRatio() < AIspells[i].min_hp)
continue;
if (AIspells[i].max_hp != 0 && GetIntHPRatio() > AIspells[i].max_hp)
continue;
if (iSpellTypes & AIspells[i].type) {
// manacost has special values, -1 is no mana cost, -2 is instant cast (no mana)
int32 mana_cost = AIspells[i].manacost;
@ -2421,7 +2428,7 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) {
if (GetLevel() >= e.minlevel && GetLevel() <= e.maxlevel && e.spellid > 0) {
if (!IsSpellInList(spell_list, e.spellid))
{
AddSpellToNPCList(e.priority, e.spellid, e.type, e.manacost, e.recast_delay, e.resist_adjust);
AddSpellToNPCList(e.priority, e.spellid, e.type, e.manacost, e.recast_delay, e.resist_adjust, e.min_hp, e.max_hp);
}
}
}
@ -2462,7 +2469,7 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) {
for (auto &e : spell_list->entries) {
if (GetLevel() >= e.minlevel && GetLevel() <= e.maxlevel && e.spellid > 0) {
AddSpellToNPCList(e.priority, e.spellid, e.type, e.manacost, e.recast_delay, e.resist_adjust);
AddSpellToNPCList(e.priority, e.spellid, e.type, e.manacost, e.recast_delay, e.resist_adjust, e.min_hp, e.max_hp);
}
}
@ -2610,7 +2617,7 @@ bool IsSpellInList(DBnpcspells_Struct* spell_list, int16 iSpellID) {
// adds a spell to the list, taking into account priority and resorting list as needed.
void NPC::AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint32 iType,
int16 iManaCost, int32 iRecastDelay, int16 iResistAdjust)
int16 iManaCost, int32 iRecastDelay, int16 iResistAdjust, int8 min_hp, int8 max_hp)
{
if(!IsValidSpell(iSpellID))
@ -2626,6 +2633,8 @@ void NPC::AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint32 iType,
t.recast_delay = iRecastDelay;
t.time_cancast = 0;
t.resist_adjust = iResistAdjust;
t.min_hp = min_hp;
t.max_hp = max_hp;
AIspells.push_back(t);
@ -2716,7 +2725,7 @@ DBnpcspells_Struct *ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID)
// pulling fixed values from an auto-increment field is dangerous...
query = StringFormat(
"SELECT spellid, type, minlevel, maxlevel, "
"manacost, recast_delay, priority, resist_adjust "
"manacost, recast_delay, priority, min_hp, max_hp, resist_adjust "
#ifdef BOTS
"FROM %s "
"WHERE npc_spells_id=%d ORDER BY minlevel",
@ -2744,9 +2753,11 @@ DBnpcspells_Struct *ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID)
entry.manacost = atoi(row[4]);
entry.recast_delay = atoi(row[5]);
entry.priority = atoi(row[6]);
entry.min_hp = atoi(row[7]);
entry.max_hp = atoi(row[8]);
if (row[7])
entry.resist_adjust = atoi(row[7]);
if (row[9])
entry.resist_adjust = atoi(row[9]);
else if (IsValidSpell(spell_id))
entry.resist_adjust = spells[spell_id].ResistDiff;

View File

@ -61,6 +61,8 @@ struct AISpells_Struct {
int32 recast_delay;
int16 priority;
int16 resist_adjust;
int8 min_hp; // >0 won't cast if HP is below
int8 max_hp; // >0 won't cast if HP is above
};
struct AISpellsEffects_Struct {
@ -378,7 +380,7 @@ public:
void NPCSlotTexture(uint8 slot, uint16 texture); // Sets new material values for slots
uint32 GetAdventureTemplate() const { return adventure_template_id; }
void AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint32 iType, int16 iManaCost, int32 iRecastDelay, int16 iResistAdjust);
void AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint32 iType, int16 iManaCost, int32 iRecastDelay, int16 iResistAdjust, int8 min_hp, int8 max_hp);
void AddSpellEffectToNPCList(uint16 iSpellEffectID, int32 base, int32 limit, int32 max);
void RemoveSpellFromNPCList(int16 spell_id);
Timer *GetRefaceTimer() const { return reface_timer; }

View File

@ -1993,7 +1993,7 @@ XS(XS_NPC_AddSpellToNPCList)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->AddSpellToNPCList(priority, spell_id, type, mana_cost, recast_delay, resist_adjust);
THIS->AddSpellToNPCList(priority, spell_id, type, mana_cost, recast_delay, resist_adjust, 0, 0);
}
XSRETURN_EMPTY;
}

View File

@ -48,13 +48,15 @@ struct wplist {
#pragma pack(1)
struct DBnpcspells_entries_Struct {
int16 spellid;
uint32 type;
uint8 minlevel;
uint8 maxlevel;
uint32 type;
int16 manacost;
int32 recast_delay;
int16 priority;
int32 recast_delay;
int16 resist_adjust;
int8 min_hp;
int8 max_hp;
};
#pragma pack()