Aller au contenu

Photo

Mage Duel system


  • Veuillez vous connecter pour répondre
28 réponses à ce sujet

#26
Baaleos

Baaleos
  • Members
  • 1 329 messages
#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

#27
acomputerdood

acomputerdood
  • Members
  • 219 messages
i really appreciate you posting that code, Baaleos!

i've figured out how most everything works, but i'm still a little confused about a few things. i'm guessing most of my questions stem from you just testing stuff out in the code, but i'll ask just to see if you have an actual reason for some of this:

void StartDuel(object oCaster, object oTarget)
{
SetLocalInt(oCaster,"DUELING",0);
SetLocalInt(oTarget,"DUELING",0);
int iDuelOn = GetLocalInt(oCaster,"DUELING");
if(iDuelOn){ return;}
...
}

this check will always fail, causing nothing to ever happen. i took it out and it works fine.

void Part2(object oCaster,object oTarget)
{
....
AddHenchman(oCaster,oCenter);
...

any reason why the beam intersection creature was added as a henchman? any faction neutral to everyone should be fine, no? again, i took it out and haven't seen any problems.

and yes, there was a LOT of code in there that wasn't used. i cleaned up the necessary functions, refactored and renamed a bit as well. the only major things i added were:

- each "round" of the pseudoloop recalculates which way the middle will travel. that way instead of just comparing spellcraft ranks and having the beam fly straight to the loser, you can add a d20 to the spellcraft each loop so the beam will go back and forth a bit.
- spectators within a certain distance of the battle will stop and watch

my future plans for the system will be:
- both caster and target will be "frozen" or "locked" in place for the battle. right now nothing stops them from running around while beaming each other. would EffectCutsceneParalyze be appropriate for this?
- spectators also run to the ball and try to attack it. i'm guess it's a faction problem.
- i'd like the participants in the battle to not be affected by anything else (spells, being attacked, etc). setting them to plot would work, but i'd like them to be untargettable - is that possible?

anyway, i have a small demo up to illustrate what i've done with Baaleos's system so far. you can direct connect to:

dalakora.com:5122

#28
Baaleos

Baaleos
  • Members
  • 1 329 messages

acomputerdood wrote...

i really appreciate you posting that code, Baaleos!

i've figured out how most everything works, but i'm still a little confused about a few things. i'm guessing most of my questions stem from you just testing stuff out in the code, but i'll ask just to see if you have an actual reason for some of this:

void StartDuel(object oCaster, object oTarget)
{
SetLocalInt(oCaster,"DUELING",0);
SetLocalInt(oTarget,"DUELING",0);
int iDuelOn = GetLocalInt(oCaster,"DUELING");
if(iDuelOn){ return;}
...
}

this check will always fail, causing nothing to ever happen. i took it out and it works fine.

void Part2(object oCaster,object oTarget)
{
....
AddHenchman(oCaster,oCenter);
...

any reason why the beam intersection creature was added as a henchman? any faction neutral to everyone should be fine, no? again, i took it out and haven't seen any problems.

and yes, there was a LOT of code in there that wasn't used. i cleaned up the necessary functions, refactored and renamed a bit as well. the only major things i added were:

- each "round" of the pseudoloop recalculates which way the middle will travel. that way instead of just comparing spellcraft ranks and having the beam fly straight to the loser, you can add a d20 to the spellcraft each loop so the beam will go back and forth a bit.
- spectators within a certain distance of the battle will stop and watch

my future plans for the system will be:
- both caster and target will be "frozen" or "locked" in place for the battle. right now nothing stops them from running around while beaming each other. would EffectCutsceneParalyze be appropriate for this?
- spectators also run to the ball and try to attack it. i'm guess it's a faction problem.
- i'd like the participants in the battle to not be affected by anything else (spells, being attacked, etc). setting them to plot would work, but i'd like them to be untargettable - is that possible?

anyway, i have a small demo up to illustrate what i've done with Baaleos's system so far. you can direct connect to:

dalakora.com:5122


Yeah,
The way I was testing the system, was by using my already functional Incantation system
(the video I posted shows it in action)
The magic missile flies from me, hits a target.
A script then gets run on the caster - but the Target of the spell is set as a local object on the caster - Allowing the Script to access the caster and the target.
The main attraction of this system, is that it uses resman, and each spell is a modular script that I upload via ftp, and then add to the system via database entries, it also provided the means for me to demo/debug the mage duel system without restarting the server.
Main attraction of this system, is that the spells can be developed, uploaded, and implimented without restarting the server.
Magic Related Systems in Worlds of Rhun

During one of my experiments I accidentally set the IS_DUELING int to be 1, and it never went back to 0

The purpose of the IS_DUELING int, is to stop another player coming along, and starting a duel while your in the process of dueling.

AddHenchman(oCaster,oCenter);

Yeah - I had faction issues in my module.
I was using ResMan for most of the development of this system, on my live server.
Meaning I never had to rebuild/compile,reupload and restart any servers.
My creature, was created in a basic module, which didnt have access to the 72+ factions that my main server had.
So - when I used a bioware faction, my creature tended to attack vampire players.
By adding as Henchman, the creature is guaranteed to be friendly to the caster - although, I cant guarantee it being friendly to the target. - For that, would need a true neutral faction, and adjustments made to faction reputation to ensure both target and caster are friendly to the middle creature.

Feel free to modify the system as needed-
To be honest - I only thought the idea up, cause it looked cool in my head.
After testing it, I got a little bit of pride knowing that it was feasible, and still looked cool.

Feel free to build upon it,
look forward to seeing your changes.

#29
acomputerdood

acomputerdood
  • Members
  • 219 messages
here's what i've done with your prototype. i tried to keep the include file generic, and added places where people could add customizations.

#include "x0_i0_position"

int DEBUG = 0;

float fStepIncrement = 3.0;
float fLoopTime = 1.75;
float fSpectatorSize = 30.0;
float fBeamBattleMaxLen = 45.0;
float fBeamBattleStunnedTime = 10.0;
float fTimeElapsed = 0.0;
float fMinDist = 10.0;
float fMaxDist = 100.0;


int GetSpellcasterLevels(object oPC){
    int iLevels;
    iLevels = GetLevelByclass(class_TYPE_BARD, oPC) + GetLevelByclass(class_TYPE_PALEMASTER, oPC) + GetLevelByclass(class_TYPE_SORCERER, oPC) + GetLevelByclass(class_TYPE_WIZARD, oPC);

    return iLevels;
}


int BeamBattleRandomBeam(){
    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;
}


int BeamBattleGetBeam(object oBeamer){
    //however you want to determine a beam

    return BeamBattleRandomBeam();
}


void BeamBattleDoBeams(object oCenter, int iBeam){
    effect eBeam1 = EffectBeam(iBeam, OBJECT_SELF, BODY_NODE_HAND);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBeam1, oCenter, 5.00);
}


// give some other reward
void BeamBattleGetReward(object oWinner, object oLoser){
    //based on level difference between two characters (NOT caster levels)
    int iXPReward = 60 - (10 * (GetHitDice(oWinner) - GetHitDice(oLoser)));
    if (iXPReward < 10)
        iXPReward = 10;
    if (iXPReward >= 100)
        iXPReward = 100;
    GiveXPToCreature(oWinner, iXPReward);

    //custom to dalakora
    object oToken = GetItemPossessedBy(oWinner, "DALA_CONVERTED");
    if(GetIsObjectValid(oToken)){
        int iObsDuelPoints = GetLocalInt(oToken, "OBS_DUEL_POINTS");
        int iLoserLevels = GetSpellcasterLevels(oLoser);
        SetLocalInt(oToken, "OBS_DUEL_POINTS", iObsDuelPoints + iLoserLevels);
    }
}


void BeamBattleExplode(object oCenter, object oLoser, object oWinner){
    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);
    if(GetIsObjectValid(oLoser)){
        SetCommandable(TRUE, oLoser);
        SetCommandable(TRUE, oWinner);
        effect eKnockdown = ExtraordinaryEffect(EffectKnockdown());
        effect eDispell = ExtraordinaryEffect(EffectDispelMagicAll(100));
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eKnockdown, oLoser, 12.0);
        ApplyEffectToObject(DURATION_TYPE_INSTANT, eDispell, oLoser);
    }

    BeamBattleGetReward(oWinner, oLoser);
    DestroyObject(oCenter, 0.25);
}


