2025/12/19 Update
Added PEPS. Updated nim tools. Hooked up new GUI event. Added PRC8 Discord journal entry. Full compile.
This commit is contained in:
193
_module/nss/pc_savebuffs.nss
Normal file
193
_module/nss/pc_savebuffs.nss
Normal file
@@ -0,0 +1,193 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
// Script Name: pc_savebuffs
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Used with pi_buffing to run the buffing plugin for
|
||||
Philos Single Player Enhancements.
|
||||
|
||||
Note: If a spell saves incorrectly check the spell script to see if the correct
|
||||
spell is being passed through the SignalEvent correctly.
|
||||
Known error in Shield of Faith spell as the below code in the shield of faith
|
||||
script sends Camoflage instead!
|
||||
"SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, 421, FALSE));"
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_nui"
|
||||
// sDataField should be one of the data fields for the table.
|
||||
// Returns a string of the data stored.
|
||||
string GetBuffDatabaseString(object oPlayer, string sDataField, string sTag = "");
|
||||
// sDataField should be one of the data fields for that table.
|
||||
// sData is the string data to be saved.
|
||||
void SetBuffDatabaseString(object oPlayer, string sDataField, string sData, string sTag = "");
|
||||
// sDataField should be one of the data fields for that table.
|
||||
// jData is the json data to be saved.
|
||||
void SetBuffDatabaseJson(object oPlayer, string sDataField, json jData, string sTag = "");
|
||||
// sDataField should be one of the data fields for the table.
|
||||
// Returns a string of the data stored.
|
||||
json GetBuffDatabaseJson(object oPlayer, string sDataField, string sTag = "");
|
||||
// Returns the level if this spell has a domain spell on nLevel, or 0.
|
||||
int GetHasDomainSpell(object oCaster, int nClass, int nLevel, int nSpell);
|
||||
|
||||
void main()
|
||||
{
|
||||
object oTarget = OBJECT_SELF;
|
||||
object oCaster = GetLastSpellCaster();
|
||||
// When setting up the save spells button we saved the PC to itself.
|
||||
// Here we get the PC from either our henchmen or ourselves.
|
||||
// We do this to make sure that this PC and henchmen are the ones saving spells.
|
||||
object oPC = GetLocalObject(ai_GetPlayerMaster(oCaster), "AI_BUFF_PC");
|
||||
// If this is a harmful spell or we couldn't find oPC then we need to fix
|
||||
// the targets scripts back and run the correct OnSpellCastAt script.
|
||||
if(GetLastSpellHarmful() || oPC == OBJECT_INVALID)
|
||||
{
|
||||
DeleteLocalObject(oPC, "AI_BUFF_PC");
|
||||
string sScript = GetLocalString(oPC, "AI_BUFF_CAST_AT_SCRIPT");
|
||||
SetEventScript(oPC, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, sScript);
|
||||
DeleteLocalString(oPC, "AI_BUFF_CAST_AT_SCRIPT");
|
||||
// Cleanup your followers to allow spells to be reacted to as normal.
|
||||
int nAssociateType = 2;
|
||||
object oAssociate = GetAssociate(nAssociateType, oPC);
|
||||
while(nAssociateType < 5)
|
||||
{
|
||||
if(oAssociate != OBJECT_INVALID)
|
||||
{
|
||||
sScript = GetLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, sScript);
|
||||
DeleteLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT");
|
||||
}
|
||||
oAssociate = GetAssociate(++nAssociateType, oPC);
|
||||
}
|
||||
int nIndex = 1;
|
||||
oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex);
|
||||
while(nIndex <= AI_MAX_HENCHMAN)
|
||||
{
|
||||
if(oAssociate != OBJECT_INVALID)
|
||||
{
|
||||
sScript = GetLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, sScript);
|
||||
DeleteLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT");
|
||||
}
|
||||
oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, ++nIndex);
|
||||
}
|
||||
NuiSetBind(oPC, NuiFindWindow(oPC, "widgetbuffwin"), "btn_save", JsonBool(FALSE));
|
||||
ai_SendMessages("Saving spells to the list has been turned off.", AI_COLOR_YELLOW, oPC);
|
||||
ExecuteScript(sScript, oTarget);
|
||||
return;
|
||||
}
|
||||
// This blocks one spell from saving multiple times due to being an AOE.
|
||||
if(GetLocalInt(oPC, "AI_ONLY_ONE")) return;
|
||||
SetLocalInt(oPC, "AI_ONLY_ONE", TRUE);
|
||||
// We delay this for just less than half a round due to haste.
|
||||
DelayCommand(2.5, DeleteLocalInt(oPC, "AI_ONLY_ONE"));
|
||||
// If the oTarget != oCaster then we are casting a spell on one of our
|
||||
// associates. Some functions expect OBJECT_SELF to be the caster.
|
||||
// We get around that by doing some ExecuteScriptChunk shenanigans.
|
||||
int nClass, nLevel, nMetaMagic;
|
||||
if(oTarget != oCaster)
|
||||
{
|
||||
// These functions need the caster to be OBJECT_SELF so lets do a HACK!
|
||||
ExecuteScriptChunk("SetLocalInt(OBJECT_SELF, \"AI_BUFF_CASTCLASS\", GetLastSpellCastClass());", oCaster);
|
||||
ExecuteScriptChunk("SetLocalInt(OBJECT_SELF, \"AI_BUFF_SPELLLEVEL\", GetLastSpellLevel());", oCaster);
|
||||
ExecuteScriptChunk("SetLocalInt(OBJECT_SELF, \"AI_BUFF_METAMAGIC\", GetMetaMagicFeat());", oCaster);
|
||||
nClass = GetLocalInt(oCaster, "AI_BUFF_CASTCLASS");
|
||||
nLevel = GetLocalInt(oCaster, "AI_BUFF_SPELLLEVEL");
|
||||
nMetaMagic = GetLocalInt(oCaster, "AI_METAMAGIC");
|
||||
DeleteLocalInt(oCaster, "AI_BUFF_CASTCLASS");
|
||||
DeleteLocalInt(oCaster, "AI_BUFF_SPELLLEVEL");
|
||||
DeleteLocalInt(oCaster, "AI_BUFF_METAMAGIC");
|
||||
}
|
||||
else
|
||||
{
|
||||
nClass = GetLastSpellCastClass();
|
||||
nLevel = GetLastSpellLevel();
|
||||
nMetaMagic = GetMetaMagicFeat();
|
||||
}
|
||||
int nSpell = GetLastSpell();
|
||||
int nDomain = GetHasDomainSpell(oCaster, nClass, nLevel, nSpell);
|
||||
string sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
if(nDomain) sName += " [Domain]";
|
||||
if(nMetaMagic > 0 && StringToInt(Get2DAString("classes", "MemorizesSpells", nClass)))
|
||||
{
|
||||
// We must add the level of the metamagic to the spells level to get the spells correct level.
|
||||
if(nMetaMagic == METAMAGIC_EMPOWER) { sName += " (Empowered)"; nLevel += 2; }
|
||||
else if(nMetaMagic == METAMAGIC_EXTEND) { sName += " (Extended)"; nLevel += 1; }
|
||||
else if(nMetaMagic == METAMAGIC_MAXIMIZE) { sName += " (Maximized)"; nLevel += 3; }
|
||||
else if(nMetaMagic == METAMAGIC_QUICKEN) { sName += " (Quickened)"; nLevel += 4; }
|
||||
else if(nMetaMagic == METAMAGIC_SILENT) { sName += " (Silent)"; nLevel += 1; }
|
||||
else if(nMetaMagic == METAMAGIC_STILL) { sName += " (Still)"; nLevel += 1; }
|
||||
}
|
||||
json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata");
|
||||
string sList = JsonGetString(JsonArrayGet(jMenuData, 0));
|
||||
json jSpells = GetBuffDatabaseJson(oPC, "spells", sList);
|
||||
json jSpell = JsonArray();
|
||||
jSpell = JsonArrayInsert(jSpell, JsonInt(nSpell));
|
||||
jSpell = JsonArrayInsert(jSpell, JsonInt(nClass));
|
||||
jSpell = JsonArrayInsert(jSpell, JsonInt(nLevel));
|
||||
jSpell = JsonArrayInsert(jSpell, JsonInt(nMetaMagic));
|
||||
jSpell = JsonArrayInsert(jSpell, JsonInt(nDomain));
|
||||
string sCasterName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oCaster)));
|
||||
jSpell = JsonArrayInsert(jSpell, JsonString(sCasterName));
|
||||
string sTargetName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oTarget)));
|
||||
jSpell = JsonArrayInsert(jSpell, JsonString(sTargetName));
|
||||
jSpells = JsonArrayInsert(jSpells, jSpell);
|
||||
SetBuffDatabaseJson(oPC, "spells", jSpells, sList);
|
||||
SendMessageToPC(oPC, sCasterName + " has cast " + sName + " to be saved for fast buffing on " + sTargetName + ".");
|
||||
ExecuteScript("pi_buffing", oPC);
|
||||
}
|
||||
string GetBuffDatabaseString(object oPlayer, string sDataField, string sTag)
|
||||
{
|
||||
string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer, TRUE)));
|
||||
string sQuery = "SELECT " + sDataField + " FROM BUFF_TABLE WHERE name = @name AND tag = @tag;";
|
||||
sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery);
|
||||
SqlBindString(sql, "@name", sName);
|
||||
SqlBindString(sql, "@tag", sTag);
|
||||
if (SqlStep (sql)) return SqlGetString (sql, 0);
|
||||
else return "";
|
||||
}
|
||||
void SetBuffDatabaseString(object oPlayer, string sDataField, string sData, string sTag)
|
||||
{
|
||||
string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer, TRUE)));
|
||||
string sQuery = "UPDATE BUFF_TABLE SET " + sDataField + " = @data WHERE name = @name AND tag = @tag;";
|
||||
sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery);
|
||||
SqlBindString(sql, "@data", sData);
|
||||
SqlBindString(sql, "@name", sName);
|
||||
SqlBindString(sql, "@tag", sTag);
|
||||
SqlStep (sql);
|
||||
}
|
||||
void SetBuffDatabaseJson (object oPlayer, string sDataField, json jData, string sTag)
|
||||
{
|
||||
string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer, TRUE)));
|
||||
string sQuery = "UPDATE BUFF_TABLE SET " + sDataField + " = @data WHERE name = @name AND tag = @tag;";
|
||||
sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery);
|
||||
SqlBindJson (sql, "@data", jData);
|
||||
SqlBindString (sql, "@name", sName);
|
||||
SqlBindString (sql, "@tag", sTag);
|
||||
SqlStep (sql);
|
||||
}
|
||||
json GetBuffDatabaseJson (object oPlayer, string sDataField, string sTag)
|
||||
{
|
||||
string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer, TRUE)));
|
||||
string sQuery = "SELECT " + sDataField + " FROM BUFF_TABLE WHERE name = @name AND tag = @tag;";
|
||||
sqlquery sql = SqlPrepareQueryObject(oPlayer, sQuery);
|
||||
SqlBindString (sql, "@name", sName);
|
||||
SqlBindString (sql, "@tag", sTag);
|
||||
if (SqlStep (sql)) return SqlGetJson (sql, 0);
|
||||
else return JsonArray ();
|
||||
}
|
||||
int GetHasDomainSpell(object oCaster, int nClass, int nLevel, int nSpell)
|
||||
{
|
||||
int nIndex, nMaxIndex, nMSpell, nMmSpell, bDomain, nSubRadSpell, nSubSpell;
|
||||
string sSubRadSpell;
|
||||
if(StringToInt(Get2DAString("classes", "MemorizesSpells", nClass)))
|
||||
{
|
||||
nMaxIndex = GetMemorizedSpellCountByLevel(oCaster, nClass, nLevel);
|
||||
while(nIndex < nMaxIndex)
|
||||
{
|
||||
nMSpell = GetMemorizedSpellId(oCaster, nClass, nLevel, nIndex);
|
||||
if(nSpell == nMSpell)
|
||||
{
|
||||
if(GetMemorizedSpellIsDomainSpell(oCaster, nClass, nLevel, nIndex)) return nLevel;
|
||||
}
|
||||
nIndex ++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user