#include "x0_i0_position"
int GetIsSpellHostile(int iSpellID)
{
int i = StringToInt(Get2DAString("spells","HostileSetting",iSpellID));
return i;
}
int HasJustCast(object oTarget)
{
return GetLocalInt(oTarget,"JUST_CAST");
}
object GetLastSpellTarget(object oCaster)
{
return GetLocalObject(oCaster,"LAST_CAST_AT");
}
void gao_ActionCreateObject(string sTemplate, location lLocation, int nDurationType, int nVFX, float fDuration, float fWait, float fLifetime, object oData)
{
object oPlaceable = CreateObject(OBJECT_TYPE_PLACEABLE, sTemplate, lLocation);
if (nDurationType >= 0 && nVFX >= 0) DelayCommand(fWait, ApplyEffectToObject(nDurationType, EffectVisualEffect(nVFX), oPlaceable, fDuration));
if (fLifetime > 0.0) DestroyObject(oPlaceable, fLifetime);
else // if display is permanent, then start storing the objects as local to ease garbage collection later on.
{ // code modified from Ornedan's modification of the original function
int i = GetLocalInt(oData, "storetotal");
AssignCommand(oPlaceable, ActionDoCommand(SetLocalObject(oData, "store" + IntToString(i), oPlaceable)));
SetLocalInt(oData, "storetotal", i+1);
}
}
void PlaceLineFromVectorToVector(string sTemplate, object oArea, vector vOne, vector vTwo, int nFrequency, float fTime, int nDurationType, int nVFX, float fDuration, float fWait, float fLifetime, object oData)
{
int i;
if (nFrequency < 1) nFrequency = 1;
vector vResultant = vTwo - vOne;
vector vUnit = VectorNormalize(vResultant);
float fDelay = fTime/IntToFloat(nFrequency);
float fLength = VectorMagnitude(vResultant);
float fTheta = fLength/IntToFloat(nFrequency); // distance between each node
float fAngle = VectorToAngle(vUnit);
location lPos;
float f;
for (i=0; i<nFrequency; i++)
{
f = IntToFloat(i);
lPos = Location(oArea, vOne + fTheta*f*vUnit, fAngle);
DelayCommand(f*fDelay, gao_ActionCreateObject(sTemplate, lPos, nDurationType, nVFX, fDuration, fWait, fLifetime, oData));
}
}
void SetJustCast(object oCaster, object oTarget)
{
SetLocalObject(oCaster,"LAST_CAST_AT",oTarget);
SetLocalInt(oCaster,"JUST_CAST",1);
DelayCommand(4.00,DeleteLocalInt(oCaster,"JUST_CAST"));
DelayCommand(4.10,DeleteLocalObject(oCaster,"LAST_CAST_AT"));
}
int ShouldTheyDuel(object oCaster, object oTarget, int iSpell)
{
if(!GetIsSpellHostile(iSpell)) { return FALSE; }
SetJustCast(oCaster,oTarget);
if(HasJustCast(oTarget) && GetLastSpellTarget(oTarget)==oCaster)
{
return TRUE;
}
return FALSE;
}
void GroupDestroyObject(object oData, float fDelay=0.0f, float fOvertime=3.0f, int bReverseOrder=FALSE)
{
int i;
int nTotal = GetLocalInt(oData, "storetotal");
if (nTotal < 1) return;
float fBreak = fOvertime/IntToFloat(nTotal);
if (bReverseOrder)
{
int j = 0;
for (i=nTotal-1; i>-1; i--)
{
DelayCommand(fDelay + fBreak*IntToFloat(j), DestroyObject(GetLocalObject(oData, "store" + IntToString(i))));
j++;
}
}
else
{
for (i=0; i<nTotal; i++)
{
DelayCommand(fDelay + fBreak*IntToFloat(i), DestroyObject(GetLocalObject(oData, "store" + IntToString(i))));
}
}
if(GetObjectType(oData)!=OBJECT_TYPE_CREATURE)
{
DestroyObject(oData, fDelay + fOvertime + 0.5);
}
}
void ApplyPriori(int iNode,object oCaster)
{
effect eBeam = EffectBeam(VFX_BEAM_ODD,OBJECT_SELF,BODY_NODE_HAND);
effect eStart = EffectVisualEffect(2155);
object oNode = GetLocalObject(oCaster,"store"+IntToString(iNode));
if(oNode == OBJECT_INVALID)
{
SpeakString("oNode = Object_invalid");
return;
}
oNode = CreateObject(OBJECT_TYPE_PLACEABLE,"invisobj",GetLocation(oNode),FALSE,GetTag(oNode)+"_b");
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eBeam,oNode,1.55);
if(OBJECT_SELF == oCaster)
{
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eStart,oNode,1.55);
}
}
void UpdateDuel(object oCaster,object oTarget, int iTotalNodes, int iCurrent)
{
//object CurrentNode = GetLocalObject(oCaster,"CURRENT_NODE");
//Smaller = Caster = Losing
//Bigger = Target = Losing
int iSpellCraftCaster = GetSkillRank(SKILL_SPELLCRAFT,oCaster,FALSE);
int iSpellCraftTarget = GetSkillRank(SKILL_SPELLCRAFT,oTarget,FALSE);
int iNext = 0;
if(iSpellCraftCaster >= iSpellCraftTarget)
{
//Caster Wins
AssignCommand(oCaster,ActionDoCommand(ApplyPriori(iCurrent+1,oCaster)));
AssignCommand(oTarget,ActionDoCommand(ApplyPriori(iCurrent+1,oCaster)));
iNext = iCurrent+1;
}else
{
//Caster Loses
AssignCommand(oCaster,ActionDoCommand(ApplyPriori(iCurrent-1,oCaster)));
AssignCommand(oTarget,ActionDoCommand(ApplyPriori(iCurrent-1,oCaster)));
iNext = iCurrent-1;
}
if(iNext <= 1)
{
// Caster Lost
AssignCommand(oCaster,SpeakString("Caster Lost!!"));
DeleteLocalInt(oCaster,"DUELING");
DeleteLocalInt(oTarget,"DUELING");
GroupDestroyObject(oCaster, 1.0,1.0, FALSE);
DeleteLocalInt(oCaster,"storedtotal");
return;
}
if(iNext >= iTotalNodes)
{
// Caster Lost
AssignCommand(oCaster,SpeakString("Caster Won!!"));
DeleteLocalInt(oCaster,"DUELING");
DeleteLocalInt(oTarget,"DUELING");
GroupDestroyObject(oCaster, 1.0,1.0, FALSE);
DeleteLocalInt(oCaster,"storedtotal");
return;
}
DelayCommand(0.75,UpdateDuel(oCaster,oTarget,iTotalNodes,iNext));
}
void GroupExecuteScript(string sScript, object oData, float fOvertime=3.0f, int bReverseOrder=FALSE)
{
int i;
int nTotal = GetLocalInt(oData, "storetotal");
if (nTotal < 1) return;
float fBreak = fOvertime/IntToFloat(nTotal);
if (bReverseOrder)
{
int j = 0;
for (i=nTotal-1; i>-1; i--)
{
DelayCommand(fBreak*IntToFloat(j), ExecuteScript(sScript, GetLocalObject(oData, "store" + IntToString(i))));
j++;
}
}
else
{
for (i=0; i<nTotal; i++)
{
DelayCommand(fBreak*IntToFloat(i), ExecuteScript(sScript, GetLocalObject(oData, "store" + IntToString(i))));
}
}
}
int RandomBeam()
{
int iReturn = 0;
switch(d6(1))
{
case 1: iReturn = VFX_BEAM_SILENT_COLD;break;
case 2: iReturn = VFX_BEAM_SILENT_EVIL;break;
case 3: iReturn = VFX_BEAM_SILENT_FIRE;break;
case 4: iReturn = VFX_BEAM_SILENT_HOLY;break;
case 5: iReturn = VFX_BEAM_SILENT_LIGHTNING;break;
case 6: iReturn = VFX_BEAM_SILENT_MIND;break;
}
return iReturn;
}
void DuelPart2a(object oCaster, object oTarget)
{
//GroupExecuteScript("default", oCaster, 5.00, FALSE);
AssignCommand(oCaster,SpeakString("Starting Duel Part 2 Function"));
int iTotalPoints = GetLocalInt(oCaster,"storetotal");
int iMid = iTotalPoints/2;
ApplyPriori(iMid,oCaster);
AssignCommand(oCaster,SpeakString("Total Points:"+IntToString(iTotalPoints)));
AssignCommand(oCaster,SpeakString("Mid Point:"+IntToString(iMid)));
//object CurrentNode = GetLocalObject(oCaster,"store"+IntToString(iMid));
//SetLocalObject(oCaster,"CURRENT_NODE",CurrentNode);
UpdateDuel(oCaster,oTarget, iTotalPoints, iMid);
}
void DoBeams(object oCenter,int iBeam)
{
effect eBeam1 = EffectBeam(iBeam,OBJECT_SELF,BODY_NODE_HAND);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eBeam1,oCenter,5.00);
}
void DuelPart2(object oCaster, object oTarget, object oCenter)
{
int iSpellCraftCaster = GetSkillRank(SKILL_SPELLCRAFT,oCaster,FALSE);
int iSpellCraftTarget = GetSkillRank(SKILL_SPELLCRAFT,oTarget,FALSE);
int iNext = 0;
if(iSpellCraftCaster >= iSpellCraftTarget)
{
AssignCommand(oCenter,ActionForceFollowObject(oTarget,0.75));
}
else
{
AssignCommand(oCenter,ActionForceFollowObject(oTarget,0.75));
}
}
void Explode(object oCenter,object oLoser)
{
effect e = EffectVisualEffect(VFX_FNF_MYSTICAL_EXPLOSION);
effect eDamage = EffectDamage(d12(3),DAMAGE_TYPE_MAGICAL,DAMAGE_POWER_ENERGY);
ApplyEffectAtLocation(DURATION_TYPE_INSTANT,e,GetLocation(oCenter));
ApplyEffectToObject(DURATION_TYPE_INSTANT,eDamage,oLoser);
DestroyObject(oCenter,0.25);
}
void PseudoLoop(object oCaster, object oTarget, object oCenter, int iBeam1, int iBeam2)
{
float fCasterDist, fTargetDist;
AssignCommand(oCaster,DoBeams(oCenter,iBeam1));
AssignCommand(oTarget,DoBeams(oCenter,iBeam2));
fCasterDist = GetDistanceBetween(OBJECT_SELF,oCaster);
fTargetDist = GetDistanceBetween(OBJECT_SELF,oTarget);
int iKill = FALSE;
if(fCasterDist <= 2.75)
{
SetLocalInt(oCaster,"DUELING",0);
SetLocalInt(oTarget,"DUELING",0);
AssignCommand(oTarget,Explode(oCenter,oCaster));
iKill = TRUE;
}
if(fTargetDist <= 2.75)
{
SetLocalInt(oCaster,"DUELING",0);
SetLocalInt(oTarget,"DUELING",0);
AssignCommand(oCaster,Explode(oCenter,oTarget));
iKill = TRUE;
}
if(iKill == TRUE)
{
DestroyObject(OBJECT_SELF,0.25);
return;
}
DelayCommand(1.75,PseudoLoop(oCaster,oTarget,oCenter,iBeam1,iBeam2));
}
void Part2(object oCaster,object oTarget)
{
vector v1 = GetPosition(oCaster);
vector v2 = GetPosition(oTarget);
float fDist = GetDistanceBetween(oCaster,oTarget);
location l = GenerateNewLocation(oCaster, fDist/2, GetFacing(oCaster), GetFacing(oCaster));
object oCenter = CreateObject(OBJECT_TYPE_CREATURE,"beam_intersec",l,FALSE,"duel_center");
effect eStart = EffectVisualEffect(2155);
effect eStart2 = EffectCutsceneGhost();
effect eSlow = EffectSlow();
ApplyEffectToObject(DURATION_TYPE_PERMANENT,eSlow,oCenter);
ApplyEffectToObject(DURATION_TYPE_PERMANENT,eStart2,oCenter);
ApplyEffectToObject(DURATION_TYPE_PERMANENT,eStart,oCenter);
SetName(oCenter,"Energy Ball");
SetImmortal(oCenter,TRUE);
AddHenchman(oCaster,oCenter);
SetIsTemporaryNeutral(oCaster,oCenter);
SetIsTemporaryNeutral(oTarget,oCenter);
AssignCommand(oCenter,SpeakString("Starting Duel"));
int i1, i2;
i1 = RandomBeam();
i2 = RandomBeam();
AssignCommand(oCenter,PseudoLoop(oCaster,oTarget,oCenter,i1,i2));
DelayCommand(1.5,DuelPart2(oCaster,oTarget,oCenter));
}
void StartDuel(object oCaster, object oTarget)
{
SetLocalInt(oCaster,"DUELING",0);
SetLocalInt(oTarget,"DUELING",0);
int iDuelOn = GetLocalInt(oCaster,"DUELING");
if(iDuelOn){ return;}
SetLocalInt(oCaster,"DUELING",1);
SetLocalInt(oTarget,"DUELING",1);
//Place the duel points
vector v1 = GetPosition(oCaster);
vector v2 = GetPosition(oTarget);
AssignCommand(oCaster,SetFacingPoint(v2));
AssignCommand(oTarget,SetFacingPoint(v1));
AssignCommand(oCaster,ActionDoCommand(Part2(oCaster,oTarget)));
}
As promissed- Note - this was just for personal use - so there is alot of non-sensical coding here,
Just follow the flow - start with
'StartDuel()
and follow the execution.
I tried multiple methods prior to using an invisible creature, so some of the code relates to those previous methods - (the nodes etc)
you will need to create your invisibile creature still, and slot its resref into this include file