object BeamBattleCalculateRoundLoser(object oCaster, object oTarget){
    int iCasterScore;
    int iTargetScore;

    //this is where we determine where the beam moves
    int iSpellCraftCaster = GetSkillRank(SKILL_SPELLCRAFT, oCaster, FALSE);
    int iSpellCraftTarget = GetSkillRank(SKILL_SPELLCRAFT, oTarget, FALSE);

//    iCasterScore = d20() + 1;
//    iTargetScore = d20();



    // custom to dalakora
    int iCasterSpellcraft = GetSkillRank(SKILL_SPELLCRAFT, oCaster, FALSE);
    int iTargetSpellcraft = GetSkillRank(SKILL_SPELLCRAFT, oTarget, FALSE);

    int iCasterInt = GetAbilityModifier(ABILITY_INTELLIGENCE, oCaster);
    int iTargetInt = GetAbilityModifier(ABILITY_INTELLIGENCE, oTarget);

    object oToken = GetItemPossessedBy(oCaster, "DALA_CONVERTED");
    int iObsDuelPoints = GetLocalInt(oToken, "OBS_DUEL_POINTS");
    int iCasterBonus = iObsDuelPoints/500;

//    int iTargetBonus = FloatToInt(GetChallengeRating(oTarget)) + 1;

