[RELEASE] More accurate skill handling

Welcome in the osRose emulator Project.

Moderators: osRose dev team, ospRose dev team, osiRose dev team, Moderators

[RELEASE] More accurate skill handling

Postby cive on Tue Sep 06, 2016 1:27 pm

Hi guys, some time ago I asked some questions about skill handling in the latest Osrose Rev and I found out that it was actually a mess. This is an attempt to clean things up. Do note that it is still a work in progress and it might not be perfectly polished just yet.

Important note: Especially the merged cases in the reworked formula might not work for a server that is NOT REV2 or higher (ie. Ktrose/OspRose/OsIrose) because the list_skill.stb values vary from our current client)


This is basically a summary post that is going to show you how to make fights in your server more balanced by adjusting the way skills work. The current code is quite a mess and there is a lot of stuff that has just been carelessly copied from the normal attack formula. I only cleaned this up with the help of PY and added a few tweaks so that:

    -Skillpower is actually split between magical damage and normal damage
    -Skillpower actually takes defense and magical defense into account
    -Skills can actually miss, which wasn't the case with the current system
    -By using tiny tweaks, battles get a lot more balanced PvP-wise

All this is handled in your battle.cpp, so open that up and find
Please note that your values for ie skillpower formula may vary a little, I'm not using a clean source code for the example
snippet from below CCharacter::UseAtkSkill

  1.  
  2.  
  3.  //Skill power calculations LMA/Tomiz : New Way
  4.     long int skillpower = (skill->atkpower*0.5) + (Stats->Attack_Power*0.5); // 60% skillpower, 20% attackpower
  5.  
  6.     //if(GServer->ServerDebug)
  7.        // Log( MSG_INFO, "Skillpower = %i (%i + %i)",skillpower,skill->atkpower,Stats->Attack_Power);
  8.     float levelmult = (float) Stats->Level / Enemy->Stats->Level;
  9.  
  10.     if(levelmult > 2)levelmult = 2; //cap level multiplier at 2
  11.  
  12.     float atkdefmult = 0;
  13.     float attack = 0;
  14.     float constant = 9;
  15.  
  16.     unsigned int skill_hitvalue = (unsigned int)floor(Stats->Accuracy * 50 / Enemy->Stats->Dodge);
  17.     if(IsMonster( ) && !IsSummon())
  18.     skill_hitvalue = (unsigned int)floor (Stats->Accuracy) * 55/ (Enemy->Stats->Dodge*1.5);
  19.     if(skill_hitvalue>100) skill_hitvalue = 99;
  20.     switch(skill->formula)//Magical Or Weapon Type Skill?
  21.     {
  22.         case 0://Skill Mental Storm
  23.         {
  24.             atkdefmult = 0;
  25.         }
  26.         break;
  27.         case 1://Weapon type dmg
  28.         {
  29.             atkdefmult = (float) Stats->Attack_Power / (Enemy->Stats->Magic_Defense+(Enemy->Stats->Defense));
  30.             skillpower += GetSen();
  31.             if(GServer->RandNumber( 30, 100 )>skill_hitvalue) atkdefmult /= 2; // Miss results in damage cut in half.
  32.         }
  33.         break;
  34.         case 2://Magical type dmg
  35.         {
  36.             atkdefmult = (float) (Stats->Attack_Power * 0.90) / (Enemy->Stats->Magic_Defense+Enemy->Stats->Defense); // -10% damage for OP clerics
  37.             skillpower += GetInt();
  38.             if(GServer->RandNumber( 30, 100 )>skill_hitvalue) atkdefmult /= 2; // Miss results in damage cut in half.
  39.         }
  40.         break;
  41.         case 3://Weapon type dmg
  42.         {
  43.             atkdefmult = (float) Stats->Attack_Power / (Enemy->Stats->Magic_Defense+Enemy->Stats->Defense);
  44.             skillpower += GetSen();
  45.             if(GServer->RandNumber( 30, 100 )>skill_hitvalue) atkdefmult = 0; // Complete Miss.
  46.         }
  47.         break;
  48.         case 4://Magical type dmg
  49.         {
  50.             atkdefmult = (float) Stats->Attack_Power / (Enemy->Stats->Magic_Defense+Enemy->Stats->Defense);
  51.             skillpower += GetInt();
  52.             if(GServer->RandNumber( 30, 100 )>skill_hitvalue) atkdefmult = 0; // Complete Miss.
  53.         }
  54.         break;
  55.         case 6://Dual Scratch
  56.         {
  57.             atkdefmult = 1;
  58.         }
  59.         break;
  60.         default:
  61.         {
  62.             atkdefmult = 1;
  63.         }
  64.         break;
  65.  
  66.  
  67.  
  68.  
  69.     }
  70.  


