Author Topic: Weapon usury system with OnHitCastSpell Unique Power(OnHit)  (Read 348 times)

Legacy_Kato -

  • Hero Member
  • *****
  • Posts: 747
  • Karma: +0/-0


               Hey there, 

I'm currently writing a weapon usury system into wich the weapons lose "health" upon hitting anything. OnHitCastSpell works fine on the weapons, updating a "health" int var on the weapon on each hit, yet I only tested in SP environment. In order to best avoid lag, I'm wondering what would be the best approach with the coding of such a system, knowing that:

- Each different weapon material has its own health, and the weapons degrade by 1 on each hit. Currently, the material is stored as an int variable on the weapon, instead of an item property(ItemPropertyMaterial()), since otherwise I would have to increase the max allowed properties, and I felt like a property might be heavier than a simple int. Am I wrong?

- The weapon's name is modified on each hit, in order to display its updated "health" in brackets aside the name. the format is: Material + " " + Weapon's Name + (Updated Health). Would this be too heavy?

- I would like to use some colored strings for material and health, same question as above...

Of course, I have searched the vault for a similar system but found none, so, many many thanks to anyone who might answer these questions. '<img'>
               
               

               


                     Modifié par Kato_Yang, 04 juin 2011 - 07:48 .
                     
                  


            

Legacy_Xardex

  • Sr. Member
  • ****
  • Posts: 414
  • Karma: +0/-0
Weapon usury system with OnHitCastSpell Unique Power(OnHit)
« Reply #1 on: June 04, 2011, 08:59:57 pm »


               It shouldn't be any more heavier then any other On Hit Cast Spell property. You shouldn't have problems unless you create an insanely long script or big loops, especially if its only for PC's.

Colored strings are created with certain symbols in the string before the colored part, so no, it wont cost any performance.
               
               

               


                     Modifié par Xardex, 04 juin 2011 - 08:01 .
                     
                  


            

Legacy_Kato -

  • Hero Member
  • *****
  • Posts: 747
  • Karma: +0/-0
Weapon usury system with OnHitCastSpell Unique Power(OnHit)
« Reply #2 on: June 05, 2011, 03:22:38 am »


               Thank you, Xardex, these are good news, indeed. '<img'>
               
               

               


                     Modifié par Kato_Yang, 12 juin 2011 - 07:56 .
                     
                  


            

Legacy_Kato -

  • Hero Member
  • *****
  • Posts: 747
  • Karma: +0/-0
Weapon usury system with OnHitCastSpell Unique Power(OnHit)
« Reply #3 on: June 12, 2011, 08:07:25 pm »


               By the way, could any of you wise guys tell me what's wrong with this custom x2_s3_onhitcast script please? The code works most of the time, only, and I know it's far from being optimized anyway. I wished to avoid using the OR(||) operator and any include, to keep the script small and fast, yet I find the whole thing rather ugly...

void main()
{
   object oItem = GetSpellCastItem(); // The item casting triggering this spellscript
   int nType = GetBaseItemType(oItem);
   if(nType == BASE_ITEM_ARMOR) return; //Only melee weapons and gloves degrade for now
   if(nType == BASE_ITEM_TOWERSHIELD) return;
   if(nType == BASE_ITEM_LARGESHIELD) return;
   if(nType == BASE_ITEM_SMALLSHIELD) return;
   int nMat = GetLocalInt(oItem, "Material");
   if(nMat == 100000) return; //Jeweled weapons do not degrade
   if(GetTag(oItem) == "ITM_DRAGGAUNTLET") return; //Same for dragon gauntlets
   int nHealth = GetLocalInt(oItem, "Health");
   if(nHealth == 0) //Destroy oItem if health goes lower than 0
   {
   DestroyObject(oItem);
   return;
   }
   SetLocalInt(oItem, "Health", nHealth-1); //Decrement weapon's health
   int nMax = (nHealth * 10 / nMat)+1; // max "sharpness" allowed according to health(each 10% = +1)
   int ipMagn, ipDur;
   itemproperty ip = GetFirstItemProperty(oItem);
   while(GetIsItemPropertyValid(ip))
   {
      int nType = GetItemPropertyType(ip);
      if(nType == ITEM_PROPERTY_ATTACK_BONUS)
      {
         ipMagn = GetItemPropertyCostTableValue(ip);
         ipDur = GetItemPropertyDurationType(ip);
         if(ipMagn > nMax)
         {
            RemoveItemProperty(oItem, ip);
            AddItemProperty(ipDur, ItemPropertyAttackBonus(nMax), oItem);
         }
      }
      else if(nType == ITEM_PROPERTY_ENHANCEMENT_BONUS)
      {
         ipMagn = GetItemPropertyCostTableValue(ip);
         ipDur = GetItemPropertyDurationType(ip);
         if(ipMagn > nMax)
         {
            RemoveItemProperty(oItem, ip);
            AddItemProperty(ipDur, ItemPropertyEnhancementBonus(nMax), oItem);
         }
      }
   ip = GetNextItemProperty(oItem);
   }
  string sMat = GetLocalString(oItem, "MatName");
  SetName(oItem, sMat + " " + GetName(oItem, TRUE) + "(" + IntToString(nHealth) + ")");

  /* Commented out to avoid a function call for the code above
  if (GetIsObjectValid(oItem))
  {
    // * Generic Item Script Execution Code
    // * If MODULE_SWITCH_EXECUTE_TAGBASED_SCRIPTS is set to TRUE on the module,
    // * it will execute a script that has the same name as the item's tag
    // * inside this script you can manage scripts for all events by checking against
    // * GetUserDefinedItemEventNumber(). See x2_it_example.nss
    if (GetModuleSwitchValue(MODULE_SWITCH_ENABLE_TAGBASED_SCRIPTS) == TRUE)
    {
       SetUserDefinedItemEventNumber(X2_ITEM_EVENT_ONHITCAST);
       int nRet =   ExecuteScriptAndReturnInt(GetUserDefinedItemEventScriptName(oItem),OBJECT_SELF);
       if (nRet == X2_EXECUTE_SCRIPT_END)
       {
          return;
       }
    }
  }
  */
}