    int iCasterLevels = GetSpellcasterLevels(oCaster);
    int iTargetLevels = GetSpellcasterLevels(oTarget);


    iCasterScore = iCasterSpellcraft + iCasterInt + iCasterBonus + iCasterLevels + d20();
    iTargetScore = iTargetSpellcraft + iTargetInt + iTargetLevels;

    if(DEBUG){
        SendMessageToPC(oCaster, "iCasterSpellcraft: " + IntToString(iCasterSpellcraft));
        SendMessageToPC(oCaster, "iCasterInt: " + IntToString(iCasterInt));
        SendMessageToPC(oCaster, "iCasterBonus: " + IntToString(iCasterBonus));
        SendMessageToPC(oCaster, "iCasterLevels: " + IntToString(iCasterLevels));
        SendMessageToPC(oCaster, "iTargetSpellcraft: " + IntToString(iTargetSpellcraft));
        SendMessageToPC(oCaster, "iTargetInt: " + IntToString(iTargetInt));
//        SendMessageToPC(oCaster, "iTargetBonus: " + IntToString(iTargetBonus));
        SendMessageToPC(oCaster, "iTargetLevels: " + IntToString(iTargetLevels));
        SendMessageToPC(oCaster, IntToString(iCasterScore) + " :  " + IntToString(iTargetScore));
    }

    // end custom
    if(iCasterScore >= iTargetScore){
        return oTarget;
    }else{
        return oCaster;
    }
}


void BeamBattleMoveCenter(object oCaster, object oTarget, object oCenter){
    object oLoser = BeamBattleCalculateRoundLoser(oCaster, oTarget);

    float fStopAt = GetDistanceBetween(oCenter, oLoser) - fStepIncrement;
    AssignCommand(oCenter, ActionForceMoveToObject(oLoser, FALSE, fStopAt, fLoopTime));
}


void BeamBattlePseudoLoop(object oCaster, object oTarget, object oCenter, int iBeam1, int iBeam2){
    float fCasterDist;
    float fTargetDist;

    AssignCommand(oCaster, BeamBattleDoBeams(oCenter, iBeam1));
    AssignCommand(oTarget, BeamBattleDoBeams(oCenter, iBeam2));

    fCasterDist = GetDistanceBetween(OBJECT_SELF, oCaster);
    fTargetDist = GetDistanceBetween(OBJECT_SELF, oTarget);

    fTimeElapsed += fLoopTime;

    int iKill = FALSE;
    if(fCasterDist <= 2.75){
        AssignCommand(oTarget, BeamBattleExplode(oCenter, oCaster, oTarget));
        iKill = TRUE;
    }
    if(fTargetDist <= 2.75){
        AssignCommand(oCaster, BeamBattleExplode(oCenter, oTarget, oCaster));
        iKill = TRUE;
    }
    if(fBeamBattleMaxLen < fTimeElapsed){
        iKill = TRUE;
    }
    if(iKill == TRUE){
        SetCommandable(TRUE, oCaster);
        SetCommandable(TRUE, oTarget);

        SetLocalInt(oCaster, "DUELING", 0);
        SetLocalInt(oTarget, "DUELING", 0);
        DestroyObject(OBJECT_SELF, 0.25);
        return;
    }

    AssignCommand(oCenter, BeamBattleMoveCenter(oCaster, oTarget, oCenter));
    DelayCommand(fLoopTime, BeamBattlePseudoLoop(oCaster, oTarget, oCenter, iBeam1, iBeam2));
}