and go ahead and replace that with

  1.  
  2. //Skill power calculations LMA/Tomiz : New Way
  3. long int skillpower = (skill->atkpower*0.5) + (Stats->Attack_Power*0.5) / 2 ;
  4.     float skilldefense = 0  ;
  5.     switch(skill->formula)//Magical Or Weapon Type Skill?
  6.  
  7.     {
  8.         case 0://Skill Mental Storm
  9.         {
  10.         skilldefense = (float) Stats->Attack_Power / (Enemy->Stats->Magic_Defense * 2.5) ;
  11.         }
  12.         break;
  13.         case 1: case 3: //Weapon type dmg
  14.         {
  15.  
  16.         skilldefense = (float) Stats->Attack_Power / (Enemy->Stats->Defense * 1.5) ;
  17.  
  18.         }
  19.         break;
  20.         case 2: case 4: //Magical type dmg
  21.         {
  22.  
  23.             skillpower += GetInt();
  24.             skilldefense = (float) Stats->Attack_Power / (Enemy->Stats->Magic_Defense * 2.5) ;
  25.         }
  26.         break;
  27.         case 6://Dual Scratch
  28.         {
  29.          skilldefense = (float) Stats->Attack_Power / (Enemy->Stats->Defense * 1.5) ;
  30.         }
  31.         break;
  32.         default:
  33.         {
  34.         skilldefense = 1 ;
  35.         }
  36.         break;
  37.  
  38.  
  39.     }
  40.  
  41.     if (skilldefense > 1) skilldefense = 1 ;
  42.     skillpower*= skilldefense ;
  43.  


Then, in order to implement the new hit/miss system for skills, find

  1. Enemy->Stats->HP -=  (long long) skillpower;


and right above it, add

  1. //new skilldodge system
  2.     float hitormis = (float)floor(Stats->Accury * 85 / Enemy->Stats->Dodge);
  3.     if(hitormis >100) hitormis = 100;
  4.     if(GServer->RandNumber( 0, 100 )>hitormis) skillpower = 0;


It is quite a basic dodge system as you can see, but it works just fine. The only thing to note is that reliable skills are not yet supported by this code (shouldn't be too hard to code though). I might add this in a later update. the * 85 behind accury is the sweetspot for me but feel free to change this to whatever value you desire (higher is less misses, lower is more misses)

So the big changes here are:

- I merged 4 cases into 2 cases, for normal skills we either do a weapon attack or a magic attack (this is declared in LIST_SKILL.STB).
When a player uses a weapon attack:
  1. skilldefense = (float) Stats->Attack_Power / (Enemy->Stats->Defense * 1.5) ;

When a player uses a magical attack:
  1. skilldefense = (float) Stats->Attack_Power / (Enemy->Stats->Magic_Defense * 2.5) ;


-I removed a bonus based on SEN stat for weapon attacks
-I removed increased damage for when players are levels apart
-I adjusted the base skillpower formula so that it scales 50/50 on respectively skilldamage & attackpower
-Added a new dodge system
-Scrapped at least three variables that came from normal attacks but had zero use in the code beside from just being declared
-I made sure that defense and magical defense were taken into account as seperate things. Note that magical defense is multiplied by 2.5 rather than 1.5 out of balancing motives, feel free to play around with the values.
-I left the int bonus in place for magical skills because it made sense to me.

So thats it, huge thanks to PurpleYouko who helped me understand everything and pointed out to me that the system needed some work. Would love to hear your feedback and tweaks so that we can continue working on this or other things.

Have fun :D







All the work originated from the post right here, take a look if you're interested in detailed changes.
viewtopic.php?f=18&t=5835
cive
Jelly Bean
Jelly Bean
 
Posts: 11
Joined: Thu Nov 07, 2013 8:15 pm

Re: [RELEASE] More accurate skill handling

Postby PurpleYouko on Tue Sep 06, 2016 2:41 pm

Also note that if you plan to use these formulas in project 137 worldserver they should work fine with one minor modifications

You need to use case 1 and 4 for normal attacks and case 2 an 5 for magical.
Case 3 is used for one GM skill called "kill (anti-crime)" skill number 3216 and for one monster skill number 2985.

I have no idea as yet what these skills do or even if they are used ever. It will need to be investigated further before coding anything for case 3 so just leave case 3 blank for now.
Need to lookup information on NARose items, skills, quests?
Now featuring a newly completed skill tree for all classes
Formatting fixed for different resolutions
Image

"A Gazelle is nothing but a giraffe plotted logarithmicaly"
User avatar
PurpleYouko
Rose Guru
Rose Guru
 
Posts: 4595
Joined: Fri Aug 10, 2007 2:05 pm


Return to Support - OsRose Emulator

Who is online

Users browsing this forum: No registered users and 3 guests