Jump to content
  • 0

pomoc Výpočet obdrženého poškození


Scydo

Dotaz

Tak jo, mám zajímavý problém k řešení pro nadšence matematiky:

Mám funkci, která vypočítává pro hráče hodnotu, kolik mu skutečně ubere poškození dle zbroje co má na sobě, a napadlo mě následujicí:

Hráči se utrpěné poškození zmenšuje podle toho, jaké všechny typy zbroje má na sobě a jakou má hodnotu (aby to bylo dynamické, kdyby měl například level 100 se zbrojí co by mu přidávalo dohromady 3000 obrany ale stále by blokoval určité procento poškození):

float ReturnTrueDamage(unsigned int damage, float armor, unsigned int per_armor) {
    return (damage - ((armor / 100) * per_armor));
}

Každá část zbroje přidává určité procento:

  • Helma - 5 %,
  • Pancíř - 15 %,
  • Rukavice - 5 %,
  • Nohavice - 10 %,
  • Boty - 5 %,
  • Štít - dle úrovně (min 10 % | max 25 %).

To znamená, jestliže mám na sobě kompletní nejlepší těžkou zbroj, tak moje procentuální obrana je 65 %. Takže, během obdrženého poškození odblokuji 65 % své celkové zbroje. Příklad:

Jestliže obdržím poškození 1000, a mám armor 200 z toho mám procentuální zbroj 10  % (Helma + Boty), tak následně obdržím: (1000 mínus 10 % ze 200) =  980 poškození.
A jestliže obdržím opět 1000 a opět mám armor 200 ale moje procentuální zbroj je 65 % (kompletní) tak obdržím (1000 - 65 % ze 200) = 870 poškození.

Ale, tady je problém, že jestliže damage je menší než armor, tak výsledné poškození jde do mínusu. Tak jsem si řekl, že když je hráč hodně OP, tak mu to ubere pouze 1 hp:

return damage < armor ? (1) : (damage - ((armor / 100) * per_armor));

Nicméně tady je další problém, že jakmile tohle aplikuji a damage je třeba jen o 1 jednotku menší, tak okamžitě obdržím pouze 1 poškození, i kdybych měl například pouze 5 % procentuální zbroje.

Další varianta, co mě napadla tak při menším damage než armor, by vracel damage odečtené damage jeho procentuální zbroje:

return damage < armor ? ((damage / 100) * per_armor) : (damage - ((armor / 100 ) * per_armor));


Ale to není moc férové, protože jestliže mám 10 % procentuální zbroje tak mi ubere pouze 10 % damage, mezitím kdybych měl nejlepší 65 % procentuální zbroje, ubere mi to ještě více.

Nenapadá někoho lepší řešení/vzoreček na to?

Edited by Scydo
typo
Link to comment
Share on other sites

3 odpovědí na tuto otázku

Recommended Posts

  • 1

Myslim si, že

return max(1, damage - ((armor / 100) * per_armor))

je víc fér, než check damage > armor. Tímhle nastavíš to, že vždy dá hráč alespoň 1 dmg, tvým způsobem by hráč mohl dát i damage v intervalu <0, 1).

 

Proč by to bylo nefér. Hráč A má armor 1000, per armor má 100 %.

- Hráč B ho attackuje s damage 1000. Hráč A dostane 0 damage.

- Hráč B ho attackuje s damage 1000.5. Hráč A dostane 0.5 damage.

- Hráč B ho attackuje s damage 999. Hráč A dostane 1 damage.

 

Takže by slabší hráč mohl dávat víc damage než silnější. V mém případě by ve všech případech dostal hráč A 1 damage. Není to taky úplně fér, ale slabší hráč nedává pak víc damage než silnější.

 

// Asi je to to stejné, co postl mxco, moje akorát nezaokrouhluje

Edited by Lukasz
  • Líbí se mi to! (+1) 1
Link to comment
Share on other sites

  • 1

Vzoreček, kdy utrpěný damage jde do mínusu bude fungovat až když budeš porovnávat damage a vypočítanou účinnost zbroje (damage který má utrpět), nikoliv surovou hodnotu armoru.

taken = round up ((armor / 100) * per_armor);
return (taken >= damage) ? (1) : (damage - taken);

(pardon za pseudokód)

Jinak se tomu asi vyhnout nedá. Když tě něco kousne s malým damage a ty seš k tomu navíc obrněnej tank, tak abys něco dostal, tak musíš dostat alespoň ten redukovanej 1 damage. Pak už je to otázka rozumu a vyváženosti, aby early game nepřítel neubíral po jedničkách po 5 minutách hraní :D

Edited by mxco
doplnění věty
  • Líbí se mi to! (+1) 1
Link to comment
Share on other sites

  • 0
před 4hodinami, mxco said:

Jinak se tomu asi vyhnout nedá. Když tě něco kousne s malým damage a ty seš k tomu navíc obrněnej tank, tak abys něco dostal, tak musíš dostat alespoň ten redukovanej 1 damage. Pak už je to otázka rozumu a vyváženosti, aby early game nepřítel neubíral po jedničkách po 5 minutách hraní :D

No právě ta 1 je až moc pevně daná ale hlavně i nepřímá :d Protože, v momentě kdybych měl 1000 nebo 10,000 životů, tak to ubírá stále po jednom, což je blbost, když dynamicky mi má ubírat určité procento.

// EDIT: Behěm psaní komentáře mě napadlo, co místo jednotky ubírat 1 % damage. Zkusil jsem a vypadá to slibně.

 

před 3hodinami, Lukasz said:

Myslim si, že


return max(1, damage - ((armor / 100) * per_armor))

// Asi je to to stejné, co postl mxco, moje akorát nezaokrouhluje

👍

No jo no... V určitých momentech v nezaokrouhledné jsou rozdíly oproti zaokrouhlené no :doge:.
Test:

Spoiler

// Typ armoru jsem zmenil na int
// Snad jsem obsáhl všechny možné scénáře.
// Testcode:
	std::cout << "Damage = " << ReturnTrueDamage(100, 0, 0) << std::endl;
	std::cout << "Damage = " << ReturnTrueDamage(100, 50, 10) << std::endl;
	std::cout << "Damage = " << ReturnTrueDamage(249, 250, 20) << std::endl;
	std::cout << "Damage = " << ReturnTrueDamage(249, 250, 65) << std::endl;
	std::cout << "Damage = " << ReturnTrueDamage(963, 300, 65) << std::endl;
	std::cout << "Damage = " << ReturnTrueDamage(1000, 300, 65) << std::endl;
	std::cout << "Damage = " << ReturnTrueDamage(1000, 1200, 65) << std::endl;
	std::cout << "Damage = " << ReturnTrueDamage(4000, 5000, 15) << std::endl;
	std::cout << "Damage = " << ReturnTrueDamage(39999, 40000, 45) << std::endl;
	std::cout << "Damage = " << ReturnTrueDamage(USHRT_MAX - 1, USHRT_MAX, 30) << std::endl;
// print:
/*
  Damage = 100
  Damage = 95
  Damage = 199
  Damage = 86
  Damage = 768
  Damage = 805
  Damage = 220
  Damage = 3250
  Damage = 21999
  Damage = 45884
*/

 

Ale nic převratného(ještě otravný problém během konverze(abych omezil co nejvíce deklarace) ale to si už poradím).
Ještě zkusím aplikovat obě varianty a to vracet max invervalu 1 % a výsledku a uvidíme.

Díky, může se lock.

Edited by Scydo
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...