I fixed Arcane Mimic.

Started by Cruzel, January 29, 2019, 03:36:05 AM

Previous topic - Next topic

Cruzel

Fixes Include:

CHECKING YOUR SPELLSLOTS.

-No longer need to split stacks. They will decrement properly.
-No more burning spellslots without ever casting, spellcraft checks moved to the spellhook. (You'll be able to spam the button and queue  a spell for days if you're fast, but they'll all fail after you fail your spellcraft check!)
-CHECKING YOUR SPELLS.
-No more wasting a rest cycle after resets. The server will remember which spells you've stolen and which you haven't since you last rested
-Did I mention you can check your spells?

-METAMAGIC, WORKING FUNCTIONALLY. (Commented out by default, to be enabled if DM's please)


As a bonus, I added an optional feature for the DM's leisure. The ability to make a loot item for a mimic they can steal a spell from without it poofing. Easy as pie. Set a variable nMimic=1  and the item will last forever.  Set an additional variable nMimicCount=5 (for example) and they can absorb the item 5 times before it is destroyed. (This part should work on any item type. Normal absorbs should be limited to potions only.)

Base functions are solid, tested, and working. Only minor tweaks are needed to make them compatible with EFU Player tools.
For the playerbase who want to fiddle with this, Instructions:
[hide] you'll be able to copy/paste these scripts into individual player tools, and all you'll need to do from there is set up a spell hook script by going to your module properties and setting a string called "X2_S_UD_SPELLSCRIPT" with a value of whatever you want your spellhook script to be called.  Then just copy/paste the hook section into that.
[/hide]

SAUCE CODES
[hide]

Steal spell script:

[hide]
#include "x3_inc_string"
#include "x2_inc_switches"
object oSelf = OBJECT_SELF;
int nSpell   = GetSpellId();
int nMeta    = GetMetaMagicFeat();

int nShift(int nNum)
{
switch (nNum)//for labeling ease
     {
         case 1:  nNum = 2 ;
         case 2:  nNum = 1 ;
         case 4:  nNum = 3 ;
         case 8:  nNum = 4 ;
         case 16: nNum = 1 ;
         case 32: nNum = 1 ;
        return nNum;
     }
return nNum;
}

int MimicCast(object oSelf, int nSlot)
{
int nInnate = StringToInt(Get2DAString("spells", "Innate", nSpell));
int nDC = GetLocalInt(oSelf, "nMimicDCSlot"+IntToString(nSlot));
int nCheck;
nMeta = GetLocalInt(oSelf, "nMimicSlot"+IntToString(nSlot)+"Meta");

nMeta = nShift(nMeta);


nCheck = FloatToInt(5 + ((nInnate + nDC + nMeta) * 1.5));
SendMessageToPC(oSelf, "Mods are : " + IntToString(nInnate) + " " + IntToString(nDC) + " " + IntToString(nMeta));


if (GetIsSkillSuccessful(oSelf,SKILL_SPELLCRAFT, nCheck))
{
SetLocalInt(oSelf,"nMimicDCSlot"+IntToString(nSlot), (nCheck)); // use EFU formula  ?
return TRUE;
}
else
{
SetLocalInt(oSelf,"nMimicDCSlot"+IntToString(nSlot), 0);  // Set DC back to 0, forget spell;
SetLocalInt(oSelf, "nMimicSlot"+IntToString(nSlot),  0); //Clear the spellslot.
SetLocalInt(oSelf, "nMimicSlot"+IntToString(nSlot)+"Meta", 0); // Clear Metamagic.
SendMessageToPC(oSelf, StringToRGBString("The spell begins to elude you...", "733"));

return FALSE;
}
}
void main()
{
int nSlot=1; //REPLACE WITH EFU SLOT ID.
int nPerk=1; //Replace with EFU Mimic Check
// Check to see if it's an ITEM being used.
if (GetSpellCastItem() != OBJECT_INVALID) { return; } // End the script if we're an item.

if (nPerk =1)// REPLACE WITH CHECK TO SEE IF THIS IS A MIMIC SELFCASTING OR NOT
{

//Check to see if the spell is in the slot. They'll still be able to spam queues of a forgotten spell, but they will all fail to cast.
if (GetLocalInt(oSelf, "nMimicSlot"+IntToString(nSlot)) == nSpell)
{
MimicCast(oSelf, nSlot);
}
else // This badboy sets the SPELL FAILURE.
  {
  SetModuleOverrideSpellScriptFinished();
  SendMessageToPC(oSelf, "SPELL FAILED. HERP DERP"); //Debug, remove it
}

string sName = StringReplace(Get2DAString("spells", "Label", nSpell),  "_", " ");
}
/*
JUST FOR DEBUG (Stealing spells from self. UnComment this and Comment out the "SafetyCheck" functions in Steal Spell if you want them to do anything.
SetLocalInt(oSelf, "nLastCast", nSpell);
SetLocalInt(oSelf, "nLastMeta", nMeta);
*/
}
[/hide]

Recall Spell:  Note: This SHOULDN'T really need to be changed on EFU. I'm including it so everyone else can muck around with what I'm posting.  Functionally, all an EFUDM needs to do is move the spellcraft check to the spellhook script; and make sure the spellcast variables/assigned commands is right.  (and optionally,  use a check for  the metamagic variable) The spellfail function of the spellhook should take care of  any weirdness.

[hide]

//:://////////////////////////////////////////////
#include "x3_inc_string"

int TargetType(int nSpell)
{
string sType = Get2DAString("spells", "TargetType", nSpell);
SendMessageToPC(GetFirstPC(),sType + " was variable");
/* switch (nType)
{
  case 0x01:// SELF
  case 0x02://CREATURE
  case 0x04://area/ground
  case 0x08://Items
  case 0x10: //Doors
  case 0x20: //Placable
  case 0x40: // Triggers
  default:
  SendMessageToPC(GetFirstPC(), "ERROR LOL THESE DONT WORK"); */
  return FALSE;
}


void main()
{
    object   oPC      = OBJECT_SELF;
    location lTarget  = GetSpellTargetLocation();
    object   oTarget  = GetSpellTargetObject();

    int      nSlot    = 1; // REPLACE WITH EFU PLAYER TOOL SLOT ID VARIABLE
    int      nSpell   = GetLocalInt(oPC, "nMimicSlot"+IntToString(nSlot));
    int      nMeta    = GetLocalInt(oPC, "nMimicSlot"+IntToString(nSlot)+"Meta");

// SAFETY CHECKS OMITT ACID FOG
if (nSpell == 0)
    {
   SendMessageToPC(oPC, StringToRGBString("You have no spell memorized in slot "+IntToString(nSlot), "733"));
   return;
    }

//if (TargetType(nSpell) == FALSE) {   //Will work on this later. Fixes "mismatched targets" and ensures player tool only triggers spells on valid targets.


        // DO SPELLCRAFT CHECK HERE ON EFU. (MAKE SPELLHOOK FOR IT.)
        // FORGET SPELL IF CHECK FAILED
    if (oTarget != OBJECT_INVALID)
      {
        AssignCommand(oPC, ActionCastSpellAtObject(nSpell, oTarget, nMeta, TRUE));

        return;
      }

    else
      {
       AssignCommand(oPC, ActionCastSpellAtLocation(nSpell, lTarget, nMeta, TRUE));

      }

//  }// end bracket for Targettype()
}[/hide]


SpellHook functions:

This is the part that probably needs the most tweaking.  You'll need to tie in to the perk system to check/auth if the caster is a mimic (and make sure they're the only one who gets the spellfailure,  and insert the proper spellcraft check formula.


[hide]
#include "x3_inc_string"
#include "x2_inc_switches"
object oSelf = OBJECT_SELF;
int nSpell   = GetSpellId();
int nMeta    = GetMetaMagicFeat();

int nShift(int nNum)
{
switch (nNum)//for labeling ease
     {
         case 1:  nNum = 2 ;
         case 2:  nNum = 1 ;
         case 4:  nNum = 3 ;
         case 8:  nNum = 4 ;
         case 16: nNum = 1 ;
         case 32: nNum = 1 ;
        return nNum;
     }
return nNum;
}

int MimicCast(object oSelf, int nSlot)
{
int nInnate = StringToInt(Get2DAString("spells", "Innate", nSpell));
int nDC = GetLocalInt(oSelf, "nMimicDCSlot"+IntToString(nSlot));
int nCheck;
nMeta = GetLocalInt(oSelf, "nMimicSlot"+IntToString(nSlot)+"Meta");

nMeta = nShift(nMeta);


nCheck = FloatToInt(5 + ((nInnate + nDC + nMeta) * 1.5));
SendMessageToPC(oSelf, "Mods are : " + IntToString(nInnate) + " " + IntToString(nDC) + " " + IntToString(nMeta));


if (GetIsSkillSuccessful(oSelf,SKILL_SPELLCRAFT, nCheck))
{
SetLocalInt(oSelf,"nMimicDCSlot"+IntToString(nSlot), (nCheck)); // use EFU formula  ?
return TRUE;
}
else
{
SetLocalInt(oSelf,"nMimicDCSlot"+IntToString(nSlot), 0);  // Set DC back to 0, forget spell;
SetLocalInt(oSelf, "nMimicSlot"+IntToString(nSlot),  0); //Clear the spellslot.
SetLocalInt(oSelf, "nMimicSlot"+IntToString(nSlot)+"Meta", 0); // Clear Metamagic.
SendMessageToPC(oSelf, StringToRGBString("The spell begins to elude you...", "733"));

return FALSE;
}
}
void main()
{
int nSlot=1; //REPLACE WITH EFU SLOT ID.
int nPerk=1; //Replace with EFU Mimic Check
// Check to see if it's an ITEM being used.
if (GetSpellCastItem() != OBJECT_INVALID) { return; } // End the script if we're an item.

if (nPerk =1)// REPLACE WITH CHECK TO SEE IF THIS IS A MIMIC SELFCASTING OR NOT
{

//Check to see if the spell is in the slot. They'll still be able to spam queues of a forgotten spell, but they will all fail to cast.
if (GetLocalInt(oSelf, "nMimicSlot"+IntToString(nSlot)) == nSpell)
{
MimicCast(oSelf, nSlot);
}
else // This badboy sets the SPELL FAILURE.
  {
  SetModuleOverrideSpellScriptFinished();
  SendMessageToPC(oSelf, "SPELL FAILED. HERP DERP"); //Debug, remove it
}

string sName = StringReplace(Get2DAString("spells", "Label", nSpell),  "_", " ");
}
/*
JUST FOR DEBUG (Stealing spells from self. UnComment this and Comment out the "SafetyCheck" functions in Steal Spell if you want them to do anything.
SetLocalInt(oSelf, "nLastCast", nSpell);
SetLocalInt(oSelf, "nLastMeta", nMeta);
*/
}[/hide]


OnRest:

Super simple. All you need to add is one line. This will clear the stolen spell list.
[hide]
SetLocalString(oPC, "sMimicList", "-");
[/hide]]



[/hide]

Charnelist