From d64f76227704b1062f0bed682568141606f84220 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 25 Apr 2014 08:52:49 -0400 Subject: [PATCH 1/6] Developement Branch AISpellEffects. Debug crash on NPC death. --- .../required/2014_04_25_AISpellEffects.sql | 50 ++++ zone/MobAI.cpp | 214 +++++++++++++++++- zone/attack.cpp | 3 +- zone/bonuses.cpp | 157 +++++++------ zone/mob.h | 3 +- zone/npc.cpp | 1 + zone/npc.h | 19 +- zone/zonedb.cpp | 13 ++ zone/zonedb.h | 22 ++ zone/zonedump.h | 1 + 10 files changed, 409 insertions(+), 74 deletions(-) create mode 100644 utils/sql/git/required/2014_04_25_AISpellEffects.sql diff --git a/utils/sql/git/required/2014_04_25_AISpellEffects.sql b/utils/sql/git/required/2014_04_25_AISpellEffects.sql new file mode 100644 index 000000000..4a450b312 --- /dev/null +++ b/utils/sql/git/required/2014_04_25_AISpellEffects.sql @@ -0,0 +1,50 @@ +-- TEST SQL -- + +ALTER TABLE `npc_types` ADD `npc_spells_effects` int( 11 ) UNSIGNED NOT NULL DEFAULT '0' AFTER `npc_spells`; + +SET FOREIGN_KEY_CHECKS=0; + +-- ---------------------------- +-- Table structure for `npc_spells_effects_entries` +-- ---------------------------- +DROP TABLE IF EXISTS `npc_spells_effects_entries`; +CREATE TABLE `npc_spells_effects_entries` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `npc_spells_effects_id` int(11) NOT NULL DEFAULT '0', + `spell_effect_id` smallint(5) NOT NULL DEFAULT '0', + `minlevel` tinyint(3) unsigned NOT NULL, + `maxlevel` tinyint(3) unsigned NOT NULL, + `se_base` int(11) NOT NULL DEFAULT '0', + `se_limit` int(11) NOT NULL DEFAULT '0', + `se_max` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + UNIQUE KEY `spellsid_spellid` (`npc_spells_effects_id`,`spell_effect_id`) +) ENGINE=InnoDB AUTO_INCREMENT=18374 DEFAULT CHARSET=latin1; + +-- ---------------------------- +-- Records of npc_spells_effects_entries +-- ---------------------------- +INSERT INTO `npc_spells_effects_entries` VALUES ('1', '1', '169', '0', '255', '10000', '-1', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('2', '1', '168', '0', '255', '3999', '-1', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('3', '2', '167', '0', '255', '98', '-1', '0'); + + + +SET FOREIGN_KEY_CHECKS=0; + +-- ---------------------------- +-- Table structure for `npc_spells_effects` +-- ---------------------------- +DROP TABLE IF EXISTS `npc_spells_effects`; +CREATE TABLE `npc_spells_effects` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `name` tinytext, + `parent_list` int(11) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1079 DEFAULT CHARSET=latin1; + +-- ---------------------------- +-- Records of npc_spells_effects +-- ---------------------------- +INSERT INTO `npc_spells_effects` VALUES ('1', 'Critical', '0'); +INSERT INTO `npc_spells_effects` VALUES ('2', 'ParentTest', '1'); diff --git a/zone/MobAI.cpp b/zone/MobAI.cpp index bcb4b131b..48814425b 100644 --- a/zone/MobAI.cpp +++ b/zone/MobAI.cpp @@ -530,6 +530,7 @@ void NPC::AI_Start(uint32 iMoveDelay) { if (NPCTypedata) { AI_AddNPCSpells(NPCTypedata->npc_spells_id); ProcessSpecialAbilities(NPCTypedata->special_abilities); + AI_AddNPCSpellsEffects(NPCTypedata->npc_spells_effects_id); } SendTo(GetX(), GetY(), GetZ()); @@ -1879,7 +1880,7 @@ bool NPC::AI_EngagedCastCheck() { AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. mlog(AI__SPELLS, "Engaged autocast check triggered. Trying to cast healing spells then maybe offensive spells."); - + Shout("KAYEN"); // try casting a heal or gate if (!AICastSpell(this, 100, SpellType_Heal | SpellType_Escape | SpellType_InCombatBuff)) { // try casting a heal on nearby @@ -2277,6 +2278,7 @@ create table npc_spells_entries ( */ bool IsSpellInList(DBnpcspells_Struct* spell_list, int16 iSpellID); +bool IsSpellEffectInList(DBnpcspellseffects_Struct* spelleffect_list, uint16 iSpellEffectID, int32 base, int32 limit, int32 max); bool Compare_AI_Spells(AISpells_Struct i, AISpells_Struct j); bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { @@ -2351,6 +2353,110 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { return true; } +bool NPC::AI_AddNPCSpellsEffects(uint32 iDBSpellsEffectsID) { + + npc_spells_effects_id = iDBSpellsEffectsID; + AIspellsEffects.clear(); + + if (iDBSpellsEffectsID == 0) + return false; + + DBnpcspellseffects_Struct* spell_effects_list = database.GetNPCSpellsEffects(iDBSpellsEffectsID); + + if (!spell_effects_list) { + return false; + } + + DBnpcspellseffects_Struct* parentlist = database.GetNPCSpellsEffects(spell_effects_list->parent_list); + + uint32 i; +#if MobAI_DEBUG_Spells >= 10 + std::cout << "Loading NPCSpellsEffects onto " << this->GetName() << ": dbspellseffectsid=" << iDBSpellsEffectsID; + if (spell_effects_list) { + std::cout << " (found, " << spell_effects_list->numentries << "), parentlist=" << spell_effects)list->parent_list; + if (spell_effects_list->parent_list) { + if (parentlist) { + std::cout << " (found, " << parentlist->numentries << ")"; + } + else + std::cout << " (not found)"; + } + } + else + std::cout << " (not found)"; + std::cout << std::endl; +#endif + + if (parentlist) { + for (i=0; inumentries; i++) { + if (GetLevel() >= parentlist->entries[i].minlevel && GetLevel() <= parentlist->entries[i].maxlevel && parentlist->entries[i].spelleffectid > 0) { + if (!IsSpellEffectInList(spell_effects_list, parentlist->entries[i].spelleffectid, parentlist->entries[i].base, + parentlist->entries[i].limit, parentlist->entries[i].max)) + { + AddSpellEffectToNPCList(parentlist->entries[i].spelleffectid, + parentlist->entries[i].base, parentlist->entries[i].limit, + parentlist->entries[i].max); + } + } + } + } + + for (i=0; inumentries; i++) { + if (GetLevel() >= spell_effects_list->entries[i].minlevel && GetLevel() <= spell_effects_list->entries[i].maxlevel && spell_effects_list->entries[i].spelleffectid > 0) { + AddSpellEffectToNPCList(spell_effects_list->entries[i].spelleffectid, + spell_effects_list->entries[i].base, spell_effects_list->entries[i].limit, + spell_effects_list->entries[i].max); + } + } + + return true; +} + +void NPC::ApplyAISpellEffects(StatBonuses* newbon) +{ + if (!AI_HasSpellsEffects()) + return; + + + + for(int i=0; i < AIspellsEffects.size(); i++) + { + Shout("ApplyAISpellEffects %i %i %i %i", AIspellsEffects[i].spelleffectid, AIspellsEffects[i].base, AIspellsEffects[i].limit,AIspellsEffects[i].max); + ApplySpellsBonuses(0, 0, newbon, 0, false, 0,-1, + true, AIspellsEffects[i].spelleffectid, AIspellsEffects[i].base, AIspellsEffects[i].limit,AIspellsEffects[i].max); + } + + return; +} + +// adds a spell to the list, taking into account priority and resorting list as needed. +void NPC::AddSpellEffectToNPCList(uint16 iSpellEffectID, int32 base, int32 limit, int32 max) +{ + + if(!iSpellEffectID) + return; + + + HasAISpellEffects = true; + AISpellsEffects_Struct t; + + t.spelleffectid = iSpellEffectID; + t.base = base; + t.limit = limit; + t.max = max; + Shout("AddSpellEffectToNPCList %i %i %i %i", iSpellEffectID,base, limit, max ); + AIspellsEffects.push_back(t); +} + +bool IsSpellEffectInList(DBnpcspellseffects_Struct* spelleffect_list, uint16 iSpellEffectID, int32 base, int32 limit, int32 max) { + for (uint32 i=0; i < spelleffect_list->numentries; i++) { + if (spelleffect_list->entries[i].spelleffectid == iSpellEffectID && spelleffect_list->entries[i].base == base + && spelleffect_list->entries[i].limit == limit && spelleffect_list->entries[i].max == max) + return true; + } + return false; +} + bool IsSpellInList(DBnpcspells_Struct* spell_list, int16 iSpellID) { for (uint32 i=0; i < spell_list->numentries; i++) { if (spell_list->entries[i].spellid == iSpellID) @@ -2415,6 +2521,7 @@ void NPC::AISpellsList(Client *c) DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) { if (iDBSpellsID == 0) return 0; + if (!npc_spells_cache) { npc_spells_maxid = GetMaxNPCSpellsID(); npc_spells_cache = new DBnpcspells_Struct*[npc_spells_maxid+1]; @@ -2424,11 +2531,13 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) { npc_spells_loadtried[i] = false; } } + if (iDBSpellsID > npc_spells_maxid) return 0; if (npc_spells_cache[iDBSpellsID]) { // it's in the cache, easy =) return npc_spells_cache[iDBSpellsID]; } + else if (!npc_spells_loadtried[iDBSpellsID]) { // no reason to ask the DB again if we have failed once already npc_spells_loadtried[iDBSpellsID] = true; char errbuf[MYSQL_ERRMSG_SIZE]; @@ -2439,7 +2548,7 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) { if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, parent_list, attack_proc, proc_chance from npc_spells where id=%d", iDBSpellsID), errbuf, &result)) { safe_delete_array(query); if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); + row = mysql_fetch_row(result); uint32 tmpparent_list = atoi(row[1]); int16 tmpattack_proc = atoi(row[2]); uint8 tmpproc_chance = atoi(row[3]); @@ -2527,3 +2636,104 @@ uint32 ZoneDatabase::GetMaxNPCSpellsID() { return 0; } +DBnpcspellseffects_Struct* ZoneDatabase::GetNPCSpellsEffects(uint32 iDBSpellsEffectsID) { + if (iDBSpellsEffectsID == 0) + return 0; + + if (!npc_spellseffects_cache) { + npc_spellseffects_maxid = GetMaxNPCSpellsEffectsID(); + npc_spellseffects_cache = new DBnpcspellseffects_Struct*[npc_spellseffects_maxid+1]; + npc_spellseffects_loadtried = new bool[npc_spellseffects_maxid+1]; + for (uint32 i=0; i<=npc_spellseffects_maxid; i++) { + npc_spellseffects_cache[i] = 0; + npc_spellseffects_loadtried[i] = false; + } + } + + if (iDBSpellsEffectsID > npc_spellseffects_maxid) + return 0; + if (npc_spellseffects_cache[iDBSpellsEffectsID]) { // it's in the cache, easy =) + return npc_spellseffects_cache[iDBSpellsEffectsID]; + } + + else if (!npc_spellseffects_loadtried[iDBSpellsEffectsID]) { // no reason to ask the DB again if we have failed once already + npc_spellseffects_loadtried[iDBSpellsEffectsID] = true; + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + + if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, parent_list from npc_spells_effects where id=%d", iDBSpellsEffectsID), errbuf, &result)) { + safe_delete_array(query); + if (mysql_num_rows(result) == 1) { + row = mysql_fetch_row(result); + uint32 tmpparent_list = atoi(row[1]); + mysql_free_result(result); + if (RunQuery(query, MakeAnyLenString(&query, "SELECT spell_effect_id, minlevel, maxlevel,se_base, se_limit, se_max from npc_spells_effects_entries where npc_spells_effects_id=%d ORDER BY minlevel", iDBSpellsEffectsID), errbuf, &result)) { + safe_delete_array(query); + uint32 tmpSize = sizeof(DBnpcspellseffects_Struct) + (sizeof(DBnpcspellseffects_Struct) * mysql_num_rows(result)); + npc_spellseffects_cache[iDBSpellsEffectsID] = (DBnpcspellseffects_Struct*) new uchar[tmpSize]; + memset(npc_spellseffects_cache[iDBSpellsEffectsID], 0, tmpSize); + npc_spellseffects_cache[iDBSpellsEffectsID]->parent_list = tmpparent_list; + npc_spellseffects_cache[iDBSpellsEffectsID]->numentries = mysql_num_rows(result); + int j = 0; + while ((row = mysql_fetch_row(result))) { + int spell_effect_id = atoi(row[0]); + npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].spelleffectid = spell_effect_id; + npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].minlevel = atoi(row[1]); + npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].maxlevel = atoi(row[2]); + npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].base = atoi(row[3]); + npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].limit = atoi(row[4]); + npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].max = atoi(row[5]); + j++; + } + mysql_free_result(result); + return npc_spellseffects_cache[iDBSpellsEffectsID]; + } + else { + std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + return 0; + } + } + else { + mysql_free_result(result); + } + } + else { + std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + return 0; + } + return 0; + } + return 0; +} + +uint32 ZoneDatabase::GetMaxNPCSpellsEffectsID() { + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + + if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(id) from npc_spells_effects"), errbuf, &result)) { + safe_delete_array(query); + if (mysql_num_rows(result) == 1) { + row = mysql_fetch_row(result); + uint32 ret = 0; + if (row[0]) + ret = atoi(row[0]); + mysql_free_result(result); + return ret; + } + mysql_free_result(result); + } + else { + std::cerr << "Error in GetMaxNPCSpellsEffectsID query '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + return 0; + } + + return 0; +} + diff --git a/zone/attack.cpp b/zone/attack.cpp index e1f6b5135..fbcec2f59 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2120,7 +2120,8 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack if(p_depop == true) return false; - + + HasAISpellEffects = false; BuffFadeAll(); uint8 killed_level = GetLevel(); diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index c726333f2..341a62b74 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1258,6 +1258,10 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) } } + //Applies any perma NPC spell bonuses from npc_spells_effects table. + if (IsNPC()) + CastToNPC()->ApplyAISpellEffects(newbon); + //Removes the spell bonuses that are effected by a 'negate' debuff. if (spellbonuses.NegateEffects){ for(i = 0; i < buff_count; i++) { @@ -1270,12 +1274,13 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) if (GetClass() == BARD) newbon->ManaRegen = 0; // Bards do not get mana regen from spells. } -void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* newbon, uint16 casterId, bool item_bonus, uint32 ticsremaining, int buffslot) +void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* newbon, uint16 casterId, bool item_bonus, uint32 ticsremaining, int buffslot, + bool IsAISpellEffect, uint16 effect_id, int32 se_base, int32 se_limit, int32 se_max) { - int i, effect_value; + int i, effect_value, base2, max, effectid; Mob *caster = nullptr; - if(!IsValidSpell(spell_id)) + if(!IsAISpellEffect && !IsValidSpell(spell_id)) return; if(casterId > 0) @@ -1283,19 +1288,35 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne for (i = 0; i < EFFECT_COUNT; i++) { - if(IsBlankSpellEffect(spell_id, i)) - continue; + //Buffs/Item effects + if (!IsAISpellEffect) { - uint8 focus = IsFocusEffect(spell_id, i); - if (focus) - { - newbon->FocusEffects[focus] = spells[spell_id].effectid[i]; - continue; + if(IsBlankSpellEffect(spell_id, i)) + continue; + + uint8 focus = IsFocusEffect(spell_id, i); + if (focus) + { + newbon->FocusEffects[focus] = spells[spell_id].effectid[i]; + continue; + } + + + effectid = spells[spell_id].effectid[i]; + effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, caster, ticsremaining); + base2 = spells[spell_id].base2[i]; + max = spells[spell_id].max[i]; + } + //Use AISpellEffects + else { + effectid = effect_id; + effect_value = se_base; + base2 = se_limit; + max = se_max; + i = EFFECT_COUNT; //End the loop } - effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, caster, ticsremaining); - - switch (spells[spell_id].effectid[i]) + switch (effectid) { case SE_CurrentHP: //regens if(effect_value > 0) { @@ -1631,27 +1652,27 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_CriticalHitChance: { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) { - if(spells[spell_id].base2[i] == -1) + if(base2 == -1) newbon->CriticalHitChance[HIGHEST_SKILL+1] += effect_value; else - newbon->CriticalHitChance[spells[spell_id].base2[i]] += effect_value; + newbon->CriticalHitChance[base2] += effect_value; } else if(effect_value < 0) { - if(spells[spell_id].base2[i] == -1 && newbon->CriticalHitChance[HIGHEST_SKILL+1] > effect_value) + if(base2 == -1 && newbon->CriticalHitChance[HIGHEST_SKILL+1] > effect_value) newbon->CriticalHitChance[HIGHEST_SKILL+1] = effect_value; - else if(spells[spell_id].base2[i] != -1 && newbon->CriticalHitChance[spells[spell_id].base2[i]] > effect_value) - newbon->CriticalHitChance[spells[spell_id].base2[i]] = effect_value; + else if(base2 != -1 && newbon->CriticalHitChance[base2] > effect_value) + newbon->CriticalHitChance[base2] = effect_value; } - else if(spells[spell_id].base2[i] == -1 && newbon->CriticalHitChance[HIGHEST_SKILL+1] < effect_value) + else if(base2 == -1 && newbon->CriticalHitChance[HIGHEST_SKILL+1] < effect_value) newbon->CriticalHitChance[HIGHEST_SKILL+1] = effect_value; - else if(spells[spell_id].base2[i] != -1 && newbon->CriticalHitChance[spells[spell_id].base2[i]] < effect_value) - newbon->CriticalHitChance[spells[spell_id].base2[i]] = effect_value; + else if(base2 != -1 && newbon->CriticalHitChance[base2] < effect_value) + newbon->CriticalHitChance[base2] = effect_value; + break; } @@ -1812,7 +1833,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_HundredHands: { if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->HundredHands += spells[spell_id].base[i]; + newbon->HundredHands += effect_value; if (effect_value > 0 && effect_value > newbon->HundredHands) newbon->HundredHands = effect_value; //Increase Weapon Delay @@ -1825,7 +1846,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne { if(newbon->MeleeSkillCheck < effect_value) { newbon->MeleeSkillCheck = effect_value; - newbon->MeleeSkillCheckSkill = spells[spell_id].base2[i]==-1?255:spells[spell_id].base2[i]; + newbon->MeleeSkillCheckSkill = base2==-1?255:base2; } break; } @@ -1834,13 +1855,13 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne { if (RuleB(Spells, AdditiveBonusValues) && item_bonus){ - if(spells[spell_id].base2[i] == -1) + if(base2 == -1) newbon->HitChanceEffect[HIGHEST_SKILL+1] += effect_value; else - newbon->HitChanceEffect[spells[spell_id].base2[i]] += effect_value; + newbon->HitChanceEffect[base2] += effect_value; } - else if(spells[spell_id].base2[i] == -1){ + else if(base2 == -1){ if ((effect_value < 0) && (newbon->HitChanceEffect[HIGHEST_SKILL+1] > effect_value)) newbon->HitChanceEffect[HIGHEST_SKILL+1] = effect_value; @@ -1852,12 +1873,12 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne else { - if ((effect_value < 0) && (newbon->HitChanceEffect[spells[spell_id].base2[i]] > effect_value)) - newbon->HitChanceEffect[spells[spell_id].base2[i]] = effect_value; + if ((effect_value < 0) && (newbon->HitChanceEffect[base2] > effect_value)) + newbon->HitChanceEffect[base2] = effect_value; - else if (!newbon->HitChanceEffect[spells[spell_id].base2[i]] || - ((newbon->HitChanceEffect[spells[spell_id].base2[i]] > 0) && (newbon->HitChanceEffect[spells[spell_id].base2[i]] < effect_value))) - newbon->HitChanceEffect[spells[spell_id].base2[i]] = effect_value; + else if (!newbon->HitChanceEffect[base2] || + ((newbon->HitChanceEffect[base2] > 0) && (newbon->HitChanceEffect[base2] < effect_value))) + newbon->HitChanceEffect[base2] = effect_value; } break; @@ -1866,19 +1887,19 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_DamageModifier: { - if(spells[spell_id].base2[i] == -1) + if(base2 == -1) newbon->DamageModifier[HIGHEST_SKILL+1] += effect_value; else - newbon->DamageModifier[spells[spell_id].base2[i]] += effect_value; + newbon->DamageModifier[base2] += effect_value; break; } case SE_MinDamageModifier: { - if(spells[spell_id].base2[i] == -1) + if(base2 == -1) newbon->MinDamageModifier[HIGHEST_SKILL+1] += effect_value; else - newbon->MinDamageModifier[spells[spell_id].base2[i]] += effect_value; + newbon->MinDamageModifier[base2] += effect_value; break; } @@ -1921,8 +1942,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne newbon->DeathSave[0] = effect_value; //1='Partial' 2='Full' newbon->DeathSave[1] = buffslot; //These are used in later expansion spell effects. - newbon->DeathSave[2] = spells[spell_id].base2[i];//Min level for HealAmt - newbon->DeathSave[3] = spells[spell_id].max[i];//HealAmt + newbon->DeathSave[2] = base2;//Min level for HealAmt + newbon->DeathSave[3] = max;//HealAmt } break; } @@ -1937,7 +1958,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne else if(newbon->DivineSaveChance[0] < effect_value) { newbon->DivineSaveChance[0] = effect_value; - newbon->DivineSaveChance[1] = spells[spell_id].base2[i]; + newbon->DivineSaveChance[1] = base2; //SetDeathSaveChance(true); } break; @@ -1972,10 +1993,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_SkillDamageTaken: { - if(spells[spell_id].base2[i] == -1) + if(base2 == -1) newbon->SkillDmgTaken[HIGHEST_SKILL+1] += effect_value; else - newbon->SkillDmgTaken[spells[spell_id].base2[i]] += effect_value; + newbon->SkillDmgTaken[base2] += effect_value; break; } @@ -2000,8 +2021,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne { newbon->CriticalSpellChance += effect_value; - if (spells[spell_id].base2[i] > newbon->SpellCritDmgIncNoStack) - newbon->SpellCritDmgIncNoStack = spells[spell_id].base2[i]; + if (base2 > newbon->SpellCritDmgIncNoStack) + newbon->SpellCritDmgIncNoStack = base2; break; } @@ -2053,9 +2074,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne if(!newbon->SpellOnKill[e]) { // Base2 = Spell to fire | Base1 = % chance | Base3 = min level - newbon->SpellOnKill[e] = spells[spell_id].base2[i]; + newbon->SpellOnKill[e] = base2; newbon->SpellOnKill[e+1] = effect_value; - newbon->SpellOnKill[e+2] = spells[spell_id].max[i]; + newbon->SpellOnKill[e+2] = max; break; } } @@ -2069,7 +2090,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne if(!newbon->SpellOnDeath[e]) { // Base2 = Spell to fire | Base1 = % chance - newbon->SpellOnDeath[e] = spells[spell_id].base2[i]; + newbon->SpellOnDeath[e] = base2; newbon->SpellOnDeath[e+1] = effect_value; break; } @@ -2079,26 +2100,26 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_CriticalDamageMob: { - if(spells[spell_id].base2[i] == -1) + if(base2 == -1) newbon->CritDmgMob[HIGHEST_SKILL+1] += effect_value; else - newbon->CritDmgMob[spells[spell_id].base2[i]] += effect_value; + newbon->CritDmgMob[base2] += effect_value; break; } case SE_ReduceSkillTimer: { - if(newbon->SkillReuseTime[spells[spell_id].base2[i]] < effect_value) - newbon->SkillReuseTime[spells[spell_id].base2[i]] = effect_value; + if(newbon->SkillReuseTime[base2] < effect_value) + newbon->SkillReuseTime[base2] = effect_value; break; } case SE_SkillDamageAmount: { - if(spells[spell_id].base2[i] == -1) + if(base2 == -1) newbon->SkillDamageAmount[HIGHEST_SKILL+1] += effect_value; else - newbon->SkillDamageAmount[spells[spell_id].base2[i]] += effect_value; + newbon->SkillDamageAmount[base2] += effect_value; break; } @@ -2188,10 +2209,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_SkillDamageAmount2: { - if(spells[spell_id].base2[i] == -1) + if(base2 == -1) newbon->SkillDamageAmount2[HIGHEST_SKILL+1] += effect_value; else - newbon->SkillDamageAmount2[spells[spell_id].base2[i]] += effect_value; + newbon->SkillDamageAmount2[base2] += effect_value; break; } @@ -2219,7 +2240,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne if (newbon->MeleeThresholdGuard[0] < effect_value){ newbon->MeleeThresholdGuard[0] = effect_value; newbon->MeleeThresholdGuard[1] = buffslot; - newbon->MeleeThresholdGuard[2] = spells[spell_id].base2[i]; + newbon->MeleeThresholdGuard[2] = base2; } break; } @@ -2229,7 +2250,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne if (newbon->SpellThresholdGuard[0] < effect_value){ newbon->SpellThresholdGuard[0] = effect_value; newbon->SpellThresholdGuard[1] = buffslot; - newbon->SpellThresholdGuard[2] = spells[spell_id].base2[i]; + newbon->SpellThresholdGuard[2] = base2; } break; } @@ -2263,20 +2284,20 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_TriggerMeleeThreshold: { - if (newbon->TriggerMeleeThreshold[2] < spells[spell_id].base2[i]){ + if (newbon->TriggerMeleeThreshold[2] < base2){ newbon->TriggerMeleeThreshold[0] = effect_value; newbon->TriggerMeleeThreshold[1] = buffslot; - newbon->TriggerMeleeThreshold[2] = spells[spell_id].base2[i]; + newbon->TriggerMeleeThreshold[2] = base2; } break; } case SE_TriggerSpellThreshold: { - if (newbon->TriggerSpellThreshold[2] < spells[spell_id].base2[i]){ + if (newbon->TriggerSpellThreshold[2] < base2){ newbon->TriggerSpellThreshold[0] = effect_value; newbon->TriggerSpellThreshold[1] = buffslot; - newbon->TriggerSpellThreshold[2] = spells[spell_id].base2[i]; + newbon->TriggerSpellThreshold[2] = base2; } break; } @@ -2291,7 +2312,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_ShieldEquipDmgMod: newbon->ShieldEquipDmgMod[0] += effect_value; - newbon->ShieldEquipDmgMod[1] += spells[spell_id].base2[i]; + newbon->ShieldEquipDmgMod[1] += base2; break; case SE_BlockBehind: @@ -2380,7 +2401,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne break; case SE_AddSingingMod: - switch (spells[spell_id].base2[i]) + switch (base2) { case ItemTypeWindInstrument: newbon->windMod += effect_value; @@ -2474,8 +2495,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) { if(!newbon->SEResist[e] && - ((newbon->SEResist[e] = spells[spell_id].base2[i]) && (newbon->SEResist[e+1] < effect_value)) ){ - newbon->SEResist[e] = spells[spell_id].base2[i]; + ((newbon->SEResist[e] = base2) && (newbon->SEResist[e+1] < effect_value)) ){ + newbon->SEResist[e] = base2; newbon->SEResist[e+1] = effect_value; break; } @@ -2493,7 +2514,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_GiveDoubleRiposte: { //Only allow for regular double riposte chance. - if(newbon->GiveDoubleRiposte[spells[spell_id].base2[i]] == 0){ + if(newbon->GiveDoubleRiposte[base2] == 0){ if(newbon->GiveDoubleRiposte[0] < effect_value) newbon->GiveDoubleRiposte[0] = effect_value; } @@ -2504,7 +2525,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne { if(newbon->SlayUndead[1] < effect_value) newbon->SlayUndead[0] = effect_value; // Rate - newbon->SlayUndead[1] = spells[spell_id].base2[i]; // Damage Modifier + newbon->SlayUndead[1] = base2; // Damage Modifier break; } @@ -2520,7 +2541,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_ImprovedTaunt: if (newbon->ImprovedTaunt[0] < effect_value) { newbon->ImprovedTaunt[0] = effect_value; - newbon->ImprovedTaunt[1] = spells[spell_id].base2[i]; + newbon->ImprovedTaunt[1] = base2; newbon->ImprovedTaunt[2] = buffslot; } break; @@ -2531,7 +2552,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne break; case SE_FrenziedDevastation: - newbon->FrenziedDevastation += spells[spell_id].base2[i]; + newbon->FrenziedDevastation += base2; break; case SE_Root: diff --git a/zone/mob.h b/zone/mob.h index 0784b7925..90013645b 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -182,7 +182,8 @@ public: bool IsBeneficialAllowed(Mob *target); virtual int GetCasterLevel(uint16 spell_id); void ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* newbon, uint16 casterID = 0, - bool item_bonus = false, uint32 ticsremaining = 0, int buffslot = -1); + bool item_bonus = false, uint32 ticsremaining = 0, int buffslot = -1, + bool IsAISpellEffect = false, uint16 effect_id = 0, int32 se_base = 0, int32 se_limit = 0, int32 se_max = 0); void NegateSpellsBonuses(uint16 spell_id); virtual float GetActSpellRange(uint16 spell_id, float range, bool IsBard = false) { return range;} virtual int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr) { return value; } diff --git a/zone/npc.cpp b/zone/npc.cpp index 2611300d8..3886d7c66 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -231,6 +231,7 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float npc_spells_id = 0; HasAISpell = false; + HasAISpellEffects = false; if(GetClass() == MERCERNARY_MASTER && RuleB(Mercs, AllowMercs)) { diff --git a/zone/npc.h b/zone/npc.h index 55bed4abc..ae444c099 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -66,6 +66,13 @@ struct AISpells_Struct { int16 resist_adjust; }; +struct AISpellsEffects_Struct { + uint16 spelleffectid; + int32 base; + int32 limit; + int32 max; +}; + class AA_SwarmPetInfo; class NPC : public Mob @@ -96,8 +103,11 @@ public: virtual void AI_Stop(); void AI_DoMovement(); bool AI_AddNPCSpells(uint32 iDBSpellsID); + bool AI_AddNPCSpellsEffects(uint32 iDBSpellsEffectsID); virtual bool AI_EngagedCastCheck(); bool AI_HasSpells() { return HasAISpell; } + bool AI_HasSpellsEffects() { return HasAISpellEffects; } + void ApplyAISpellEffects(StatBonuses* newbon); virtual bool AI_PursueCastCheck(); virtual bool AI_IdleCastCheck(); @@ -289,6 +299,7 @@ public: inline void GiveNPCTypeData(NPCType *ours) { NPCTypedata_ours = ours; } inline const uint32 GetNPCSpellsID() const { return npc_spells_id; } + inline const uint32 GetNPCSpellsEffectsID() const { return npc_spells_effects_id; } ItemList itemlist; //kathgar - why is this public? Doing other things or I would check the code @@ -339,6 +350,7 @@ public: uint32 GetAdventureTemplate() const { return adventure_template_id; } void AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint16 iType, int16 iManaCost, int32 iRecastDelay, int16 iResistAdjust); + void AddSpellEffectToNPCList(uint16 iSpellEffectID, int32 base, int32 limit, int32 max); void RemoveSpellFromNPCList(int16 spell_id); Timer *GetRefaceTimer() const { return reface_timer; } const uint32 GetAltCurrencyType() const { return NPCTypedata->alt_currency_type; } @@ -400,8 +412,11 @@ protected: bool HasAISpell; virtual bool AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes); virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0); - - + + uint32 npc_spells_effects_id; + std::vector AIspellsEffects; + bool HasAISpellEffects; + uint32 max_dmg; uint32 min_dmg; int32 accuracy_rating; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 893a1a27a..2178a15c9 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -33,8 +33,11 @@ ZoneDatabase::ZoneDatabase(const char* host, const char* user, const char* passw void ZoneDatabase::ZDBInitVars() { memset(door_isopen_array, 0, sizeof(door_isopen_array)); npc_spells_maxid = 0; + npc_spellseffects_maxid = 0; npc_spells_cache = 0; + npc_spellseffects_cache = 0; npc_spells_loadtried = 0; + npc_spellseffects_loadtried = 0; max_faction = 0; faction_array = nullptr; } @@ -49,6 +52,14 @@ ZoneDatabase::~ZoneDatabase() { } safe_delete_array(npc_spells_loadtried); + if (npc_spellseffects_cache) { + for (x=0; x<=npc_spellseffects_maxid; x++) { + safe_delete_array(npc_spellseffects_cache[x]); + } + safe_delete_array(npc_spellseffects_cache); + } + safe_delete_array(npc_spellseffects_loadtried); + if (faction_array != nullptr) { for (x=0; x <= max_faction; x++) { if (faction_array[x] != 0) @@ -1053,6 +1064,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { "npc_types.attack_count," "npc_types.special_abilities," "npc_types.npc_spells_id," + "npc_types.npc_spells_effects_id," "npc_types.d_meele_texture1," "npc_types.d_meele_texture2," "npc_types.prim_melee_type," @@ -1151,6 +1163,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->attack_count = atoi(row[r++]); strn0cpy(tmpNPCType->special_abilities, row[r++], 512); tmpNPCType->npc_spells_id = atoi(row[r++]); + tmpNPCType->npc_spells_effects_id = atoi(row[r++]); tmpNPCType->d_meele_texture1 = atoi(row[r++]); tmpNPCType->d_meele_texture2 = atoi(row[r++]); tmpNPCType->prim_melee_type = atoi(row[r++]); diff --git a/zone/zonedb.h b/zone/zonedb.h index 797b59980..e53b45530 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -30,6 +30,17 @@ struct DBnpcspells_entries_Struct { }; #pragma pack() +#pragma pack(1) +struct DBnpcspellseffects_entries_Struct { + int16 spelleffectid; + uint8 minlevel; + uint8 maxlevel; + int32 base; + int32 limit; + int32 max; +}; +#pragma pack() + struct DBnpcspells_Struct { uint32 parent_list; int16 attack_proc; @@ -38,6 +49,12 @@ struct DBnpcspells_Struct { DBnpcspells_entries_Struct entries[0]; }; +struct DBnpcspellseffects_Struct { + uint32 parent_list; + uint32 numentries; + DBnpcspellseffects_entries_Struct entries[0]; +}; + struct DBTradeskillRecipe_Struct { SkillUseTypes tradeskill; int16 skill_needed; @@ -345,7 +362,9 @@ public: void AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* itemlist, uint32* copper, uint32* silver, uint32* gold, uint32* plat); void AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* itemlist, uint8 droplimit, uint8 mindrop); uint32 GetMaxNPCSpellsID(); + uint32 GetMaxNPCSpellsEffectsID(); DBnpcspells_Struct* GetNPCSpells(uint32 iDBSpellsID); + DBnpcspellseffects_Struct* GetNPCSpellsEffects(uint32 iDBSpellsEffectsID); /* * Mercs @@ -475,8 +494,11 @@ protected: uint32 max_faction; Faction** faction_array; uint32 npc_spells_maxid; + uint32 npc_spellseffects_maxid; DBnpcspells_Struct** npc_spells_cache; bool* npc_spells_loadtried; + DBnpcspellseffects_Struct** npc_spellseffects_cache; + bool* npc_spellseffects_loadtried; uint8 door_isopen_array[255]; }; diff --git a/zone/zonedump.h b/zone/zonedump.h index 39c6b39d7..e18734d4f 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -53,6 +53,7 @@ struct NPCType uint8 helmtexture; uint32 loottable_id; uint32 npc_spells_id; + uint32 npc_spells_effects_id; int32 npc_faction_id; uint32 merchanttype; uint32 alt_currency_type; From 391b6ed515c7731e2d5ca9c6d3008a2e701d89fc Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 25 Apr 2014 09:07:48 -0400 Subject: [PATCH 2/6] fix --- utils/sql/git/required/2014_04_25_AISpellEffects.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/sql/git/required/2014_04_25_AISpellEffects.sql b/utils/sql/git/required/2014_04_25_AISpellEffects.sql index 4a450b312..a85b117bc 100644 --- a/utils/sql/git/required/2014_04_25_AISpellEffects.sql +++ b/utils/sql/git/required/2014_04_25_AISpellEffects.sql @@ -1,6 +1,6 @@ -- TEST SQL -- -ALTER TABLE `npc_types` ADD `npc_spells_effects` int( 11 ) UNSIGNED NOT NULL DEFAULT '0' AFTER `npc_spells`; +ALTER TABLE `npc_types` ADD `npc_spells_effects_id` int( 11 ) UNSIGNED NOT NULL DEFAULT '0' AFTER `npc_spells_id`; SET FOREIGN_KEY_CHECKS=0; From 380cf8691a0fb0c9fd27c2544fad5500ad778db4 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 27 Apr 2014 03:57:14 -0400 Subject: [PATCH 3/6] Implemented new table 'npc_spells_effects' and 'npc_spells_effects_entires'. Implemented new field in 'npc_spell_effects_id' in npc_types. These are used to directly apply spell effect bonuses to NPC's without requirings spells/buffs. Example: Allow an npc to spawn with an innate 50 pt damage shield and a 5% chance to critical hit. Please see the wiki page: http://wiki.eqemulator.org/p?npc_spell_effects_entries for details. *NPC's can now do critical heals / damage spells if bonus is applied from table. Required SQL: utils/sql/git/required/2014_04_27_AISpellEffects.sql Note: 30 examples of spell effects have been included by default in this sql. Edited/removed as needed. --- changelog.txt | 14 +++ .../required/2014_04_27_AISpellEffects.sql | 104 ++++++++++++++++++ zone/MobAI.cpp | 9 +- zone/bonuses.cpp | 42 +++++-- zone/effects.cpp | 44 +++++++- zone/mob.cpp | 28 ++--- zone/spell_effects.cpp | 2 +- 7 files changed, 208 insertions(+), 35 deletions(-) create mode 100644 utils/sql/git/required/2014_04_27_AISpellEffects.sql diff --git a/changelog.txt b/changelog.txt index fe35332b6..92bb01e61 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,19 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 04/27/2014 == +Kayen: Implemented new table 'npc_spells_effects' and 'npc_spells_effects_entires'. + Implemented new field in 'npc_spell_effects_id' in npc_types. + + +These are used to directly apply spell effect bonuses to NPC's without requirings spells/buffs. +Example: Allow an npc to spawn with an innate 50 pt damage shield and a 5% chance to critical hit. +Please see the wiki page: http://wiki.eqemulator.org/p?npc_spell_effects_entries for details. +*NPC's can now do critical heals / damage spells if bonus is applied from table. + +Required SQL: utils/sql/git/required/2014_04_27_AISpellEffects.sql +Note: 30 examples of spell effects have been included by default in this sql. Edited/removed as needed. + + == 04/25/2014 == cavedude: Corrected a crash in spawn_conditions caused by NPCs on a one way path. cavedude: Added strict column to spawn_events which will prevent an event from enabling if it's mid-cycle. diff --git a/utils/sql/git/required/2014_04_27_AISpellEffects.sql b/utils/sql/git/required/2014_04_27_AISpellEffects.sql new file mode 100644 index 000000000..6a5645513 --- /dev/null +++ b/utils/sql/git/required/2014_04_27_AISpellEffects.sql @@ -0,0 +1,104 @@ +-- Note: The data entered into the new table are only examples and can be deleted/modified as needed. + +ALTER TABLE `npc_types` ADD `npc_spells_effects_id` int( 11 ) UNSIGNED NOT NULL DEFAULT '0' AFTER `npc_spells_id`; + +SET FOREIGN_KEY_CHECKS=0; + +-- ---------------------------- +-- Table structure for `npc_spells_effects` +-- ---------------------------- +DROP TABLE IF EXISTS `npc_spells_effects`; +CREATE TABLE `npc_spells_effects` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `name` tinytext, + `parent_list` int(11) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1080 DEFAULT CHARSET=latin1; + +-- ---------------------------- +-- Records of npc_spells_effects +-- ---------------------------- +INSERT INTO `npc_spells_effects` VALUES ('1', 'Critical Melee [All Skills]', '0'); +INSERT INTO `npc_spells_effects` VALUES ('2', 'Damage Shield', '0'); +INSERT INTO `npc_spells_effects` VALUES ('3', 'Melee Haste', '0'); +INSERT INTO `npc_spells_effects` VALUES ('4', 'Resist Spell Chance', '0'); +INSERT INTO `npc_spells_effects` VALUES ('5', 'Resist Direct Dmg Spell Chance', '0'); +INSERT INTO `npc_spells_effects` VALUES ('6', 'Reflect Spell Chance', '0'); +INSERT INTO `npc_spells_effects` VALUES ('7', 'Spell Damage Shield', '0'); +INSERT INTO `npc_spells_effects` VALUES ('8', 'Melee Mitigation [All]', '0'); +INSERT INTO `npc_spells_effects` VALUES ('9', 'Avoid Melee', '0'); +INSERT INTO `npc_spells_effects` VALUES ('10', 'Riposte Chance', '0'); +INSERT INTO `npc_spells_effects` VALUES ('11', 'Dodge Chance', '0'); +INSERT INTO `npc_spells_effects` VALUES ('12', 'Parry Chance', '0'); +INSERT INTO `npc_spells_effects` VALUES ('13', 'Decrease Dmg Taken [2HS]', '0'); +INSERT INTO `npc_spells_effects` VALUES ('14', 'Increase Dmg Taken [1HS]', '0'); +INSERT INTO `npc_spells_effects` VALUES ('15', 'Block Chance', '0'); +INSERT INTO `npc_spells_effects` VALUES ('16', 'Melee Lifetap', '0'); +INSERT INTO `npc_spells_effects` VALUES ('17', 'Hit Chance', '0'); +INSERT INTO `npc_spells_effects` VALUES ('18', 'Increase Dmg [1HS]', '0'); +INSERT INTO `npc_spells_effects` VALUES ('19', 'Increase Archery Dmg', '0'); +INSERT INTO `npc_spells_effects` VALUES ('20', 'Flurry Chance', '0'); +INSERT INTO `npc_spells_effects` VALUES ('21', 'Add Damage [2HS]', '0'); +INSERT INTO `npc_spells_effects` VALUES ('22', 'Divine Aura', '0'); +INSERT INTO `npc_spells_effects` VALUES ('23', 'Cast CH on Kill', '0'); +INSERT INTO `npc_spells_effects` VALUES ('24', 'Critical Heal', '0'); +INSERT INTO `npc_spells_effects` VALUES ('25', 'Critical Direct Dmg', '0'); +INSERT INTO `npc_spells_effects` VALUES ('26', 'Heal Rate', '0'); +INSERT INTO `npc_spells_effects` VALUES ('27', 'Negate Damage Shield', '0'); +INSERT INTO `npc_spells_effects` VALUES ('28', 'Increase Spell Vulnerability [All]', '0'); +INSERT INTO `npc_spells_effects` VALUES ('29', 'Decrease Spell Vulnerability [FR]', '0'); +INSERT INTO `npc_spells_effects` VALUES ('30', 'Movement Speed', '0'); + +SET FOREIGN_KEY_CHECKS=0; + +-- ---------------------------- +-- Table structure for `npc_spells_effects_entries` +-- ---------------------------- +DROP TABLE IF EXISTS `npc_spells_effects_entries`; +CREATE TABLE `npc_spells_effects_entries` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `npc_spells_effects_id` int(11) NOT NULL DEFAULT '0', + `spell_effect_id` smallint(5) NOT NULL DEFAULT '0', + `minlevel` tinyint(3) unsigned NOT NULL, + `maxlevel` tinyint(3) unsigned NOT NULL, + `se_base` int(11) NOT NULL DEFAULT '0', + `se_limit` int(11) NOT NULL DEFAULT '0', + `se_max` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + UNIQUE KEY `spellsid_spellid` (`npc_spells_effects_id`,`spell_effect_id`) +) ENGINE=InnoDB AUTO_INCREMENT=18374 DEFAULT CHARSET=latin1; + +-- ---------------------------- +-- Records of npc_spells_effects_entries +-- ---------------------------- +INSERT INTO `npc_spells_effects_entries` VALUES ('1', '1', '169', '0', '255', '10000', '-1', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('2', '2', '59', '0', '255', '-60', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('3', '3', '11', '0', '255', '150', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('4', '4', '180', '0', '255', '50', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('5', '5', '378', '0', '255', '85', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('6', '6', '158', '0', '255', '50', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('7', '7', '157', '0', '255', '-300', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('8', '8', '168', '0', '255', '-50', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('9', '9', '172', '0', '255', '10000', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('10', '10', '173', '0', '255', '10000', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('11', '11', '174', '0', '255', '10000', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('12', '12', '175', '0', '255', '10000', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('13', '13', '197', '0', '255', '-80', '3', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('14', '14', '197', '0', '255', '80', '1', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('15', '15', '188', '0', '255', '10000', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('16', '16', '178', '0', '255', '90', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('17', '17', '184', '0', '255', '10000', '-1', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('18', '18', '185', '0', '255', '100', '1', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('19', '19', '301', '0', '255', '100', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('20', '20', '279', '0', '255', '50', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('21', '21', '220', '0', '255', '2000', '1', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('22', '22', '40', '0', '255', '1', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('23', '23', '360', '0', '255', '100', '13', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('24', '24', '274', '0', '255', '90', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('25', '25', '294', '0', '255', '100', '200', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('26', '26', '120', '0', '255', '50', '0', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('27', '27', '382', '0', '255', '0', '55', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('28', '28', '296', '0', '255', '1000', '-1', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('29', '29', '296', '0', '255', '-50', '2', '0'); +INSERT INTO `npc_spells_effects_entries` VALUES ('30', '30', '3', '0', '255', '60', '0', '0'); + diff --git a/zone/MobAI.cpp b/zone/MobAI.cpp index 7574f19ad..3128eb111 100644 --- a/zone/MobAI.cpp +++ b/zone/MobAI.cpp @@ -1901,7 +1901,7 @@ bool NPC::AI_EngagedCastCheck() { AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. mlog(AI__SPELLS, "Engaged autocast check triggered. Trying to cast healing spells then maybe offensive spells."); - Shout("KAYEN"); + // try casting a heal or gate if (!AICastSpell(this, 100, SpellType_Heal | SpellType_Escape | SpellType_InCombatBuff)) { // try casting a heal on nearby @@ -2437,12 +2437,9 @@ void NPC::ApplyAISpellEffects(StatBonuses* newbon) { if (!AI_HasSpellsEffects()) return; - - for(int i=0; i < AIspellsEffects.size(); i++) { - Shout("ApplyAISpellEffects %i %i %i %i", AIspellsEffects[i].spelleffectid, AIspellsEffects[i].base, AIspellsEffects[i].limit,AIspellsEffects[i].max); ApplySpellsBonuses(0, 0, newbon, 0, false, 0,-1, true, AIspellsEffects[i].spelleffectid, AIspellsEffects[i].base, AIspellsEffects[i].limit,AIspellsEffects[i].max); } @@ -2456,7 +2453,6 @@ void NPC::AddSpellEffectToNPCList(uint16 iSpellEffectID, int32 base, int32 limit if(!iSpellEffectID) return; - HasAISpellEffects = true; AISpellsEffects_Struct t; @@ -2465,7 +2461,6 @@ void NPC::AddSpellEffectToNPCList(uint16 iSpellEffectID, int32 base, int32 limit t.base = base; t.limit = limit; t.max = max; - Shout("AddSpellEffectToNPCList %i %i %i %i", iSpellEffectID,base, limit, max ); AIspellsEffects.push_back(t); } @@ -2692,7 +2687,7 @@ DBnpcspellseffects_Struct* ZoneDatabase::GetNPCSpellsEffects(uint32 iDBSpellsEff mysql_free_result(result); if (RunQuery(query, MakeAnyLenString(&query, "SELECT spell_effect_id, minlevel, maxlevel,se_base, se_limit, se_max from npc_spells_effects_entries where npc_spells_effects_id=%d ORDER BY minlevel", iDBSpellsEffectsID), errbuf, &result)) { safe_delete_array(query); - uint32 tmpSize = sizeof(DBnpcspellseffects_Struct) + (sizeof(DBnpcspellseffects_Struct) * mysql_num_rows(result)); + uint32 tmpSize = sizeof(DBnpcspellseffects_Struct) + (sizeof(DBnpcspellseffects_entries_Struct) * mysql_num_rows(result)); npc_spellseffects_cache[iDBSpellsEffectsID] = (DBnpcspellseffects_Struct*) new uchar[tmpSize]; memset(npc_spellseffects_cache[iDBSpellsEffectsID], 0, tmpSize); npc_spellseffects_cache[iDBSpellsEffectsID]->parent_list = tmpparent_list; diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 341a62b74..db0f81115 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1158,14 +1158,20 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) break; } + case SE_SpellEffectResistChance: { for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) { - if(!newbon->SEResist[e] || ((newbon->SEResist[e] = base2) && (newbon->SEResist[e+1] < base1)) ){ - newbon->SEResist[e] = base2; - newbon->SEResist[e+1] = base1; - break; + if(newbon->SEResist[e+1] && (newbon->SEResist[e] == base2) && (newbon->SEResist[e+1] < base1)){ + newbon->SEResist[e] = base2; //Spell Effect ID + newbon->SEResist[e+1] = base1; //Resist Chance + break; + } + else if (!newbon->SEResist[e+1]){ + newbon->SEResist[e] = base2; //Spell Effect ID + newbon->SEResist[e+1] = base1; //Resist Chance + break; } } break; @@ -1791,10 +1797,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne newbon->MeleeLifetap += spells[spell_id].base[i]; else if((effect_value < 0) && (newbon->MeleeLifetap > effect_value)) - newbon->MeleeLifetap = spells[spell_id].base[i]; + newbon->MeleeLifetap = effect_value; - else if(newbon->MeleeLifetap < spells[spell_id].base[i]) - newbon->MeleeLifetap = spells[spell_id].base[i]; + else if(newbon->MeleeLifetap < effect_value) + newbon->MeleeLifetap = effect_value; break; } @@ -2494,10 +2500,14 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne { for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) { - if(!newbon->SEResist[e] && - ((newbon->SEResist[e] = base2) && (newbon->SEResist[e+1] < effect_value)) ){ - newbon->SEResist[e] = base2; - newbon->SEResist[e+1] = effect_value; + if(newbon->SEResist[e+1] && (newbon->SEResist[e] == base2) && (newbon->SEResist[e+1] < effect_value)){ + newbon->SEResist[e] = base2; //Spell Effect ID + newbon->SEResist[e+1] = effect_value; //Resist Chance + break; + } + else if (!newbon->SEResist[e+1]){ + newbon->SEResist[e] = base2; //Spell Effect ID + newbon->SEResist[e+1] = effect_value; //Resist Chance break; } } @@ -2598,7 +2608,15 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_Screech: newbon->Screech = effect_value; break; - + + //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table + if (IsAISpellEffect) { + + //Non-Focused Effect to modify incomming spell damage by resist type. + case SE_FcSpellVulnerability: + ModVulnerability(base2, effect_value); + break; + } } } } diff --git a/zone/effects.cpp b/zone/effects.cpp index 329c69084..f2a8db2a6 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -55,9 +55,36 @@ int32 NPC::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { else value -= target->GetFcDamageAmtIncoming(this, spell_id)/spells[spell_id].buffduration; } - + value += dmg*SpellFocusDMG/100; + if (AI_HasSpellsEffects()){ + int16 chance = 0; + int ratio = 0; + + if (spells[spell_id].buffduration == 0) { + + chance += spellbonuses.CriticalSpellChance + spellbonuses.FrenziedDevastation; + + if (chance && MakeRandomInt(1,100) <= chance){ + + ratio += spellbonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncNoStack; + value += (value*ratio)/100; + entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, OTHER_CRIT_BLAST, GetCleanName(), itoa(-value)); + } + } + else { + + chance += spellbonuses.CriticalDoTChance; + + if (chance && MakeRandomInt(1,100) <= chance){ + + ratio += spellbonuses.DotCritDmgIncrease; + value += (value*ratio)/100; + } + } + } + return value; } @@ -254,6 +281,21 @@ int32 NPC::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id); value += value*target->GetHealRate(spell_id, this)/100; } + + //Allow for critical heal chance if NPC is loading spell effect bonuses. + if (AI_HasSpellsEffects()){ + + if(spells[spell_id].buffduration < 1) { + + if(spellbonuses.CriticalHealChance && (MakeRandomInt(0,99) < spellbonuses.CriticalHealChance)) { + value = value*2; + entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, OTHER_CRIT_HEAL, GetCleanName(), itoa(value)); + } + } + else if(spellbonuses.CriticalHealOverTime && (MakeRandomInt(0,99) < spellbonuses.CriticalHealOverTime)) { + value = value*2; + } + } return value; } diff --git a/zone/mob.cpp b/zone/mob.cpp index 48452f26a..dcd204d0b 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -4150,10 +4150,10 @@ void Mob::TrySpellOnKill(uint8 level, uint16 spell_id) for (int i = 0; i < EFFECT_COUNT; i++) { if (spells[spell_id].effectid[i] == SE_SpellOnKill2) { - if (spells[spell_id].max[i] <= level) + if (IsValidSpell(spells[spell_id].base2[i]) && spells[spell_id].max[i] <= level) { if(MakeRandomInt(0,99) < spells[spell_id].base[i]) - SpellFinished(spells[spell_id].base2[i], this); + SpellFinished(spells[spell_id].base2[i], this, 10, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff); } } } @@ -4166,19 +4166,19 @@ void Mob::TrySpellOnKill(uint8 level, uint16 spell_id) // Allow to check AA, items and buffs in all cases. Base2 = Spell to fire | Base1 = % chance | Base3 = min level for(int i = 0; i < MAX_SPELL_TRIGGER*3; i+=3) { - if(aabonuses.SpellOnKill[i] && (level >= aabonuses.SpellOnKill[i + 2])) { + if(aabonuses.SpellOnKill[i] && IsValidSpell(aabonuses.SpellOnKill[i]) && (level >= aabonuses.SpellOnKill[i + 2])) { if(MakeRandomInt(0, 99) < static_cast(aabonuses.SpellOnKill[i + 1])) - SpellFinished(aabonuses.SpellOnKill[i], this); + SpellFinished(aabonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); } - if(itembonuses.SpellOnKill[i] && (level >= itembonuses.SpellOnKill[i + 2])){ + if(itembonuses.SpellOnKill[i] && IsValidSpell(itembonuses.SpellOnKill[i]) && (level >= itembonuses.SpellOnKill[i + 2])){ if(MakeRandomInt(0, 99) < static_cast(itembonuses.SpellOnKill[i + 1])) - SpellFinished(itembonuses.SpellOnKill[i], this); + SpellFinished(itembonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); } - if(spellbonuses.SpellOnKill[i] && (level >= spellbonuses.SpellOnKill[i + 2])) { + if(spellbonuses.SpellOnKill[i] && IsValidSpell(spellbonuses.SpellOnKill[i]) && (level >= spellbonuses.SpellOnKill[i + 2])) { if(MakeRandomInt(0, 99) < static_cast(spellbonuses.SpellOnKill[i + 1])) - SpellFinished(spellbonuses.SpellOnKill[i], this); + SpellFinished(spellbonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); } } @@ -4193,21 +4193,21 @@ bool Mob::TrySpellOnDeath() return false; for(int i = 0; i < MAX_SPELL_TRIGGER*2; i+=2) { - if(IsClient() && aabonuses.SpellOnDeath[i]) { + if(IsClient() && aabonuses.SpellOnDeath[i] && IsValidSpell(aabonuses.SpellOnDeath[i])) { if(MakeRandomInt(0, 99) < static_cast(aabonuses.SpellOnDeath[i + 1])) { - SpellFinished(aabonuses.SpellOnDeath[i], this); + SpellFinished(aabonuses.SpellOnDeath[i], this, 10, 0, -1, spells[aabonuses.SpellOnDeath[i]].ResistDiff); } } - if(itembonuses.SpellOnDeath[i]) { + if(itembonuses.SpellOnDeath[i] && IsValidSpell(itembonuses.SpellOnDeath[i])) { if(MakeRandomInt(0, 99) < static_cast(itembonuses.SpellOnDeath[i + 1])) { - SpellFinished(itembonuses.SpellOnDeath[i], this); + SpellFinished(itembonuses.SpellOnDeath[i], this, 10, 0, -1, spells[itembonuses.SpellOnDeath[i]].ResistDiff); } } - if(spellbonuses.SpellOnDeath[i]) { + if(spellbonuses.SpellOnDeath[i] && IsValidSpell(spellbonuses.SpellOnDeath[i])) { if(MakeRandomInt(0, 99) < static_cast(spellbonuses.SpellOnDeath[i + 1])) { - SpellFinished(spellbonuses.SpellOnDeath[i], this); + SpellFinished(spellbonuses.SpellOnDeath[i], this, 10, 0, -1, spells[spellbonuses.SpellOnDeath[i]].ResistDiff); } } } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 4ecb9d221..8731dfaab 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5675,7 +5675,7 @@ uint16 Mob::GetSpellEffectResistChance(uint16 spell_id) if(!IsValidSpell(spell_id)) return 0; - if (!aabonuses.SEResist[0] && !spellbonuses.SEResist[0] && !itembonuses.SEResist[0]) + if (!aabonuses.SEResist[1] && !spellbonuses.SEResist[1] && !itembonuses.SEResist[1]) return 0; uint16 resist_chance = 0; From d3a9d509a832ecc1231c3cbcc385fe5d9cef4228 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 27 Apr 2014 04:02:41 -0400 Subject: [PATCH 4/6] remove old sql --- .../required/2014_04_25_AISpellEffects.sql | 50 ------------------- 1 file changed, 50 deletions(-) delete mode 100644 utils/sql/git/required/2014_04_25_AISpellEffects.sql diff --git a/utils/sql/git/required/2014_04_25_AISpellEffects.sql b/utils/sql/git/required/2014_04_25_AISpellEffects.sql deleted file mode 100644 index a85b117bc..000000000 --- a/utils/sql/git/required/2014_04_25_AISpellEffects.sql +++ /dev/null @@ -1,50 +0,0 @@ --- TEST SQL -- - -ALTER TABLE `npc_types` ADD `npc_spells_effects_id` int( 11 ) UNSIGNED NOT NULL DEFAULT '0' AFTER `npc_spells_id`; - -SET FOREIGN_KEY_CHECKS=0; - --- ---------------------------- --- Table structure for `npc_spells_effects_entries` --- ---------------------------- -DROP TABLE IF EXISTS `npc_spells_effects_entries`; -CREATE TABLE `npc_spells_effects_entries` ( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `npc_spells_effects_id` int(11) NOT NULL DEFAULT '0', - `spell_effect_id` smallint(5) NOT NULL DEFAULT '0', - `minlevel` tinyint(3) unsigned NOT NULL, - `maxlevel` tinyint(3) unsigned NOT NULL, - `se_base` int(11) NOT NULL DEFAULT '0', - `se_limit` int(11) NOT NULL DEFAULT '0', - `se_max` int(11) NOT NULL DEFAULT '0', - PRIMARY KEY (`id`), - UNIQUE KEY `spellsid_spellid` (`npc_spells_effects_id`,`spell_effect_id`) -) ENGINE=InnoDB AUTO_INCREMENT=18374 DEFAULT CHARSET=latin1; - --- ---------------------------- --- Records of npc_spells_effects_entries --- ---------------------------- -INSERT INTO `npc_spells_effects_entries` VALUES ('1', '1', '169', '0', '255', '10000', '-1', '0'); -INSERT INTO `npc_spells_effects_entries` VALUES ('2', '1', '168', '0', '255', '3999', '-1', '0'); -INSERT INTO `npc_spells_effects_entries` VALUES ('3', '2', '167', '0', '255', '98', '-1', '0'); - - - -SET FOREIGN_KEY_CHECKS=0; - --- ---------------------------- --- Table structure for `npc_spells_effects` --- ---------------------------- -DROP TABLE IF EXISTS `npc_spells_effects`; -CREATE TABLE `npc_spells_effects` ( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `name` tinytext, - `parent_list` int(11) unsigned NOT NULL DEFAULT '0', - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=1079 DEFAULT CHARSET=latin1; - --- ---------------------------- --- Records of npc_spells_effects --- ---------------------------- -INSERT INTO `npc_spells_effects` VALUES ('1', 'Critical', '0'); -INSERT INTO `npc_spells_effects` VALUES ('2', 'ParentTest', '1'); From cd9cf9f52f9b11d4337010e7bc3397b9d566293a Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 27 Apr 2014 04:27:02 -0400 Subject: [PATCH 5/6] sql hot fix --- utils/sql/git/required/2014_04_27_AISpellEffects.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/sql/git/required/2014_04_27_AISpellEffects.sql b/utils/sql/git/required/2014_04_27_AISpellEffects.sql index 6a5645513..171ae6956 100644 --- a/utils/sql/git/required/2014_04_27_AISpellEffects.sql +++ b/utils/sql/git/required/2014_04_27_AISpellEffects.sql @@ -59,8 +59,8 @@ CREATE TABLE `npc_spells_effects_entries` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `npc_spells_effects_id` int(11) NOT NULL DEFAULT '0', `spell_effect_id` smallint(5) NOT NULL DEFAULT '0', - `minlevel` tinyint(3) unsigned NOT NULL, - `maxlevel` tinyint(3) unsigned NOT NULL, + `minlevel` tinyint(3) NOT NULL DEFAULT '0', + `maxlevel` tinyint(3) NOT NULL DEFAULT '255', `se_base` int(11) NOT NULL DEFAULT '0', `se_limit` int(11) NOT NULL DEFAULT '0', `se_max` int(11) NOT NULL DEFAULT '0', From 649f363917c85560382ef5e4c09dc57aea79b571 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Mon, 28 Apr 2014 17:18:23 -0400 Subject: [PATCH 6/6] fix sql --- utils/sql/git/required/2014_04_27_AISpellEffects.sql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/sql/git/required/2014_04_27_AISpellEffects.sql b/utils/sql/git/required/2014_04_27_AISpellEffects.sql index 171ae6956..2ff0c49bd 100644 --- a/utils/sql/git/required/2014_04_27_AISpellEffects.sql +++ b/utils/sql/git/required/2014_04_27_AISpellEffects.sql @@ -49,6 +49,7 @@ INSERT INTO `npc_spells_effects` VALUES ('28', 'Increase Spell Vulnerability [Al INSERT INTO `npc_spells_effects` VALUES ('29', 'Decrease Spell Vulnerability [FR]', '0'); INSERT INTO `npc_spells_effects` VALUES ('30', 'Movement Speed', '0'); + SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- @@ -59,8 +60,8 @@ CREATE TABLE `npc_spells_effects_entries` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `npc_spells_effects_id` int(11) NOT NULL DEFAULT '0', `spell_effect_id` smallint(5) NOT NULL DEFAULT '0', - `minlevel` tinyint(3) NOT NULL DEFAULT '0', - `maxlevel` tinyint(3) NOT NULL DEFAULT '255', + `minlevel` tinyint(3) unsigned NOT NULL DEFAULT '0', + `maxlevel` tinyint(3) unsigned NOT NULL DEFAULT '255', `se_base` int(11) NOT NULL DEFAULT '0', `se_limit` int(11) NOT NULL DEFAULT '0', `se_max` int(11) NOT NULL DEFAULT '0', @@ -101,4 +102,3 @@ INSERT INTO `npc_spells_effects_entries` VALUES ('27', '27', '382', '0', '255', INSERT INTO `npc_spells_effects_entries` VALUES ('28', '28', '296', '0', '255', '1000', '-1', '0'); INSERT INTO `npc_spells_effects_entries` VALUES ('29', '29', '296', '0', '255', '-50', '2', '0'); INSERT INTO `npc_spells_effects_entries` VALUES ('30', '30', '3', '0', '255', '60', '0', '0'); -