You have my humble thanks, dear reader.

Kato
               
               

               


                     Modifié par Kato_Yang, 12 juin 2011 - 08:06 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Weapon usury system with OnHitCastSpell Unique Power(OnHit)
« Reply #4 on: June 12, 2011, 10:31:07 pm »


               It would help if we knew what you mean by "works most of the time." 

Does this mean that the script is always firing, but not always working right? 
or
That the script is not always firing?

If the script is firing but not working right, it could be that the Iprop is not removed untill after the script is finished running but the new prop is being added before the script is finished. 

If it is that the script is not always running.  It could be that the weapon has more then one OnHit prop on it.  Only one OnHit prop will work on a weapon per hit.  Sometimes it seems pretty consistant as to the one that will hit. At other times it seems pretty random. 

So if you have a weapon with say OnHit Poison and your custom OnHit cast spell.  Only one of them will take effect for any given hit.

I have even noticed the OnHit Cast Spell negating vamperic regen at times.


@ OR operator
I also do not see your logic in not using the logical OR operater.  Not using it will not make your code any faster. 

When an 'If Statment' is made up of a bunch of chained OR's (||) it does not mean that everything in the expression will  be evaulted. 

take the following code.  

int A=5, 
int B=6;
int C=10; 
If ( A>B || C>B || A==C....and several more ||'s)  return;

Since the above expression in the if statment is a bunch of logical Or's chained together, the compiler is smart enough to know that as soon as it finds one that is true the entire expression is true.   So in effect it will first check if A>B find it FALSE and continue the checks. The Next check of C>B will be found to be TRUE.  At this point the entire expression is TRUE reguardless of the outcome of the rest of the checks. The compiled code will at this point skip porcessing the rest of the expression, for it has no need to, the entire expression is TRUE reguardless. 

It works about the same way with linked AND operators, the differance is it knows the answer once if gets is first FALSE result.  Once that happens the entire expression has to be false.  

@include files.
The Idea that Include file will always slow down your code is also a missconception. 
As long as the Include does not declair any vars that are not constants, outside of the functions that it contains,  It will not slow down your code in the least.  
               
               

               


                     Modifié par Lightfoot8, 12 juin 2011 - 09:33 .
                     
                  


            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Weapon usury system with OnHitCastSpell Unique Power(OnHit)
« Reply #5 on: June 12, 2011, 10:36:37 pm »


               Remember that only one onhit will work at a time, on a weapon. So, if you've cast a spell that adds one, only that spell, or the use script will fire (usury does not mean what you think '<img'> ). The way around this is to integrate all onhits into a single script, which is indeed as complicated as it sounds.

Funky
               
               

               
            

Legacy_ShadowM

  • Hero Member
  • *****
  • Posts: 1373
  • Karma: +0/-0
Weapon usury system with OnHitCastSpell Unique Power(OnHit)
« Reply #6 on: June 12, 2011, 11:10:32 pm »


               You might want to consider reversing how you do it, and put a function OnDamaged or OnPhyicallyAttacked of the monsters to find the weapon and change it that way. Just a thought I sure there downsides to it.
               
               

               


                     Modifié par ShadowM, 12 juin 2011 - 10:10 .
                     
                  


            

Legacy_Kato -

  • Hero Member
  • *****
  • Posts: 747
  • Karma: +0/-0
Weapon usury system with OnHitCastSpell Unique Power(OnHit)
« Reply #7 on: June 13, 2011, 01:34:58 am »


               Okay, thanks everyone. Considering the infos you all gave me, it looks like the problem came from more than 1 OnHit prop on the weapon(sorry about my terminology, Funky, I should probably have said degradation instead of usury, my english is so so). To solve this, I re-wrote all spells adding such a prop(darkfire etc...) to instead add a equivalent dynamic damage property, and it seems to work fine, now. Still, I'm shocked to learn that several if() are not faster than several OR in same if(), having read this more than once, thank you Lightfoot(the info about includes is much appreciated too, a misconception of my own...).

Hey ShadowM, your suggestion sounds cool, but what happens if two players are fighting each other?

Anyway, it looks like the problem is solved, so thanks a lot guys!
               
               

               
            

Legacy_ShadowM

  • Hero Member
  • *****
  • Posts: 1373
  • Karma: +0/-0
Weapon usury system with OnHitCastSpell Unique Power(OnHit)
« Reply #8 on: June 13, 2011, 02:26:32 am »


               Yeah that true, then you have to use onhit uniquepower and you back to the same thing basically.