void BeamBattleDoPseudoLoop(object oCaster, object oTarget, object oCenter){
    int i1, i2;
    i1 = BeamBattleGetBeam(oCaster);
    i2 = BeamBattleGetBeam(oTarget);

    AssignCommand(oCenter, BeamBattlePseudoLoop(oCaster, oTarget, oCenter, i1, i2));
}


object BeamBattleMakeMiddle(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, " ");
    SetImmortal(oCenter, TRUE);
    SetIsTemporaryNeutral(oCaster, oCenter);
    SetIsTemporaryNeutral(oTarget, oCenter);
//    AssignCommand(oCenter, SpeakString("Starting Duel"));

    return oCenter;
}


string BeamBattleGetRandomSpeak(){
    string sReturn = "";

    switch(d6()){
        case 1: sReturn = "By the gods!"; break;
        case 2: sReturn = "Amazing!"; break;
        case 3: sReturn = "Such power to behold!"; break;
        case 4: sReturn = "Look at that!"; break;
        case 5: sReturn = "I'm not worthy!"; break;
        case 6: sReturn = "Aaaaahhhhhhh!"; break;
    }
    return sReturn;
}


int BeamBattleStart(object oCaster, object oTarget){
    if(GetLocalInt(oTarget,"DUELING")){
        SendMessageToPC(oCaster, "Target already engaged in a duel.");
        return -1;
    }
    if(GetLocalInt(oCaster,"DUELING")){
        SendMessageToPC(oCaster, "You are already engaged in a duel.");
        return -1;
    }

    float fDistance = GetDistanceBetween(oCaster, oTarget);
    if(fDistance < fMinDist){
        SendMessageToPC(oCaster, "You are too close to your target.");
        return -1;
    }
    if(fMaxDist < fDistance){
        SendMessageToPC(oCaster, "You are too far from your target.");
        return -1;
    }

    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));

    DelayCommand(0.1, SetCommandable(FALSE, oCaster));
    DelayCommand(0.1, SetCommandable(FALSE, oTarget));
    DelayCommand(fBeamBattleMaxLen, SetCommandable(TRUE, oCaster));
    DelayCommand(fBeamBattleMaxLen, SetCommandable(TRUE, oTarget));

    object oCenter = BeamBattleMakeMiddle(oCaster, oTarget);

    object oSpectator = GetFirstObjectInShape(SHAPE_SPHERE, fSpectatorSize, GetLocation(oCenter), TRUE, OBJECT_TYPE_CREATURE);
    while(GetIsObjectValid(oSpectator)){
        if((oSpectator == oCenter) || (oSpectator == oCaster) || (oSpectator == oTarget)){
        }else{
            AssignCommand(oSpectator, ClearAllActions());
            AssignCommand(oSpectator, SetFacingPoint(GetPosition(oCenter)));
            string sSpeak = BeamBattleGetRandomSpeak();
            AssignCommand(oSpectator, ActionSpeakString(sSpeak));
            DelayCommand(0.1, SetCommandable(FALSE, oSpectator));
            DelayCommand(fBeamBattleStunnedTime, SetCommandable(TRUE, oSpectator));
        }
        oSpectator = GetNextObjectInShape(SHAPE_SPHERE, fSpectatorSize, GetLocation(oCenter));
    }

    BeamBattleDoPseudoLoop(oCaster, oTarget, oCenter);

    return 0; 
}

PS: you'd think that the "code" formatting blocks would understand that spaces are important for code formatting.


basically, you just call the BeamBattleStart() with the two objects.  mine is being called from an onActivateItem.  people will need a center creature, whose resref is "beam_intersec".

Modifié par acomputerdood, 24 août 2012 - 12:26 .