CONTROL 79 Posted February 7 Share Posted February 7 (edited) hi, today when i was trying my new element bonuses system i noticed that the elements cannot be with another race flag like RACE_FLAG_DEVIL for example so i went to the jungles of my source and i discoverd a little crime in battle.cpp if (pkVictim->IsRaceFlag(RACE_FLAG_ANIMAL)) iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ANIMAL)) / 100; else if (pkVictim->IsRaceFlag(RACE_FLAG_UNDEAD)) iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_UNDEAD)) / 100; else if (pkVictim->IsRaceFlag(RACE_FLAG_DEVIL)) iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_DEVIL)) / 100; else if (pkVictim->IsRaceFlag(RACE_FLAG_HUMAN)) iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_HUMAN)) / 100; else if (pkVictim->IsRaceFlag(RACE_FLAG_ORC)) iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ORC)) / 100; else if (pkVictim->IsRaceFlag(RACE_FLAG_MILGYO)) iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_MILGYO)) / 100; else if (pkVictim->IsRaceFlag(RACE_FLAG_INSECT)) iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_INSECT)) / 100; else if (pkVictim->IsRaceFlag(RACE_FLAG_FIRE)) iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_FIRE)) / 100; else if (pkVictim->IsRaceFlag(RACE_FLAG_ICE)) iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ICE)) / 100; else if (pkVictim->IsRaceFlag(RACE_FLAG_DESERT)) iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_DESERT)) / 100; else if (pkVictim->IsRaceFlag(RACE_FLAG_TREE)) iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_TREE)) / 100; the redundancy in here is not just preventing the flags to be together it's affecting the performance too.. so i've changed the entire thing in order to make it less messy, and more readable & performance friendly (considering that this is one of the functions that should be triggered with each attack !!) Spoiler struct RacePointPair { int raceFlag; uint8_t pointAttribute; }; RacePointPair racePointTable[] = { { RACE_FLAG_ANIMAL, POINT_ATTBONUS_ANIMAL }, { RACE_FLAG_UNDEAD, POINT_ATTBONUS_UNDEAD }, { RACE_FLAG_DEVIL, POINT_ATTBONUS_DEVIL }, { RACE_FLAG_HUMAN, POINT_ATTBONUS_HUMAN }, { RACE_FLAG_ORC, POINT_ATTBONUS_ORC }, { RACE_FLAG_MILGYO, POINT_ATTBONUS_MILGYO }, { RACE_FLAG_INSECT, POINT_ATTBONUS_INSECT }, { RACE_FLAG_FIRE, POINT_ATTBONUS_FIRE }, { RACE_FLAG_ICE, POINT_ATTBONUS_ICE }, { RACE_FLAG_DESERT, POINT_ATTBONUS_DESERT }, { RACE_FLAG_TREE, POINT_ATTBONUS_TREE } }; for (uint8_t i = 0; i < _countof(racePointTable); i++) { if (pkVictim->IsRaceFlag(racePointTable[i].raceFlag)) iAtk += (iAtk * pkAttacker->GetPoint(racePointTable[i].pointAttribute)) / 100; } you can adjust it based on your bonuses and all .. Thx Edited February 7 by CONTROL 1 Link to comment Share on other sites More sharing options...
Contributor Amun 1906 Posted February 9 Contributor Share Posted February 9 Pretty good, but this shouldn't be in support, G. Also, you should break after you find your race, otherwise you'll loop over the rest for no reason(unless you have multiple races for the same mob). The performance part makes no difference in release, since the compiler is smart enough to optimize the fuck out of them, but it does a bit of a difference in debug. Here's some profiles(in debug, with optimizations disabled) for 10 million iterations: Exact copy/paste of your code with raceFlag(for both) = RACE_FLAG_ANIMAL(first match) : [BRANCHES] Execution x 10000000 took [29.618000] [ARRAY] Execution x 10000000 took [283.952606] Exact copy/paste of your code with raceFlag(for both) = RACE_FLAG_TREE(last match) [BRANCHES] Execution x 10000000 took [287.451385] [ARRAY] Execution x 10000000 took [345.841217] With raceFlag(for both) = RACE_FLAG_ANIMAL(first match) + break after match: [BRANCHES] Execution x 10000000 took [29.319500] [ARRAY] Execution x 10000000 took [47.762199] With raceFlag(for both) = RACE_FLAG_TREE(last match) + break after match(useless here): [BRANCHES] Execution x 10000000 took [295.321716] [ARRAY] Execution x 10000000 took [282.486206] With raceFlag(for both) = RACE_FLAG_ANIMAL(first match) + break after match + static array: [BRANCHES] Execution x 10000000 took [29.350700] [ARRAY] Execution x 10000000 took [32.444702] With raceFlag(for both) = RACE_FLAG_TREE(first match) + break after match(useless here) + static array: [BRANCHES] Execution x 10000000 took [298.241302] [ARRAY] Execution x 10000000 took [272.202393] Using a switch with raceFlag = RACE_FLAG_ANIMAL(first match) [BRANCHES] Execution x 10000000 took [31.487902] [ARRAY] Execution x 10000000 took [32.890202] [SWITCH] Execution x 10000000 took [31.182301] Using a switch with raceFlag = RACE_FLAG_TREE(last match). Something like RACE_FLAG_ATT_ELEC(which isn't checked) brings the switch down to 16ms. [BRANCHES] Execution x 10000000 took [289.458801] [ARRAY] Execution x 10000000 took [271.130280] [SWITCH] Execution x 10000000 took [46.620998] Yeah, I'm bored, how did you know? Take these with a grain of salt btw, the numbers are influenced by what's going on on my pc at the time of running the program, but I guess they're good for a quick "lemme have a look at this shit". 1 1 1 Link to comment Share on other sites More sharing options...
CONTROL 79 Posted February 9 Author Share Posted February 9 1 hour ago, Amun said: Pretty good, but this shouldn't be in support, G. Also, you should break after you find your race, otherwise you'll loop over the rest for no reason(unless you have multiple races for the same mob). The performance part makes no difference in release, since the compiler is smart enough to optimize the fuck out of them, but it does a bit of a difference in debug. Here's some profiles(in debug, with optimizations disabled) for 10 million iterations: Exact copy/paste of your code with raceFlag(for both) = RACE_FLAG_ANIMAL(first match) : [BRANCHES] Execution x 10000000 took [29.618000] [ARRAY] Execution x 10000000 took [283.952606] Exact copy/paste of your code with raceFlag(for both) = RACE_FLAG_TREE(last match) [BRANCHES] Execution x 10000000 took [287.451385] [ARRAY] Execution x 10000000 took [345.841217] With raceFlag(for both) = RACE_FLAG_ANIMAL(first match) + break after match: [BRANCHES] Execution x 10000000 took [29.319500] [ARRAY] Execution x 10000000 took [47.762199] With raceFlag(for both) = RACE_FLAG_TREE(last match) + break after match(useless here): [BRANCHES] Execution x 10000000 took [295.321716] [ARRAY] Execution x 10000000 took [282.486206] With raceFlag(for both) = RACE_FLAG_ANIMAL(first match) + break after match + static array: [BRANCHES] Execution x 10000000 took [29.350700] [ARRAY] Execution x 10000000 took [32.444702] With raceFlag(for both) = RACE_FLAG_TREE(first match) + break after match(useless here) + static array: [BRANCHES] Execution x 10000000 took [298.241302] [ARRAY] Execution x 10000000 took [272.202393] Using a switch with raceFlag = RACE_FLAG_ANIMAL(first match) [BRANCHES] Execution x 10000000 took [31.487902] [ARRAY] Execution x 10000000 took [32.890202] [SWITCH] Execution x 10000000 took [31.182301] Using a switch with raceFlag = RACE_FLAG_TREE(last match). Something like RACE_FLAG_ATT_ELEC(which isn't checked) brings the switch down to 16ms. [BRANCHES] Execution x 10000000 took [289.458801] [ARRAY] Execution x 10000000 took [271.130280] [SWITCH] Execution x 10000000 took [46.620998] Yeah, I'm bored, how did you know? Take these with a grain of salt btw, the numbers are influenced by what's going on on my pc at the time of running the program, but I guess they're good for a quick "lemme have a look at this shit". thx for ur time & sry about the section it's just my first topic in here when i said performance friendly i didn't really meant something that huge lmao XD and about the (break) it's not just a me thing most or even all pvm servers have (race + element) on some mobs and 1 of them will be disabled if they have the old code written above so i think it would be better to make 2 loops and use break on each one of them to get a single ( race + element ) struct RacePointPair { int raceFlag; uint8_t pointAttribute; }; RacePointPair racePointTable[] = { { RACE_FLAG_ANIMAL, POINT_ATTBONUS_ANIMAL }, { RACE_FLAG_UNDEAD, POINT_ATTBONUS_UNDEAD }, { RACE_FLAG_DEVIL, POINT_ATTBONUS_DEVIL }, { RACE_FLAG_HUMAN, POINT_ATTBONUS_HUMAN }, { RACE_FLAG_ORC, POINT_ATTBONUS_ORC }, { RACE_FLAG_MILGYO, POINT_ATTBONUS_MILGYO }, { RACE_FLAG_INSECT, POINT_ATTBONUS_INSECT }, { RACE_FLAG_DESERT, POINT_ATTBONUS_DESERT }, { RACE_FLAG_TREE, POINT_ATTBONUS_TREE } #ifdef ENABLE_NEW_ATTR ,{ RACE_FLAG_METIN, POINT_ATTBONUS_METIN } #endif #ifdef ENABLE_ZODIAC_ATTR ,{ RACE_FLAG_ZODIAC, POINT_ATTBONUS_ZODIAC } #endif #ifdef ENABLE_LEGENDARY_ATTR ,{ RACE_FLAG_LEGENDARY, POINT_ATTBONUS_LEGENDARY } #endif }; for (uint8_t i = 0; i < _countof(racePointTable); i++) { if (pkVictim->IsRaceFlag(racePointTable[i].raceFlag)) { iAtk += (iAtk * pkAttacker->GetPoint(racePointTable[i].pointAttribute)) / 100; break; } } RacePointPair elementPointTable[] = { { RACE_FLAG_FIRE, POINT_ATTBONUS_FIRE }, { RACE_FLAG_ICE, POINT_ATTBONUS_ICE } #ifdef ELEMENT_NEW_BONUSES ,{ RACE_FLAG_ELEC, POINT_ATTBONUS_ELEC } ,{ RACE_FLAG_WIND, POINT_ATTBONUS_WIND } ,{ RACE_FLAG_EARTH, POINT_ATTBONUS_EARTH } ,{ RACE_FLAG_DARK, POINT_ATTBONUS_DARK } #endif }; for (uint8_t i = 0; i < _countof(elementPointTable); i++) { if (pkVictim->IsRaceFlag(elementPointTable[i].raceFlag)) { iAtk += (iAtk * pkAttacker->GetPoint(elementPointTable[i].pointAttribute)) / 100; break; } } Link to comment Share on other sites More sharing options...
Contributor Amun 1906 Posted February 20 Contributor Share Posted February 20 On 2/9/2024 at 3:13 PM, CONTROL said: thx for ur time & sry about the section it's just my first topic in here when i said performance friendly i didn't really meant something that huge lmao XD and about the (break) it's not just a me thing most or even all pvm servers have (race + element) on some mobs and 1 of them will be disabled if they have the old code written above so i think it would be better to make 2 loops and use break on each one of them to get a single ( race + element ) struct RacePointPair { int raceFlag; uint8_t pointAttribute; }; RacePointPair racePointTable[] = { { RACE_FLAG_ANIMAL, POINT_ATTBONUS_ANIMAL }, { RACE_FLAG_UNDEAD, POINT_ATTBONUS_UNDEAD }, { RACE_FLAG_DEVIL, POINT_ATTBONUS_DEVIL }, { RACE_FLAG_HUMAN, POINT_ATTBONUS_HUMAN }, { RACE_FLAG_ORC, POINT_ATTBONUS_ORC }, { RACE_FLAG_MILGYO, POINT_ATTBONUS_MILGYO }, { RACE_FLAG_INSECT, POINT_ATTBONUS_INSECT }, { RACE_FLAG_DESERT, POINT_ATTBONUS_DESERT }, { RACE_FLAG_TREE, POINT_ATTBONUS_TREE } #ifdef ENABLE_NEW_ATTR ,{ RACE_FLAG_METIN, POINT_ATTBONUS_METIN } #endif #ifdef ENABLE_ZODIAC_ATTR ,{ RACE_FLAG_ZODIAC, POINT_ATTBONUS_ZODIAC } #endif #ifdef ENABLE_LEGENDARY_ATTR ,{ RACE_FLAG_LEGENDARY, POINT_ATTBONUS_LEGENDARY } #endif }; for (uint8_t i = 0; i < _countof(racePointTable); i++) { if (pkVictim->IsRaceFlag(racePointTable[i].raceFlag)) { iAtk += (iAtk * pkAttacker->GetPoint(racePointTable[i].pointAttribute)) / 100; break; } } RacePointPair elementPointTable[] = { { RACE_FLAG_FIRE, POINT_ATTBONUS_FIRE }, { RACE_FLAG_ICE, POINT_ATTBONUS_ICE } #ifdef ELEMENT_NEW_BONUSES ,{ RACE_FLAG_ELEC, POINT_ATTBONUS_ELEC } ,{ RACE_FLAG_WIND, POINT_ATTBONUS_WIND } ,{ RACE_FLAG_EARTH, POINT_ATTBONUS_EARTH } ,{ RACE_FLAG_DARK, POINT_ATTBONUS_DARK } #endif }; for (uint8_t i = 0; i < _countof(elementPointTable); i++) { if (pkVictim->IsRaceFlag(elementPointTable[i].raceFlag)) { iAtk += (iAtk * pkAttacker->GetPoint(elementPointTable[i].pointAttribute)) / 100; break; } } No worries, man, I just mentioned the break because that's how it works on the "clean" source/proto. Everyone is free to modify to suit their needs and it's not like a few more iterations will make any difference in real life anyway. Anyhow, don't mind me, I was just bored Link to comment Share on other sites More sharing options...
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now