2025/12/16 Update
Updated PEPS Hooked up new GUI module event. Updated classes.2da Updated baseitems.2da Updated nim tools. Full compile.
This commit is contained in:
@@ -219,13 +219,13 @@ int ai_GetHasTalent(object oCreature, int nTalent);
|
||||
// Type 4)item 0-type, 1-spell, 2-item object, 3-level, 4-slot.
|
||||
// jJsonLevel is the level to place the talent in the json array
|
||||
// maybe different then the talents actual level which is passed in nLevel.
|
||||
void ai_SaveTalent(object oCreature, int nClass, int nJsonLevel, int nLevel, int nSlot, int nSpell, int nType, int bBuff, int bDisablePreBuffs, object oItem = OBJECT_INVALID);
|
||||
void ai_SaveTalent(object oCreature, int nClass, int nJsonLevel, int nLevel, int nSlot, int nSpell, int nType, int bBuff, int bPreBuff, int bFullBuff, object oItem = OBJECT_INVALID);
|
||||
// Removes a talent nSlotIndex from jLevel in jCategory.
|
||||
void ai_RemoveTalent(object oCreature, json jCategory, json jLevel, string sCategory, int nLevel, int nSlotIndex);
|
||||
// Saves a creatures talents to variables upon them for combat use.
|
||||
// bMonster will check to see if they should be buffed when we set the talents.
|
||||
// bDisablePrebuffs - Tells the talent system
|
||||
void ai_SetCreatureTalents(object oCreature, int bMonster, int bDisablePreBuffs = FALSE);
|
||||
// bForceTalentSetup - Tells the talent system to force a talent setup but no Buffing.
|
||||
void ai_SetCreatureTalents(object oCreature, int bMonster, int bForceTalentSetup = FALSE);
|
||||
// Return TRUE if oCreature spontaneously casts a cure spell from a talent in sCategory.
|
||||
int ai_UseSpontaneousCureTalentFromCategory(object oCreature, string sCategory, int nInMelee, int nDamage, object oTarget = OBJECT_INVALID);
|
||||
// Returns TRUE if oCreature uses jTalent on oTarget.
|
||||
@@ -488,12 +488,13 @@ int ai_CheckTalentsVsConditions(object oCreature, int nConditions, int nInMelee,
|
||||
{
|
||||
nTalentUsed = ai_UseCreatureSpellTalent(oCreature, jLevel, jTalent, AI_TALENT_CURE, nInMelee, oTarget);
|
||||
// -1 means it was a memorized spell and we need to remove it.
|
||||
if(nTalentUsed == -1)
|
||||
{
|
||||
ai_RemoveTalent(oCreature, jCategory, jLevel, AI_TALENT_CURE, nLevel, nSlotIndex);
|
||||
return TRUE;
|
||||
}
|
||||
else if(nTalentUsed) return TRUE;
|
||||
//if(nTalentUsed == -1)
|
||||
//{
|
||||
// ai_RemoveTalent(oCreature, jCategory, jLevel, AI_TALENT_CURE, nLevel, nSlotIndex);
|
||||
// return TRUE;
|
||||
//}
|
||||
//else
|
||||
if(nTalentUsed) return TRUE;
|
||||
}
|
||||
}
|
||||
else if(nType == AI_TALENT_TYPE_SP_ABILITY)
|
||||
@@ -2044,10 +2045,8 @@ int ai_GetHasTalent(object oCreature, int nTalent)
|
||||
object ai_CheckTalentForBuffing(object oCreature, string sCategory, int nSpell)
|
||||
{
|
||||
// Should we buff this monster caster? Added legacy code just in case.
|
||||
if((sCategory == "P" || sCategory == "E" ||
|
||||
(sCategory == "S" && GetLocalInt(GetModule(), AI_RULE_PRESUMMON))) &&
|
||||
(GetLocalInt(GetModule(), AI_RULE_BUFF_MONSTERS) ||
|
||||
GetLocalInt(oCreature, "NW_GENERIC_MASTER") & 0x04000000)) return ai_GetBuffTarget(oCreature, nSpell);
|
||||
if(sCategory == "P" || sCategory == "E" ||
|
||||
(sCategory == "S" && GetLocalInt(GetModule(), AI_RULE_PRESUMMON))) return ai_GetBuffTarget(oCreature, nSpell);
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
int ai_UseBuffTalent(object oCreature, int nClass, int nLevel, int nSlot, int nSpell, int nType, object oTarget, object oItem)
|
||||
@@ -2127,7 +2126,7 @@ int ai_SpellRestricted(int nSpell)
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
void ai_SaveTalent(object oCreature, int nClass, int nJsonLevel, int nLevel, int nSlot, int nSpell, int nType, int bMonster, int bDisablePreBuffs, object oItem = OBJECT_INVALID)
|
||||
void ai_SaveTalent(object oCreature, int nClass, int nJsonLevel, int nLevel, int nSlot, int nSpell, int nType, int bMonster, int bPreBuff, int bFullBuff, object oItem = OBJECT_INVALID)
|
||||
{
|
||||
// Players/Admins can restrict some spells.
|
||||
if(ai_SpellRestricted(nSpell)) return;
|
||||
@@ -2136,10 +2135,10 @@ void ai_SaveTalent(object oCreature, int nClass, int nJsonLevel, int nLevel, int
|
||||
// If it is a blank talent or it is an Area of Effect talent we skip.
|
||||
if(sCategory == "" || sCategory == "A") return;
|
||||
// Check to see if we should be prebuffing.
|
||||
if(bMonster && !bDisablePreBuffs)
|
||||
if(bMonster && bPreBuff)
|
||||
{
|
||||
int nSpellBuffDuration = StringToInt(Get2DAString("ai_spells", "Buff_Duration", nSpell));
|
||||
if(nSpellBuffDuration == 3)
|
||||
if(nSpellBuffDuration == 3 || (nSpellBuffDuration == 2 && bFullBuff))
|
||||
{
|
||||
object oTarget = ai_CheckTalentForBuffing(oCreature, sCategory, nSpell);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
@@ -2213,7 +2212,81 @@ void ai_RemoveTalentLevel(object oCreature, json jCategory, json jLevel, string
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1861", "jCategory: " + JsonDump(jCategory, 2));
|
||||
SetLocalJson(oCreature, sCategory, jCategory);
|
||||
}
|
||||
void ai_SetCreatureSpellTalents(object oCreature, int bMonster, int bDisablePreBuffs)
|
||||
/*******************************************************************************
|
||||
New Set Talents by Level then category.
|
||||
*******************************************************************************/
|
||||
/*void ai_SaveTalentByLevel(object oCreature, int nClass, int nJsonLevel, int nLevel, int nSlot, int nSpell, int nType, int bMonster, int bPreBuff, int bFullBuff, object oItem = OBJECT_INVALID)
|
||||
{
|
||||
// Players/Admins can restrict some spells.
|
||||
if(ai_SpellRestricted(nSpell)) return;
|
||||
// Get the talent category, we organize all talents by categories.
|
||||
string sCategory = Get2DAString("ai_spells", "Category", nSpell);
|
||||
// If it is a blank talent or it is an Area of Effect talent we skip.
|
||||
if(sCategory == "" || sCategory == "A") return;
|
||||
// Check to see if we should be prebuffing.
|
||||
if(bMonster && bPreBuff)
|
||||
{
|
||||
int nSpellBuffDuration = StringToInt(Get2DAString("ai_spells", "Buff_Duration", nSpell));
|
||||
if(nSpellBuffDuration == 3 || (nSpellBuffDuration == 2 && bFullBuff))
|
||||
{
|
||||
object oTarget = ai_CheckTalentForBuffing(oCreature, sCategory, nSpell);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1794", GetName(oCreature) + " is prebuffing with spell " + IntToString(nSpell));
|
||||
if(ai_UseBuffTalent(oCreature, nClass, nLevel, nSlot, nSpell, nType, oTarget, oItem)) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
string sLevel = IntToString(nLevel);
|
||||
// Get the Level saved to Json.
|
||||
json jLevel = GetLocalJson(oCreature, "SPELL_LEVEL_" + sLevel);
|
||||
// If jLevel is not created we set it up.
|
||||
if(JsonGetType(jLevel) == JSON_TYPE_NULL) jLevel = JsonArray();
|
||||
json jTalent = JsonArray();
|
||||
if(nType == AI_TALENT_TYPE_SPELL || nType == AI_TALENT_TYPE_SP_ABILITY)
|
||||
{
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nType), 0);
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nSpell));
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nClass));
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nLevel));
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nSlot));
|
||||
jTalent = JsonArrayInsert(jTalent, JsonString(sCategory));
|
||||
}
|
||||
else if(nType == AI_TALENT_TYPE_ITEM)
|
||||
{
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nType), 0);
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nSpell));
|
||||
jTalent = JsonArrayInsert(jTalent, JsonString(ObjectToString(oItem)));
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nLevel));
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nSlot));
|
||||
jTalent = JsonArrayInsert(jTalent, JsonString(sCategory));
|
||||
}
|
||||
jLevel = JsonArrayInsert(jLevel, jTalent);
|
||||
SetLocalJson(oCreature, "SPELL_LEVEL_" + sLevel, jLevel);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2265", sLevel + ": " + JsonDump(jLevel, 1));
|
||||
// Set AI_MAX_TALENT if this talent is higher than the maximum.
|
||||
if(nJsonLevel > GetLocalInt(oCreature, AI_MAX_LEVEL + sLevel))
|
||||
{
|
||||
SetLocalInt(oCreature, AI_MAX_LEVEL + sLevel, nJsonLevel);
|
||||
}
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2271", "AI_MAX_LEVEL: " +
|
||||
IntToString(GetLocalInt(oCreature, AI_MAX_LEVEL + sLevel)) +
|
||||
" nJsonLevel: " + IntToString(nJsonLevel));
|
||||
}
|
||||
// For removing used up spell slots.
|
||||
void ai_RemoveTalentByLevel(object oCreature, json jLevel, int nLevel, int nSlotIndex)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2278", "removing Talent from slot: " + IntToString(nSlotIndex));
|
||||
jLevel = JsonArrayDel(jLevel, nSlotIndex);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2280", "jLevel: " + JsonDump(jLevel, 2));
|
||||
SetLocalJson(oCreature, "SPELL_LEVEL_" + IntToString(nLevel), jLevel);
|
||||
}
|
||||
// For removing Sorcerer/Bard spell levels once used up.
|
||||
void ai_RemoveTalentLevelByLevel(object oCreature, int nLevel)
|
||||
{
|
||||
DeleteLocalJson(oCreature, "SPELL_LEVEL_" + IntToString(nLevel));
|
||||
}
|
||||
void ai_SetCreatureSpellTalentsByLevel(object oCreature, int bMonster, int bPreBuff, int bFullBuff)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1417", GetName(oCreature) + ": Setting Spell Talents for combat [Buff: " +
|
||||
IntToString(bMonster) + "].");
|
||||
@@ -2265,8 +2338,8 @@ void ai_SetCreatureSpellTalents(object oCreature, int bMonster, int bDisablePreB
|
||||
nAdjLevel = nLevel + nMetaMagic;
|
||||
if(nAdjLevel > 9) nAdjLevel = 9;
|
||||
}
|
||||
else nAdjLevel = nLevel; */
|
||||
ai_SaveTalent(oCreature, nClass, nLevel, nLevel, nSlot, nSpell, AI_TALENT_TYPE_SPELL, bMonster, bDisablePreBuffs);
|
||||
else nAdjLevel = nLevel;
|
||||
ai_SaveTalentByLevel(oCreature, nClass, nLevel, nLevel, nSlot, nSpell, AI_TALENT_TYPE_SPELL, bMonster, bPreBuff, bFullBuff);
|
||||
}
|
||||
nSlot++;
|
||||
}
|
||||
@@ -2295,7 +2368,7 @@ void ai_SetCreatureSpellTalents(object oCreature, int bMonster, int bDisablePreB
|
||||
IntToString(GetSpellUsesLeft(oCreature, nClass, nSpell)));
|
||||
if(GetSpellUsesLeft(oCreature, nClass, nSpell) > 0)
|
||||
{
|
||||
ai_SaveTalent(oCreature, nClass, nLevel, nLevel, nSlot, nSpell, AI_TALENT_TYPE_SPELL, bMonster, bDisablePreBuffs);
|
||||
ai_SaveTalentByLevel(oCreature, nClass, nLevel, nLevel, nSlot, nSpell, AI_TALENT_TYPE_SPELL, bMonster, bPreBuff, bFullBuff);
|
||||
}
|
||||
nSlot++;
|
||||
}
|
||||
@@ -2307,7 +2380,7 @@ void ai_SetCreatureSpellTalents(object oCreature, int bMonster, int bDisablePreB
|
||||
nClass = GetClassByPosition(nClassPosition, oCreature);
|
||||
}
|
||||
}
|
||||
void ai_SetCreatureSpecialAbilityTalents(object oCreature, int bMonster, int bDisablePreBuffs)
|
||||
void ai_SetCreatureSpecialAbilityTalentsByLevel(object oCreature, int bMonster, int bPreBuff, int bFullBuff)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1488", GetName(oCreature) + ": Setting Special Ability Talents for combat.");
|
||||
// Cycle through all the creatures special abilities.
|
||||
@@ -2322,13 +2395,13 @@ void ai_SetCreatureSpecialAbilityTalents(object oCreature, int bMonster, int bDi
|
||||
if(GetSpellAbilityReady(oCreature, nSpell))
|
||||
{
|
||||
nLevel = StringToInt(Get2DAString("spells", "Innate", nSpell));
|
||||
ai_SaveTalent(oCreature, 255, nLevel, nLevel, nIndex, nSpell, AI_TALENT_TYPE_SP_ABILITY, bMonster, bDisablePreBuffs);
|
||||
ai_SaveTalentByLevel(oCreature, 255, nLevel, nLevel, nIndex, nSpell, AI_TALENT_TYPE_SP_ABILITY, bMonster, bPreBuff, bFullBuff);
|
||||
}
|
||||
nIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
void ai_CheckItemProperties(object oCreature, object oItem, int bMonster, int bDisablePreBuffs, int bEquiped = FALSE)
|
||||
void ai_CheckItemPropertiesByLevel(object oCreature, object oItem, int bMonster, int bPreBuff, int bFullBuff, int bEquiped = FALSE)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1509", "Checking Item properties on " + GetName(oItem));
|
||||
// We have established that we can use the item if it is equiped.
|
||||
@@ -2374,7 +2447,7 @@ void ai_CheckItemProperties(object oCreature, object oItem, int bMonster, int bD
|
||||
nIprpSubType = GetItemPropertySubType(ipProp);
|
||||
nSpell = StringToInt(Get2DAString("iprp_spells", "SpellIndex", nIprpSubType));
|
||||
nLevel = StringToInt(Get2DAString("iprp_spells", "InnateLvl", nIprpSubType));
|
||||
ai_SaveTalent(oCreature, 255, nLevel, nLevel, nIndex, nSpell, AI_TALENT_TYPE_ITEM, bMonster, bDisablePreBuffs, oItem);
|
||||
ai_SaveTalentByLevel(oCreature, 255, nLevel, nLevel, nIndex, nSpell, AI_TALENT_TYPE_ITEM, bMonster, bPreBuff, bFullBuff, oItem);
|
||||
}
|
||||
}
|
||||
else if(nIPType == ITEM_PROPERTY_HEALERS_KIT)
|
||||
@@ -2385,7 +2458,7 @@ void ai_CheckItemProperties(object oCreature, object oItem, int bMonster, int bD
|
||||
// Must also have ranks in healing kits.
|
||||
if(GetSkillRank(SKILL_HEAL, oCreature) > 0)
|
||||
{
|
||||
ai_SaveTalent(oCreature, 255, 7, 0, nIndex, nSpell, AI_TALENT_TYPE_ITEM, bMonster, bDisablePreBuffs, oItem);
|
||||
ai_SaveTalent(oCreature, 255, 7, 0, nIndex, nSpell, AI_TALENT_TYPE_ITEM, bMonster, bPreBuff, bFullBuff, oItem);
|
||||
}
|
||||
}
|
||||
if(bEquiped)
|
||||
@@ -2449,7 +2522,7 @@ void ai_CheckItemProperties(object oCreature, object oItem, int bMonster, int bD
|
||||
// If any Immunity has been set then we need to save our Immunity json.
|
||||
if(bHasItemImmunity) SetLocalJson(oCreature, AI_TALENT_IMMUNITY, jImmunity);
|
||||
}
|
||||
void ai_SetCreatureItemTalents(object oCreature, int bMonster, int bDisablePreBuffs)
|
||||
void ai_SetCreatureItemTalentsByLevel(object oCreature, int bMonster, int bPreBuff, int bFullBuff)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1561", GetName(oCreature) + ": Setting Item Talents for combat.");
|
||||
int bEquiped;
|
||||
@@ -2465,7 +2538,7 @@ void ai_SetCreatureItemTalents(object oCreature, int bMonster, int bDisablePreBu
|
||||
// Does the item need to be equiped to use its powers?
|
||||
sSlots = Get2DAString("baseitems", "EquipableSlots", GetBaseItemType(oItem));
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1572", GetName(oItem) + " requires " + Get2DAString("baseitems", "EquipableSlots", GetBaseItemType(oItem)) + " slots.");
|
||||
if(sSlots == "0x00000") ai_CheckItemProperties(oCreature, oItem, bMonster, bDisablePreBuffs);
|
||||
if(sSlots == "0x00000") ai_CheckItemPropertiesByLevel(oCreature, oItem, bMonster, bPreBuff, bFullBuff);
|
||||
}
|
||||
oItem = GetNextItemInInventory(oCreature);
|
||||
}
|
||||
@@ -2474,29 +2547,331 @@ void ai_SetCreatureItemTalents(object oCreature, int bMonster, int bDisablePreBu
|
||||
oItem = GetItemInSlot(nSlot, oCreature);
|
||||
while(nSlot < 11)
|
||||
{
|
||||
if(oItem != OBJECT_INVALID) ai_CheckItemProperties(oCreature, oItem, bMonster, TRUE);
|
||||
if(oItem != OBJECT_INVALID) ai_CheckItemPropertiesByLevel(oCreature, oItem, bMonster, bPreBuff, bFullBuff, TRUE);
|
||||
oItem = GetItemInSlot(++nSlot, oCreature);
|
||||
}
|
||||
oItem = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oCreature);
|
||||
if(oItem != OBJECT_INVALID) ai_CheckItemProperties(oCreature, oItem, bMonster, TRUE);
|
||||
if(oItem != OBJECT_INVALID) ai_CheckItemPropertiesByLevel(oCreature, oItem, bMonster, bPreBuff, bFullBuff, TRUE);
|
||||
}
|
||||
void ai_SetCreatureTalents(object oCreature, int bMonster, int bDisablePreBuffs = FALSE)
|
||||
void ai_SetCreatureTalentsByLevel(object oCreature, int bMonster, int bForceTalentSetup = FALSE)
|
||||
{
|
||||
//json jCreature = ObjectToJson(oCreature);
|
||||
//if(AI_DEBUG) ai_Debug("0i_talents", "2072", GetName(oCreature) + " jCreature: " + JsonDump(jCreature, 4));
|
||||
if(GetLocalInt(oCreature, AI_TALENTS_SET) && !bDisablePreBuffs) return;
|
||||
if(GetLocalInt(oCreature, AI_TALENTS_SET) && !bForceTalentSetup) return;
|
||||
SetLocalInt(oCreature, AI_TALENTS_SET, TRUE);
|
||||
object oModule = GetModule();
|
||||
int bPreBuff = GetLocalInt(GetModule(), AI_RULE_BUFF_MONSTERS) || (GetLocalInt(oCreature, "NW_GENERIC_MASTER") & 0x04000000);
|
||||
int bFullBuff = GetLocalInt(GetModule(), AI_RULE_FULL_BUFF_MONSTERS);
|
||||
if(bForceTalentSetup) bPreBuff = FALSE;
|
||||
ai_Counter_Start();
|
||||
ai_SetCreatureSpellTalents(oCreature, bMonster, bDisablePreBuffs);
|
||||
ai_SetCreatureSpellTalentsByLevel(oCreature, bMonster, bPreBuff, bFullBuff);
|
||||
ai_Counter_End(GetName(oCreature) + ": Spell Talents");
|
||||
ai_SetCreatureSpecialAbilityTalents(oCreature, bMonster, bDisablePreBuffs);
|
||||
ai_SetCreatureSpecialAbilityTalentsByLevel(oCreature, bMonster, bPreBuff, bFullBuff);
|
||||
ai_Counter_End(GetName(oCreature) + ": Special Ability Talents");
|
||||
DeleteLocalJson(oCreature, AI_TALENT_IMMUNITY);
|
||||
ai_SetCreatureItemTalents(oCreature, bMonster, bDisablePreBuffs);
|
||||
ai_SetCreatureItemTalentsByLevel(oCreature, bMonster, bPreBuff, bFullBuff);
|
||||
ai_Counter_End(GetName(oCreature) + ": Item Talents");
|
||||
if(GetLocalInt(oModule, AI_RULE_SUMMON_COMPANIONS) &&
|
||||
GetLocalInt(oModule, AI_RULE_PRESUMMON) && bMonster && !bDisablePreBuffs)
|
||||
GetLocalInt(oModule, AI_RULE_PRESUMMON) && bMonster && bPreBuff)
|
||||
{
|
||||
ai_TrySummonFamiliarTalent(oCreature);
|
||||
ai_TrySummonAnimalCompanionTalent(oCreature);
|
||||
}
|
||||
// AI_CAT_CURE is setup differently we save the level as the highest.
|
||||
//if(JsonGetType(GetLocalJson(oCreature, AI_TALENT_CURE)) != JSON_TYPE_NULL) SetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_CURE, 9);
|
||||
// With spontaneous cure spells we need to clear this as the number of spells don't count.
|
||||
//if(GetLevelByClass(CLASS_TYPE_CLERIC, oCreature)) SetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_HEALING, 0);
|
||||
} */
|
||||
/*******************************************************************************
|
||||
Old Set talents by category then level.
|
||||
*******************************************************************************/
|
||||
void ai_SetCreatureSpellTalents(object oCreature, int bMonster, int bPreBuff, int bFullBuff)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1417", GetName(oCreature) + ": Setting Spell Talents for combat [Buff: " +
|
||||
IntToString(bMonster) + "].");
|
||||
// Cycle through all classes and spells.
|
||||
int nClassPosition = 1, nMaxSlot, nLevel, nSlot, nSpell, nIndex, nMetaMagic;
|
||||
int nClass = GetClassByPosition(nClassPosition, oCreature);
|
||||
while(nClassPosition <= AI_MAX_CLASSES_PER_CHARACTER && nClass != CLASS_TYPE_INVALID)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1824", "nClass: " + IntToString(nClass) +
|
||||
" nClassPosition: " + IntToString(nClassPosition) +
|
||||
" SpellCaster: " + Get2DAString("classes", "SpellCaster", nClass) +
|
||||
" Memorized: " + Get2DAString("classes", "MemorizesSpells", nClass));
|
||||
if(Get2DAString("classes", "SpellCaster", nClass) == "1")
|
||||
{
|
||||
// Search all memorized spells for the spell.
|
||||
if(Get2DAString("classes", "MemorizesSpells", nClass) == "1")
|
||||
{
|
||||
// Check each level organizing from highest to lowest.
|
||||
nLevel = (GetLevelByPosition(nClassPosition, oCreature) + 1) / 2;
|
||||
if(nLevel > 9) nLevel = 9;
|
||||
while(nLevel > -1)
|
||||
{
|
||||
// Check each slot within each level.
|
||||
nMaxSlot = GetMemorizedSpellCountByLevel(oCreature, nClass, nLevel);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1434", "nClass: " + IntToString(nClass) +
|
||||
" nLevel: " + IntToString(nLevel) + " nMaxSlot: " +
|
||||
IntToString(nMaxSlot));
|
||||
nSlot = 0;
|
||||
while(nSlot < nMaxSlot)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1440", "nSlot: " + IntToString(nSlot) + " nSpell: " +
|
||||
IntToString(GetMemorizedSpellId(oCreature, nClass, nLevel, nSlot)) + " spell memorized: " +
|
||||
IntToString(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlot)));
|
||||
if(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlot) == 1)
|
||||
{
|
||||
nSpell = GetMemorizedSpellId(oCreature, nClass, nLevel, nSlot);
|
||||
/* Spells are already at the higher level when saved as a talent.
|
||||
// Move a spell up to a different JsonLevel as higher Jsonlevel
|
||||
// spells usually get cast first.
|
||||
nMetaMagic = GetMemorizedSpellMetaMagic(oCreature, nClass, nLevel, nSlot);
|
||||
if(nMetaMagic > 0)
|
||||
{
|
||||
if(nMetaMagic == METAMAGIC_STILL) nMetaMagic = 1;
|
||||
else if(nMetaMagic == METAMAGIC_EXTEND) nMetaMagic = 1;
|
||||
else if(nMetaMagic == METAMAGIC_SILENT) nMetaMagic = 1;
|
||||
else if(nMetaMagic == METAMAGIC_EMPOWER) nMetaMagic = 2;
|
||||
else if(nMetaMagic == METAMAGIC_MAXIMIZE) nMetaMagic = 3;
|
||||
else if(nMetaMagic == METAMAGIC_QUICKEN) nMetaMagic = 4;
|
||||
nAdjLevel = nLevel + nMetaMagic;
|
||||
if(nAdjLevel > 9) nAdjLevel = 9;
|
||||
}
|
||||
else nAdjLevel = nLevel; */
|
||||
ai_SaveTalent(oCreature, nClass, nLevel, nLevel, nSlot, nSpell, AI_TALENT_TYPE_SPELL, bMonster, bPreBuff, bFullBuff);
|
||||
}
|
||||
nSlot++;
|
||||
}
|
||||
nLevel--;
|
||||
}
|
||||
}
|
||||
// Check non-memorized known lists for the spell.
|
||||
else
|
||||
{
|
||||
// Check each level starting with the highest to lowest.
|
||||
nLevel = (GetLevelByPosition(nClassPosition, oCreature) + 1) / 2;
|
||||
if(nLevel > 9) nLevel = 9;
|
||||
while(nLevel > -1)
|
||||
{
|
||||
// Check each slot within each level.
|
||||
nMaxSlot = GetKnownSpellCount(oCreature, nClass, nLevel);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1462", "nClass: " + IntToString(nClass) +
|
||||
" nLevel: " + IntToString(nLevel) + " nMaxSlot: " +
|
||||
IntToString(nMaxSlot));
|
||||
nSlot = 0;
|
||||
while(nSlot < nMaxSlot)
|
||||
{
|
||||
nSpell = GetKnownSpellId(oCreature, nClass, nLevel, nSlot);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1469", "nSlot: " + IntToString(nSlot) +
|
||||
" nSpell: " + IntToString(nSpell) + " nUsesLeft: " +
|
||||
IntToString(GetSpellUsesLeft(oCreature, nClass, nSpell)));
|
||||
if(GetSpellUsesLeft(oCreature, nClass, nSpell) > 0)
|
||||
{
|
||||
ai_SaveTalent(oCreature, nClass, nLevel, nLevel, nSlot, nSpell, AI_TALENT_TYPE_SPELL, bMonster, bPreBuff, bFullBuff);
|
||||
}
|
||||
nSlot++;
|
||||
}
|
||||
nLevel--;
|
||||
}
|
||||
}
|
||||
}
|
||||
nClassPosition++;
|
||||
nClass = GetClassByPosition(nClassPosition, oCreature);
|
||||
}
|
||||
}
|
||||
void ai_SetCreatureSpecialAbilityTalents(object oCreature, int bMonster, int bPreBuff, int bFullBuff)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1488", GetName(oCreature) + ": Setting Special Ability Talents for combat.");
|
||||
// Cycle through all the creatures special abilities.
|
||||
int nMaxSpecialAbilities = GetSpellAbilityCount(oCreature);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1491", IntToString(nMaxSpecialAbilities) + " Spell abilities.");
|
||||
if(nMaxSpecialAbilities)
|
||||
{
|
||||
int nIndex, nSpell, nLevel;
|
||||
while(nIndex < nMaxSpecialAbilities)
|
||||
{
|
||||
nSpell = GetSpellAbilitySpell(oCreature, nIndex);
|
||||
if(GetSpellAbilityReady(oCreature, nSpell))
|
||||
{
|
||||
nLevel = StringToInt(Get2DAString("spells", "Innate", nSpell));
|
||||
ai_SaveTalent(oCreature, 255, nLevel, nLevel, nIndex, nSpell, AI_TALENT_TYPE_SP_ABILITY, bMonster, bPreBuff, bFullBuff);
|
||||
}
|
||||
nIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
void ai_CheckItemProperties(object oCreature, object oItem, int bMonster, int bPreBuff, int bFullBuff, int bEquiped = FALSE)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1509", "Checking Item properties on " + GetName(oItem));
|
||||
// We have established that we can use the item if it is equiped.
|
||||
if(!bEquiped && !ai_CheckIfCanUseItem(oCreature, oItem)) return;
|
||||
// Get or create an Immunity in json so we can check item immunities quickly.
|
||||
int nSpellImmunity, bHasItemImmunity, nPerDay, nCharges, nUses, bSaveTalent;
|
||||
json jImmunity = GetLocalJson(oCreature, AI_TALENT_IMMUNITY);
|
||||
if(JsonGetType(jImmunity) == JSON_TYPE_NULL) jImmunity = JsonArray();
|
||||
int nIprpSubType, nSpell, nLevel, nIPType, nIndex;
|
||||
itemproperty ipProp = GetFirstItemProperty(oItem);
|
||||
// Lets skip this if there are no properties.
|
||||
if(!GetIsItemPropertyValid(ipProp)) return;
|
||||
// Check for cast spell property and add them to the talent list.
|
||||
while(GetIsItemPropertyValid(ipProp))
|
||||
{
|
||||
nIPType = GetItemPropertyType(ipProp);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1895", "ItempropertyType(15/80/53): " + IntToString(nIPType));
|
||||
if(nIPType == ITEM_PROPERTY_CAST_SPELL)
|
||||
{
|
||||
bSaveTalent = TRUE;
|
||||
// Get how they use the item (charges or uses per day).
|
||||
nUses = GetItemPropertyCostTableValue(ipProp);
|
||||
if(nUses > 1 && nUses < 7)
|
||||
{
|
||||
nCharges = GetItemCharges(oItem);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1530", "Charges per use: " + IntToString(nUses) +
|
||||
" Item charges: " + IntToString(nCharges));
|
||||
if((nUses == IP_CONST_CASTSPELL_NUMUSES_1_CHARGE_PER_USE && nCharges < 1) ||
|
||||
(nUses == IP_CONST_CASTSPELL_NUMUSES_2_CHARGES_PER_USE && nCharges < 2) ||
|
||||
(nUses == IP_CONST_CASTSPELL_NUMUSES_3_CHARGES_PER_USE && nCharges < 3) ||
|
||||
(nUses == IP_CONST_CASTSPELL_NUMUSES_4_CHARGES_PER_USE && nCharges < 4) ||
|
||||
(nUses == IP_CONST_CASTSPELL_NUMUSES_5_CHARGES_PER_USE && nCharges < 5)) bSaveTalent = FALSE;
|
||||
}
|
||||
else if(nUses > 7 && nUses < 13)
|
||||
{
|
||||
nPerDay = GetItemPropertyUsesPerDayRemaining(oItem, ipProp);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1676", "Item uses: " + IntToString(nPerDay));
|
||||
if(nPerDay == 0) bSaveTalent = FALSE;
|
||||
}
|
||||
if(bSaveTalent)
|
||||
{
|
||||
// SubType is the ip spell index for iprp_spells.2da
|
||||
nIprpSubType = GetItemPropertySubType(ipProp);
|
||||
nSpell = StringToInt(Get2DAString("iprp_spells", "SpellIndex", nIprpSubType));
|
||||
nLevel = StringToInt(Get2DAString("iprp_spells", "InnateLvl", nIprpSubType));
|
||||
ai_SaveTalent(oCreature, 255, nLevel, nLevel, nIndex, nSpell, AI_TALENT_TYPE_ITEM, bMonster, bPreBuff, bFullBuff, oItem);
|
||||
}
|
||||
}
|
||||
else if(nIPType == ITEM_PROPERTY_HEALERS_KIT)
|
||||
{
|
||||
// Lets set Healing kits as Cure Light Wounds since they heal 1d20 in combat.
|
||||
nSpell = SPELL_CURE_MINOR_WOUNDS;
|
||||
// Save the healer kit as level 9 so we can use them first.
|
||||
// Must also have ranks in healing kits.
|
||||
if(GetSkillRank(SKILL_HEAL, oCreature) > 0)
|
||||
{
|
||||
ai_SaveTalent(oCreature, 255, 7, 0, nIndex, nSpell, AI_TALENT_TYPE_ITEM, bMonster, bPreBuff, bFullBuff, oItem);
|
||||
}
|
||||
}
|
||||
if(bEquiped)
|
||||
{
|
||||
if(nIPType == ITEM_PROPERTY_IMMUNITY_SPECIFIC_SPELL)
|
||||
{
|
||||
bHasItemImmunity = TRUE;
|
||||
nSpellImmunity = GetItemPropertyCostTableValue(ipProp);
|
||||
nSpellImmunity = StringToInt(Get2DAString("iprp_spellcost", "SpellIndex", nSpellImmunity));
|
||||
//if(AI_DEBUG) ai_Debug("0i_talents", "1950", "SpellImmunity to " + Get2DAString("spells", "Label", nSpellImmunity));
|
||||
jImmunity = JsonArrayInsert(jImmunity, JsonInt(nSpellImmunity));
|
||||
}
|
||||
else if(nIPType == ITEM_PROPERTY_HASTE)
|
||||
{
|
||||
SetLocalInt(oCreature, sIPHasHasteVarname, TRUE);
|
||||
}
|
||||
else if(nIPType == ITEM_PROPERTY_IMMUNITY_DAMAGE_TYPE)
|
||||
{
|
||||
int nBit, nIpSubType = GetItemPropertySubType(ipProp);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1957", "nIPSubType: " + IntToString(nIpSubType));
|
||||
if(nIpSubType == 0) nBit = DAMAGE_TYPE_BLUDGEONING;
|
||||
else if(nIpSubType == 1) nBit = DAMAGE_TYPE_PIERCING;
|
||||
else if(nIpSubType == 2) nBit = DAMAGE_TYPE_SLASHING;
|
||||
else if(nIpSubType == 5) nBit = DAMAGE_TYPE_MAGICAL;
|
||||
else if(nIpSubType == 6) nBit = DAMAGE_TYPE_ACID;
|
||||
else if(nIpSubType == 7) nBit = DAMAGE_TYPE_COLD;
|
||||
else if(nIpSubType == 8) nBit = DAMAGE_TYPE_DIVINE;
|
||||
else if(nIpSubType == 9) nBit = DAMAGE_TYPE_ELECTRICAL;
|
||||
else if(nIpSubType == 10) nBit = DAMAGE_TYPE_FIRE;
|
||||
else if(nIpSubType == 11) nBit = DAMAGE_TYPE_NEGATIVE;
|
||||
else if(nIpSubType == 12) nBit = DAMAGE_TYPE_POSITIVE;
|
||||
else if(nIpSubType == 13) nBit = DAMAGE_TYPE_SONIC;
|
||||
if(nBit > 0) ai_SetItemProperty(oCreature, sIPImmuneVarname, nBit, TRUE);
|
||||
}
|
||||
else if(nIPType == ITEM_PROPERTY_DAMAGE_RESISTANCE)
|
||||
{
|
||||
int nBit, nIpSubType = GetItemPropertySubType(ipProp);
|
||||
if(nIpSubType == 0) nBit = DAMAGE_TYPE_BLUDGEONING;
|
||||
else if(nIpSubType == 1) nBit = DAMAGE_TYPE_PIERCING;
|
||||
else if(nIpSubType == 2) nBit = DAMAGE_TYPE_SLASHING;
|
||||
else if(nIpSubType == 5) nBit = DAMAGE_TYPE_MAGICAL;
|
||||
else if(nIpSubType == 6) nBit = DAMAGE_TYPE_ACID;
|
||||
else if(nIpSubType == 7) nBit = DAMAGE_TYPE_COLD;
|
||||
else if(nIpSubType == 8) nBit = DAMAGE_TYPE_DIVINE;
|
||||
else if(nIpSubType == 9) nBit = DAMAGE_TYPE_ELECTRICAL;
|
||||
else if(nIpSubType == 10) nBit = DAMAGE_TYPE_FIRE;
|
||||
else if(nIpSubType == 11) nBit = DAMAGE_TYPE_NEGATIVE;
|
||||
else if(nIpSubType == 12) nBit = DAMAGE_TYPE_POSITIVE;
|
||||
else if(nIpSubType == 13) nBit = DAMAGE_TYPE_SONIC;
|
||||
if(nBit > 0) ai_SetItemProperty(oCreature, sIPResistVarname, nBit, TRUE);
|
||||
}
|
||||
else if(nIPType == ITEM_PROPERTY_DAMAGE_REDUCTION)
|
||||
{
|
||||
int nIpSubType = GetItemPropertySubType(ipProp);
|
||||
SetLocalInt(oCreature, sIPReducedVarname, nIpSubType);
|
||||
}
|
||||
}
|
||||
nIndex++;
|
||||
ipProp = GetNextItemProperty(oItem);
|
||||
}
|
||||
// If any Immunity has been set then we need to save our Immunity json.
|
||||
if(bHasItemImmunity) SetLocalJson(oCreature, AI_TALENT_IMMUNITY, jImmunity);
|
||||
}
|
||||
void ai_SetCreatureItemTalents(object oCreature, int bMonster, int bPreBuff, int bFullBuff)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1561", GetName(oCreature) + ": Setting Item Talents for combat.");
|
||||
int bEquiped;
|
||||
// Set the Immunities to -1 so we know they were set incase there are no immunities.
|
||||
SetLocalInt(oCreature, sIPReducedVarname, -1);
|
||||
string sSlots;
|
||||
// Cycle through all the creatures inventory items.
|
||||
object oItem = GetFirstItemInInventory(oCreature);
|
||||
while(oItem != OBJECT_INVALID)
|
||||
{
|
||||
if(GetIdentified(oItem))
|
||||
{
|
||||
// Does the item need to be equiped to use its powers?
|
||||
sSlots = Get2DAString("baseitems", "EquipableSlots", GetBaseItemType(oItem));
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1572", GetName(oItem) + " requires " + Get2DAString("baseitems", "EquipableSlots", GetBaseItemType(oItem)) + " slots.");
|
||||
if(sSlots == "0x00000") ai_CheckItemProperties(oCreature, oItem, bMonster, bPreBuff, bFullBuff);
|
||||
}
|
||||
oItem = GetNextItemInInventory(oCreature);
|
||||
}
|
||||
int nSlot;
|
||||
// Cycle through all the creatures equiped items.
|
||||
oItem = GetItemInSlot(nSlot, oCreature);
|
||||
while(nSlot < 11)
|
||||
{
|
||||
if(oItem != OBJECT_INVALID) ai_CheckItemProperties(oCreature, oItem, bMonster, bPreBuff, bFullBuff, TRUE);
|
||||
oItem = GetItemInSlot(++nSlot, oCreature);
|
||||
}
|
||||
oItem = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oCreature);
|
||||
if(oItem != OBJECT_INVALID) ai_CheckItemProperties(oCreature, oItem, bMonster, bPreBuff, bFullBuff, TRUE);
|
||||
}
|
||||
void ai_SetCreatureTalents(object oCreature, int bMonster, int bForceTalentSetup = FALSE)
|
||||
{
|
||||
//json jCreature = ObjectToJson(oCreature);
|
||||
//if(AI_DEBUG) ai_Debug("0i_talents", "2072", GetName(oCreature) + " jCreature: " + JsonDump(jCreature, 4));
|
||||
if(GetLocalInt(oCreature, AI_TALENTS_SET) && !bForceTalentSetup) return;
|
||||
SetLocalInt(oCreature, AI_TALENTS_SET, TRUE);
|
||||
object oModule = GetModule();
|
||||
int bPreBuff = GetLocalInt(GetModule(), AI_RULE_BUFF_MONSTERS) || (GetLocalInt(oCreature, "NW_GENERIC_MASTER") & 0x04000000);
|
||||
int bFullBuff = GetLocalInt(GetModule(), AI_RULE_FULL_BUFF_MONSTERS);
|
||||
if(bForceTalentSetup) bPreBuff = FALSE;
|
||||
ai_Counter_Start();
|
||||
ai_SetCreatureSpellTalents(oCreature, bMonster, bPreBuff, bFullBuff);
|
||||
ai_Counter_End(GetName(oCreature) + ": Spell Talents");
|
||||
ai_SetCreatureSpecialAbilityTalents(oCreature, bMonster, bPreBuff, bFullBuff);
|
||||
ai_Counter_End(GetName(oCreature) + ": Special Ability Talents");
|
||||
DeleteLocalJson(oCreature, AI_TALENT_IMMUNITY);
|
||||
ai_SetCreatureItemTalents(oCreature, bMonster, bPreBuff, bFullBuff);
|
||||
ai_Counter_End(GetName(oCreature) + ": Item Talents");
|
||||
if(GetLocalInt(oModule, AI_RULE_SUMMON_COMPANIONS) &&
|
||||
GetLocalInt(oModule, AI_RULE_PRESUMMON) && bMonster && bPreBuff)
|
||||
{
|
||||
ai_TrySummonFamiliarTalent(oCreature);
|
||||
ai_TrySummonAnimalCompanionTalent(oCreature);
|
||||
@@ -2622,20 +2997,6 @@ int ai_UseCreatureSpellTalent(object oCreature, json jLevel, json jTalent, strin
|
||||
}
|
||||
}
|
||||
if(ai_ArcaneSpellFailureTooHigh(oCreature, nClass, nLevel, nSlot)) return FALSE;
|
||||
if(Get2DAString("classes", "MemorizesSpells", nClass) == "1")
|
||||
{
|
||||
// Shouldn't need this anymore, we need to do a debug looking at this.
|
||||
if(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlot) < 1) return FALSE;
|
||||
if(ai_CheckSpecialTalentsandUse(oCreature, jTalent, sCategory, nInMelee, oTarget))
|
||||
{
|
||||
if(ai_CompareLastAction(oCreature, AI_LAST_ACTION_CAST_SPELL)) return -1;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1629", "Known caster Level: " + IntToString(nLevel) +
|
||||
" Uses : " + IntToString(GetSpellUsesLeft(oCreature, nClass, JsonGetInt(JsonArrayGet(jTalent, 1)))));
|
||||
if(!GetSpellUsesLeft(oCreature, nClass, JsonGetInt(JsonArrayGet(jTalent, 1)))) return -2;
|
||||
return ai_CheckSpecialTalentsandUse(oCreature, jTalent, sCategory, nInMelee, oTarget);
|
||||
}
|
||||
int ai_UseCreatureItemTalent(object oCreature, json jLevel, json jTalent, string sCategory, int nInMelee, object oTarget = OBJECT_INVALID)
|
||||
@@ -2691,6 +3052,178 @@ void ai_UpdateMaxTalentLevel(object oCreature, json jCategory, string sCategory,
|
||||
SetLocalInt(oCreature, AI_MAX_TALENT + sCategory, nLevel);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
New talent system that checks by level then category.
|
||||
*******************************************************************************/
|
||||
/*int ai_UseCreatureTalentByLevel(object oCreature, int nInMelee, int nLevel = 10, object oTarget = OBJECT_INVALID)
|
||||
{
|
||||
string sLevel = IntToString(nLevel);
|
||||
// Get the Max Talent Level to see if we even need to pull this talent.
|
||||
int nMaxTalentLevel = GetLocalInt(oCreature, AI_MAX_LEVEL + sLevel);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2394", AI_MAX_LEVEL + sLevel + ": " +
|
||||
IntToString(nMaxTalentLevel) +
|
||||
" nLevel: " + IntToString(nLevel));
|
||||
if(nMaxTalentLevel == -1) return FALSE;
|
||||
// If there are no talents at higher levels then start at the lowest talent level.
|
||||
if(nMaxTalentLevel < nLevel) nLevel = nMaxTalentLevel;
|
||||
if(nLevel < 0 || nLevel > 10) nLevel = 9;
|
||||
json jTalent;
|
||||
int bHasTalent, nClass, nSlot, nType, nSlotIndex, nMaxSlotIndex, nTalentUsed, nSpell;
|
||||
int bUseMagic = !ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC);
|
||||
int bUseMagicItems = !ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC_ITEMS);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2413", "bUseMagic: " + IntToString(bUseMagic) +
|
||||
" bUseMagicItems: " + IntToString(bUseMagicItems));
|
||||
// Loop through nLevels starting at the highest then going to the lowest.
|
||||
// (i.e. the highest or best is our assumption).
|
||||
// Get the saved level from oCreature.
|
||||
json jLevel = GetLocalJson(oCreature, "SPELL_LEVEL_" + IntToString(nLevel));
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "3091", "jLevel: " + IntToString(nLevel) + " " + JsonDump(jLevel, 2));
|
||||
if(JsonGetType(jCategory) == JSON_TYPE_NULL)
|
||||
{
|
||||
SetLocalInt(oCreature, AI_MAX_LEVEL + sCategory, -1);
|
||||
return FALSE;
|
||||
}
|
||||
while(nLevel > -1)
|
||||
{
|
||||
// Get the array of nLevel cycling down to 0.
|
||||
jLevel = JsonArrayGet(jCategory, nLevel);
|
||||
nMaxSlotIndex = JsonGetLength(jLevel);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2422", "Level: " + IntToString(nLevel) +
|
||||
" nMaxSlotIndex: " + IntToString(nMaxSlotIndex));
|
||||
if(nMaxSlotIndex > 0)
|
||||
{
|
||||
bHasTalent = TRUE;
|
||||
// Get the talent within nLevel cycling from the first to the last.
|
||||
nSlotIndex = 0;
|
||||
while (nSlotIndex < nMaxSlotIndex)
|
||||
{
|
||||
jTalent= JsonArrayGet(jLevel, nSlotIndex);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2432", "nSlotIndex: " + IntToString(nSlotIndex) +
|
||||
" jTalent Type: " + IntToString(JsonGetInt(JsonArrayGet(jTalent, 0))));
|
||||
nType = JsonGetInt(JsonArrayGet(jTalent, 0));
|
||||
if(bUseMagic)
|
||||
{
|
||||
if(nType == AI_TALENT_TYPE_SPELL)
|
||||
{
|
||||
nTalentUsed = ai_UseCreatureSpellTalent(oCreature, jLevel, jTalent, sCategory, nInMelee, oTarget);
|
||||
// -1 means it was a memorized spell and we need to remove it.
|
||||
if(nTalentUsed == -1)
|
||||
{
|
||||
ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex);
|
||||
if(nMaxSlotIndex == 1) ai_UpdateMaxTalentLevel(oCreature, jCategory, sCategory, nMaxTalentLevel, nLevel);
|
||||
return TRUE;
|
||||
}
|
||||
// There are no more spell slots left for non-memorizing caster so remove the level.
|
||||
else if(nTalentUsed == -2)
|
||||
{
|
||||
ai_RemoveTalentLevel(oCreature, jCategory, jLevel, sCategory, nLevel);
|
||||
if(nMaxSlotIndex == 1) ai_UpdateMaxTalentLevel(oCreature, jCategory, sCategory, nMaxTalentLevel, nLevel);
|
||||
}
|
||||
else if(nTalentUsed) return TRUE;
|
||||
}
|
||||
else if(nType == AI_TALENT_TYPE_SP_ABILITY)
|
||||
{
|
||||
// Special ability spells do not need to concentrate?!
|
||||
if(ai_CheckSpecialTalentsandUse(oCreature, jTalent, sCategory, nInMelee, oTarget))
|
||||
{
|
||||
// When the ability is used that slot is now not readied.
|
||||
// Multiple uses of the same spell are stored in different slots.
|
||||
ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex);
|
||||
if(nMaxSlotIndex == 1) ai_UpdateMaxTalentLevel(oCreature, jCategory, sCategory, nMaxTalentLevel, nLevel);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bUseMagicItems && nType == AI_TALENT_TYPE_ITEM)
|
||||
{
|
||||
// Items do not need to concentrate.
|
||||
if(ai_UseCreatureItemTalent(oCreature, jLevel, jTalent, sCategory, nInMelee, oTarget))
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2473", "Checking if Item is used up: " +
|
||||
IntToString(JsonGetInt(JsonArrayGet(jTalent, 4))));
|
||||
if(JsonGetInt(JsonArrayGet(jTalent, 4)) == -1)
|
||||
{
|
||||
ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex);
|
||||
if(nMaxSlotIndex == 1) ai_UpdateMaxTalentLevel(oCreature, jCategory, sCategory, nMaxTalentLevel, nLevel);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
//else if(nType == AI_TALENT_TYPE_FEAT) {}
|
||||
nSlotIndex++;
|
||||
}
|
||||
}
|
||||
else if(!bHasTalent) SetLocalInt(oCreature, AI_MAX_LEVEL + sCategory, nLevel - 1);
|
||||
nLevel--;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
int ai_UseTalentByLevel(object oCreature, int nTalent, object oTarget)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1912", GetName(oCreature) + " is trying to use " + GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nTalent))) +
|
||||
" on " + GetName(oTarget));
|
||||
// Get the saved category from oCreature.
|
||||
string sCategory = Get2DAString("ai_spells", "Category", nTalent);
|
||||
json jCategory = GetLocalJson(oCreature, sCategory);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1917", "jCategory: " + sCategory + " " + JsonDump(jCategory, 2));
|
||||
if(JsonGetType(jCategory) == JSON_TYPE_NULL) return FALSE;
|
||||
json jLevel, jTalent;
|
||||
int nLevel, nClass, nSlot, nType, nSlotIndex, nMaxSlotIndex, nTalentUsed, nSpell;
|
||||
// Loop through nLevels down to nMinNoTalentLevel looking for the first talent
|
||||
// (i.e. the highest or best?).
|
||||
while(nLevel <= 9)
|
||||
{
|
||||
// Get the array of nLevel.
|
||||
jLevel = JsonArrayGet(jCategory, nLevel);
|
||||
nMaxSlotIndex = JsonGetLength(jLevel);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1925", "nLevel: " + IntToString(nLevel) +
|
||||
" nMaxSlotIndex: " + IntToString(nMaxSlotIndex));
|
||||
if(nMaxSlotIndex > 0)
|
||||
{
|
||||
// Get the talent within nLevel cycling from the first to the last.
|
||||
nSlotIndex = 0;
|
||||
while (nSlotIndex < nMaxSlotIndex)
|
||||
{
|
||||
jTalent= JsonArrayGet(jLevel, nSlotIndex);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1936", "nSlotIndex: " + IntToString(nSlotIndex) +
|
||||
" jTalent Type: " + IntToString(JsonGetInt(JsonArrayGet(jTalent, 0))));
|
||||
nSpell = JsonGetInt(JsonArrayGet(jTalent, 1));
|
||||
if(nSpell == nTalent)
|
||||
{
|
||||
nType = JsonGetInt(JsonArrayGet(jTalent, 0));
|
||||
if(nType == AI_TALENT_TYPE_SPELL || nType == AI_TALENT_TYPE_SP_ABILITY)
|
||||
{
|
||||
if(ai_UseTalentOnObject(oCreature, jTalent, oTarget, 0))
|
||||
{
|
||||
ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if(nType == AI_TALENT_TYPE_ITEM)
|
||||
{
|
||||
// Items do not need to concentrate.
|
||||
if(ai_UseCreatureItemTalent(oCreature, jLevel, jTalent, sCategory, 0, oTarget))
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1955", "Checking if Item is used up: " +
|
||||
IntToString(JsonGetInt(JsonArrayGet(jTalent, 4))));
|
||||
if(JsonGetInt(JsonArrayGet(jTalent, 4)) == -1)
|
||||
{
|
||||
ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
nSlotIndex++;
|
||||
}
|
||||
}
|
||||
nLevel++;
|
||||
}
|
||||
return FALSE;
|
||||
} */
|
||||
/*******************************************************************************
|
||||
Old talent system that checks by category then level.
|
||||
*******************************************************************************/
|
||||
int ai_UseCreatureTalent(object oCreature, string sCategory, int nInMelee, int nLevel = 10, object oTarget = OBJECT_INVALID)
|
||||
{
|
||||
// Get the Max Talent Level to see if we even need to pull this talent.
|
||||
@@ -2740,21 +3273,28 @@ int ai_UseCreatureTalent(object oCreature, string sCategory, int nInMelee, int n
|
||||
{
|
||||
if(nType == AI_TALENT_TYPE_SPELL)
|
||||
{
|
||||
nTalentUsed = ai_UseCreatureSpellTalent(oCreature, jLevel, jTalent, sCategory, nInMelee, oTarget);
|
||||
// -1 means it was a memorized spell and we need to remove it.
|
||||
if(nTalentUsed == -1)
|
||||
// Check to make sure they still have this spell.
|
||||
nClass = JsonGetInt(JsonArrayGet(jTalent, 2));
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "3290", GetName(oCreature) + " Memorizes Spells? " +
|
||||
Get2DAString("classes", "MemorizesSpells", nClass));
|
||||
if(Get2DAString("classes", "MemorizesSpells", nClass) == "1")
|
||||
{
|
||||
ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex);
|
||||
if(nMaxSlotIndex == 1) ai_UpdateMaxTalentLevel(oCreature, jCategory, sCategory, nMaxTalentLevel, nLevel);
|
||||
return TRUE;
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "3294", " Spell Memorized? " +
|
||||
IntToString(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlotIndex)));
|
||||
if(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlotIndex) < 1)
|
||||
{
|
||||
ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex);
|
||||
if(nMaxSlotIndex == 1) ai_UpdateMaxTalentLevel(oCreature, jCategory, sCategory, nMaxTalentLevel, nLevel);
|
||||
}
|
||||
else if(ai_UseCreatureSpellTalent(oCreature, jLevel, jTalent, sCategory, nInMelee, oTarget)) return TRUE;
|
||||
}
|
||||
// There are no more spell slots left for non-memorizing caster so remove the level.
|
||||
else if(nTalentUsed == -2)
|
||||
else if(!GetSpellUsesLeft(oCreature, nClass, JsonGetInt(JsonArrayGet(jTalent, 1))))
|
||||
{
|
||||
ai_RemoveTalentLevel(oCreature, jCategory, jLevel, sCategory, nLevel);
|
||||
if(nMaxSlotIndex == 1) ai_UpdateMaxTalentLevel(oCreature, jCategory, sCategory, nMaxTalentLevel, nLevel);
|
||||
nTalentUsed = FALSE;
|
||||
}
|
||||
else if(nTalentUsed) return TRUE;
|
||||
else if(ai_UseCreatureSpellTalent(oCreature, jLevel, jTalent, sCategory, nInMelee, oTarget)) return TRUE;
|
||||
}
|
||||
else if(nType == AI_TALENT_TYPE_SP_ABILITY)
|
||||
{
|
||||
@@ -2769,7 +3309,7 @@ int ai_UseCreatureTalent(object oCreature, string sCategory, int nInMelee, int n
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bUseMagicItems && nType == AI_TALENT_TYPE_ITEM)
|
||||
else if(bUseMagicItems && nType == AI_TALENT_TYPE_ITEM)
|
||||
{
|
||||
// Items do not need to concentrate.
|
||||
if(ai_UseCreatureItemTalent(oCreature, jLevel, jTalent, sCategory, nInMelee, oTarget))
|
||||
@@ -2856,6 +3396,19 @@ int ai_UseTalent(object oCreature, int nTalent, object oTarget)
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
// Lets do a check right before we cast the spell to see if the target is still good.
|
||||
void ai_CheckSpellTarget(object oCreature, object oTarget)
|
||||
{
|
||||
if(GetIsDead(oTarget))
|
||||
{
|
||||
//SendMessageToPC(GetFirstPC(), "0i_talents, 2864, " + GetName(oCreature) +
|
||||
//" is stopping our spell casting because " + GetName(oTarget) + " is dead!");
|
||||
//WriteTimestampedLogEntry("0i_talents, 2864, " + GetName(oCreature) +
|
||||
//" is stopping our spell casting because " + GetName(oTarget) + " is dead!");
|
||||
ai_ClearCreatureActions();
|
||||
ExecuteScript("0e_do_combat_rnd", oCreature);
|
||||
}
|
||||
}
|
||||
int ai_UseTalentOnObject(object oCreature, json jTalent, object oTarget, int nInMelee, int bCheckPosition = TRUE)
|
||||
{
|
||||
int nClass, nLevel, nSlot, nMetaMagic, nDomain;
|
||||
@@ -2955,7 +3508,14 @@ int ai_UseTalentOnObject(object oCreature, json jTalent, object oTarget, int nIn
|
||||
" nDomain: " + IntToString(nDomain) + " nClass: " + IntToString(nClass));
|
||||
ai_SetLastAction(oCreature, nSpell);
|
||||
ActionCastSpellAtObject(nSpell, oTarget, nMetaMagic, FALSE, nDomain, 0, FALSE, nClass, FALSE);
|
||||
// This was added to do a second check right before they cast to make sure
|
||||
// the target was not killed between us deciding to cast and then casting!
|
||||
DelayCommand(2.5, ai_CheckSpellTarget(oCreature, oTarget));
|
||||
ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature));
|
||||
// Temp Debug!!!!!
|
||||
//string sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
//SendMessageToPC(GetFirstPC(), "0i_talents, 1859 " + GetName(oCreature) + " is casting " + sSpellName + " on " + GetName(oTarget));
|
||||
// Temp Debug!!!!!
|
||||
if(AI_DEBUG)
|
||||
{
|
||||
string sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
@@ -3062,7 +3622,23 @@ int ai_UseTalentAtLocation(object oCreature, json jTalent, object oTarget, int n
|
||||
int ai_CheckSpecialTalentsandUse(object oCreature, json jTalent, string sCategory, int nInMelee, object oTarget)
|
||||
{
|
||||
int nSpell = JsonGetInt(JsonArrayGet(jTalent, 1));
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1949", "nSpell: " + GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))) +
|
||||
// This checks to see if they tried to cast this spell last round and if we
|
||||
// are trying to cast it again before at least 3 seconds is up then the spell
|
||||
// is being canceled... remove this spell and look for another!
|
||||
if(ai_CompareLastAction(oCreature, nSpell) &&
|
||||
ai_GetCurrentTimeStamp() - GetLocalInt(oCreature, sLastActionTimeVarname) < 2)
|
||||
{
|
||||
if(AI_DEBUG)
|
||||
{
|
||||
int nLastTime = GetLocalInt(oCreature, sLastActionTimeVarname);
|
||||
int nCurrentTime = ai_GetCurrentTimeStamp();
|
||||
ai_Debug("0i_talents", "3634", "Same spell cast within less than 2 seconds!" +
|
||||
" nSpell: " + IntToString(nSpell) + " nLastActionTime: " + IntToString(nLastTime) +
|
||||
" nCurrentTime: " + IntToString(nCurrentTime) + " Difference: " + IntToString(nCurrentTime - nLastTime));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "3637", "nSpell: " + GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))) +
|
||||
" sCategory: " + sCategory);
|
||||
if(sCategory == AI_TALENT_DISCRIMINANT_AOE)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user