2025/11/30 Update

Updated for NWN:EE 37-17
Updated NWNxEE libraries.
Updated nim tooling
Updated PEPs
Associated new GUI module event script.
Full compile.
This commit is contained in:
Jaysyn904
2025-12-01 00:00:34 -05:00
parent 4d7b173526
commit d0a4ee6f1f
540 changed files with 62740 additions and 60703 deletions

View File

@@ -152,6 +152,8 @@ void ai_AmbientAnimations();
void ai_DoAssociateCombatRound(object oCreature, object oTarget = OBJECT_INVALID)
{
object oMaster = GetMaster(oCreature);
if(GetLocalInt(oMaster, AI_TARGET_MODE_ON) && GetLocalObject(oMaster, AI_TARGET_MODE_ASSOCIATE) == oCreature) return;
if(ai_StayClose(oCreature)) return;
// Is the target our Player has locked in dead? If so then clear it.
if(GetIsDead(GetLocalObject(oCreature, AI_PC_LOCKED_TARGET))) DeleteLocalObject(oCreature, AI_PC_LOCKED_TARGET);
@@ -176,21 +178,27 @@ void ai_DoAssociateCombatRound(object oCreature, object oTarget = OBJECT_INVALID
// the polymorph AI script.
if(sAI != "ai_coward" && sAI != "ai_a_peaceful")
{
if(AI_DEBUG) ai_Debug("0i_actions", "173", "Should we use polymorph? " +
IntToString(GetAppearanceType(oCreature) != ai_GetNormalAppearance(oCreature)));
if(AI_DEBUG)
{
ai_Debug("0i_actions", "181", "Should we use polymorph? Current: " +
IntToString(GetAppearanceType(oCreature)) + " Normal: " + IntToString(ai_GetNormalAppearance(oCreature)));
if(ai_GetIsHidden(oCreature))
{
ai_Debug("0i_actions", "179", "We are hidden!" +
ai_Debug("0i_actions", "185", "We are hidden!" +
" Can they see us? " + IntToString(ai_GetNearestIndexThatSeesUs(oCreature)));
}
}
if(GetAppearanceType(oCreature) != ai_GetNormalAppearance(oCreature))
if(ai_GetIsHidden(oCreature) && !ai_GetNearestIndexThatSeesUs(oCreature)) sAI = "ai_a_invisible";
else if(GetAppearanceType(oCreature) != ai_GetNormalAppearance(oCreature))
{
sAI = "ai_a_polymorphed";
if(!GetLocalInt(oCreature, AI_POLYMORPHED))
{
SetLocalInt(oCreature, AI_POLYMORPHED, TRUE);
ai_ClearTalents(oCreature);
ai_SetCreatureSpecialAbilityTalents(oCreature, FALSE, TRUE);
}
}
else if(ai_GetIsHidden(oCreature) && !ai_GetNearestIndexThatSeesUs(oCreature)) sAI = "ai_a_invisible";
}
if(sAI == "") sAI = "ai_a_default";
if(AI_DEBUG) ai_Debug("0i_actions", "190", "********** " + GetName (oCreature) + " **********");
@@ -226,11 +234,24 @@ void ai_DoMonsterCombatRound(object oMonster)
string sAI = GetLocalString(oMonster, AI_COMBAT_SCRIPT);
if(sAI != "ai_coward")
{
if(GetAppearanceType(oMonster) != ai_GetNormalAppearance(oMonster))
if(AI_DEBUG) ai_Debug("0i_actions", "235", "Should we use polymorph? Current: " +
IntToString(GetAppearanceType(oMonster)) + " Normal: " + IntToString(ai_GetNormalAppearance(oMonster)));
if(ai_GetIsHidden(oMonster))
{
if(AI_DEBUG) ai_Debug("0i_actions", "239", "We are hidden!" +
" Can they see us? " + IntToString(ai_GetNearestIndexThatSeesUs(oMonster)));
}
if(ai_GetIsHidden(oMonster) && !ai_GetNearestIndexThatSeesUs(oMonster)) sAI = "ai_invisible";
else if(GetAppearanceType(oMonster) != ai_GetNormalAppearance(oMonster))
{
sAI = "ai_polymorphed";
if(!GetLocalInt(oMonster, AI_POLYMORPHED))
{
SetLocalInt(oMonster, AI_POLYMORPHED, TRUE);
ai_ClearTalents(oMonster);
ai_SetCreatureSpecialAbilityTalents(oMonster, TRUE, TRUE);
}
}
else if(ai_GetIsHidden(oMonster) && !ai_GetNearestIndexThatSeesUs(oMonster)) sAI = "ai_invisible";
}
if(sAI == "") sAI = "ai_default";
if(AI_DEBUG) ai_Debug("0i_actions", "230", "********** " + GetName (oMonster) + " **********");
@@ -277,7 +298,7 @@ int ai_StayClose(object oCreature)
if(fPerceptionDistance == 0.0)
{
fPerceptionDistance = GetLocalFloat(oMaster, AI_ASSOC_PERCEPTION_DISTANCE);
if(fPerceptionDistance == 0.0) fPerceptionDistance = 20.0;
if(fPerceptionDistance == 0.0) fPerceptionDistance = 25.0;
}
object oTarget = GetLocalObject(oCreature, AI_FOLLOW_TARGET);
if(oTarget == OBJECT_INVALID) oTarget = oMaster;
@@ -521,11 +542,11 @@ int ai_MoralCheck(object oCreature)
if(nHpPercent <= AI_HEALTH_WOUNDED)
{
// Debug code to look for multiple moral checks at once by one creature?
if(GetLocalString(GetModule(), AI_RULE_DEBUG_CREATURE) == "")
{
SetLocalString(GetModule(), AI_RULE_DEBUG_CREATURE, GetName(oCreature));
ai_Debug("0i_actions", "424", GetName(oCreature) + " starting debug mode to test Moral checks!");
}
//if(GetLocalString(GetModule(), AI_RULE_DEBUG_CREATURE) == "")
//{
// SetLocalString(GetModule(), AI_RULE_DEBUG_CREATURE, GetName(oCreature));
// ai_Debug("0i_actions", "424", GetName(oCreature) + " starting debug mode to test Moral checks!");
//}
if(nHpPercent <= AI_HEALTH_BLOODY) nDC = AI_BLOODY_MORAL_DC;
else nDC = AI_WOUNDED_MORAL_DC;
nDC = nDC - GetLocalInt(oCreature, AI_ALLY_NUMBERS);
@@ -681,17 +702,17 @@ void ai_DoPhysicalAttackOnBest(object oCreature, int nInMelee, int bAlwaysAtk =
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
}
else
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
if(AI_DEBUG) ai_Debug("0i_actions", "519", "Do ranged attack against nearest: " + GetName(oTarget) + "!");
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
@@ -739,17 +760,17 @@ void ai_DoPhysicalAttackOnNearest(object oCreature, int nInMelee, int bAlwaysAtk
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestPhysicalTarget(oCreature);
}
else
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
if(AI_DEBUG) ai_Debug("0i_actions", "519", "Do ranged attack against nearest: " + GetName(oTarget) + "!");
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
@@ -796,17 +817,17 @@ void ai_DoPhysicalAttackOnLowestCR(object oCreature, int nInMelee, int bAlwaysAt
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
}
else
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
if(AI_DEBUG) ai_Debug("0i_actions", "559", GetName(OBJECT_SELF) + " does ranged attack on weakest: " + GetName(oTarget) + "!");
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
@@ -1112,7 +1133,7 @@ void ai_ActionTryHealing(object oCreature, object oTarget)
}
int ai_TryHealing(object oCreature, object oTarget, int bForce = FALSE)
{
if(AI_DEBUG) ai_Debug("0i_actions", "733", "Try healing: oCreature: " + GetName(oCreature) +
if(AI_DEBUG) ai_Debug("0i_actions", "1136", "Try healing: oCreature: " + GetName(oCreature) +
" oTarget: " + GetName(oTarget) + " No Party Healing: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_PARTY_HEALING_OFF)) +
" No Self Healing: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_SELF_HEALING_OFF)) +
" AI_I_AM_BEING_HEALED: " + IntToString(GetLocalInt(oTarget, "AI_I_AM_BEING_HEALED")) +
@@ -1133,52 +1154,92 @@ int ai_TryHealing(object oCreature, object oTarget, int bForce = FALSE)
oCreature != oTarget) return FALSE;
if(ai_GetAIMode(oCreature, AI_MODE_SELF_HEALING_OFF) &&
oCreature == oTarget) return FALSE;
// Undead don't heal so lets skip this for them, maybe later we can fix this.
if(GetRacialType(oTarget) == RACIAL_TYPE_UNDEAD) return FALSE;
int nHpLost = ai_GetPercHPLoss(oTarget);
// If the player is forcing a heal then we always heal.
if(bForce && nHpLost < 100) nHpLost = 0;
if(AI_DEBUG) ai_Debug("0i_actions", "743", "nHpLost: " + IntToString(nHpLost) +
if(AI_DEBUG) ai_Debug("0i_actions", "1160", "nHpLost: " + IntToString(nHpLost) +
" limit: " + IntToString(ai_GetHealersHpLimit(oTarget, FALSE)));
if(nHpLost >= ai_GetHealersHpLimit(oTarget, FALSE))
// Check to see if we need poison, disease, or ability drain removed.
int nEffectType;
effect eEffect = GetFirstEffect(oTarget);
while(GetIsEffectValid(eEffect))
{
// Check to see if we need poison, disease, or ability drain removed.
int nEffectType;
effect eEffect = GetFirstEffect(oTarget);
while(GetIsEffectValid(eEffect))
nEffectType = GetEffectType(eEffect);
if(AI_DEBUG) ai_Debug("0i_actions", "1168", "Checking to cure(31/32/39) nEffectType: " + IntToString(nEffectType));
if(nEffectType == EFFECT_TYPE_DISEASE)
{
nEffectType = GetEffectType(eEffect);
if(AI_DEBUG) ai_Debug("0i_actions", "1094", "Checking to cure(31/32/39) nEffectType: " + IntToString(nEffectType));
if(nEffectType == EFFECT_TYPE_DISEASE)
if(AI_DEBUG) ai_Debug("0i_actions", "1171", GetName(oTarget) + " is diseased!");
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_DISEASED, bForce)) return TRUE;
if(oCreature == oTarget)
{
if(AI_DEBUG) ai_Debug("0i_actions", "1097", "I am diseased!");
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_DISEASED, bForce)) return TRUE;
if(oCreature == oTarget)
{
if(!d20()) ai_HaveCreatureSpeak(oCreature, 5, ":43:4:14:15:16:");
SpeakString(AI_I_AM_DISEASED, TALKVOLUME_SILENT_TALK);
}
if(!Random(20)) ai_HaveCreatureSpeak(oCreature, 5, ":43:4:14:15:16:");
SpeakString(AI_I_AM_DISEASED, TALKVOLUME_SILENT_TALK);
}
else if(nEffectType == EFFECT_TYPE_POISON)
}
else if(nEffectType == EFFECT_TYPE_POISON)
{
if(AI_DEBUG) ai_Debug("0i_actions", "1181", GetName(oTarget) + " is poisoned!");
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_POISONED, bForce)) return TRUE;
if(oCreature == oTarget)
{
if(AI_DEBUG) ai_Debug("0i_actions", "1107", "I am poisoned!");
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_POISONED, bForce)) return TRUE;
if(oCreature == oTarget)
{
if(!d20()) ai_HaveCreatureSpeak(oCreature, 6, ":43:4:14:15:16:19:");
SpeakString(AI_I_AM_POISONED, TALKVOLUME_SILENT_TALK);
}
if(!Random(20)) ai_HaveCreatureSpeak(oCreature, 6, ":43:4:14:15:16:19:");
SpeakString(AI_I_AM_POISONED, TALKVOLUME_SILENT_TALK);
}
else if(nEffectType == EFFECT_TYPE_ABILITY_DECREASE)
}
else if(nEffectType == EFFECT_TYPE_ABILITY_DECREASE)
{
if(AI_DEBUG) ai_Debug("0i_actions", "1191", GetName(oTarget) + " is weak!");
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_WEAK, bForce)) return TRUE;
if(oCreature == oTarget)
{
if(AI_DEBUG) ai_Debug("0i_actions", "1117", "I am weak!");
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_WEAK, bForce)) return TRUE;
if(oCreature == oTarget)
{
if(!d20()) ai_HaveCreatureSpeak(oCreature, 3, ":43:4:5:");
SpeakString(AI_I_AM_WEAK, TALKVOLUME_SILENT_TALK);
}
if(!Random(20)) ai_HaveCreatureSpeak(oCreature, 3, ":43:4:5:");
SpeakString(AI_I_AM_WEAK, TALKVOLUME_SILENT_TALK);
}
eEffect = GetNextEffect(oTarget);
}
eEffect = GetNextEffect(oTarget);
}
// Everything below here is for healing.
if(nHpLost >= ai_GetHealersHpLimit(oTarget, FALSE)) return FALSE;
// Undead require inflict spells to heal!
object oMaster = ai_GetPlayerMaster(oCreature);
if(GetRacialType(oTarget) == RACIAL_TYPE_UNDEAD)
{
// Do we have no magic on?
if(!ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC))
{
int nClass, nPosition = 1;
string sMemorized;
while(nPosition <= AI_MAX_CLASSES_PER_CHARACTER)
{
nClass = GetClassByPosition(nPosition, oCreature);
if(AI_DEBUG) ai_Debug("0i_actions", "753", "nClass: " + IntToString(nClass));
if(nClass == CLASS_TYPE_INVALID) break;
sMemorized = Get2DAString("classes", "MemorizesSpells", nClass);
// If Memorized column is "" then they are not a caster.
if(sMemorized != "")
{
if(sMemorized == "1")
{
if(ai_CastMemorizedInflict(oCreature, oTarget, oMaster, nClass))
{
SetLocalInt(oTarget, "AI_I_AM_BEING_HEALED", TRUE);
return TRUE;
}
}
else if(ai_CastKnownInflict(oCreature, oTarget, oMaster, nClass))
{
SetLocalInt(oTarget, "AI_I_AM_BEING_HEALED", TRUE);
return TRUE;
}
}
nPosition++;
}
}
// We can't heal ourselves! Can any of our allies? Lets ask.
if(oCreature == oTarget)
{
SetLocalInt(oCreature, "AI_WOUNDED_SHOUT_LIMIT", GetLocalInt(oCreature, "AI_WOUNDED_SHOUT_LIMIT") + 1);
SpeakString(AI_I_AM_WOUNDED, TALKVOLUME_SILENT_TALK);
}
return FALSE;
}
@@ -1192,7 +1253,6 @@ int ai_TryHealing(object oCreature, object oTarget, int bForce = FALSE)
return TRUE;
}
}
object oMaster = ai_GetPlayerMaster(oCreature);
// Do we have no magic on?
if(!ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC))
{