Optimize_List_Action.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. <?php
  2. /**
  3. * File for the rune optimization action.
  4. *
  5. * Implements an action function to be called from the {@see Controller}.
  6. *
  7. * @author Iñigo Valentin <i@inigovalentin.com>
  8. * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
  9. * @package SWDB
  10. */
  11. require_once(PATH::ACTION . "Action.php");
  12. /**
  13. * Selects the runes for optimization.
  14. *
  15. * Reads the POST parameters looking for the following KEYS:
  16. * player: Player ID.
  17. * mode: Game mode ({@see GAME_MODE_ID}).
  18. * unit: Unit ID.
  19. * source: Source of the runes to select (assigned, unassigned, ...).
  20. * tuning: 1: All +12; 2: Even +15, odd + 12; 3: All +15.
  21. * set[]: Selected rune sets ({@see RUNE_SET_ID}).
  22. *
  23. * Then it selects all the runes matching the cryteria.
  24. *
  25. * @category Action
  26. */
  27. class Optimize_List_Action extends Action{
  28. /**
  29. * Executes the action.
  30. */
  31. public function execute(){
  32. // Increase max execution time.
  33. set_time_limit(60);
  34. $candidates = [
  35. 1 => [],
  36. 2 => [],
  37. 3 => [],
  38. 4 => [],
  39. 5 => [],
  40. 6 => []
  41. ];
  42. $response = null;
  43. $player = filter_input(INPUT_POST, 'player');
  44. if ($player == null){
  45. $this->code = 400;
  46. $this->message = "POST parameter 'player' not specified.";
  47. return;
  48. }
  49. $game_mode = GAME_MODE_ID::NORMAL;
  50. if (filter_input(INPUT_POST, 'mode') == GAME_MODE_ID::RTA){
  51. $game_mode = GAME_MODE_ID::RTA;
  52. }
  53. $unit_id = filter_input(INPUT_POST, 'unit');
  54. if ($unit_id == null){
  55. $this->code = 400;
  56. $this->message = "POST parameter 'unit' not specified.";
  57. return;
  58. }
  59. // Sets
  60. $sets = [];
  61. foreach ($_POST["set"] as $x){
  62. array_push($sets, intval($x));
  63. }
  64. if (sizeof($sets) < 2 || sizeof($sets) > 3){
  65. $this->code = 400;
  66. $this->message = "POST parameter 'set' not specified or invalid. Two or three rune sets must be specified. Broken sets are not supported.";
  67. return;
  68. }
  69. $focus = [];
  70. if (isset($_POST["focus_0"]) && intval($_POST["focus_0"]) > 0){
  71. array_push($focus, intval($_POST["focus_0"]));
  72. }
  73. if (isset($_POST["focus_1"]) && intval($_POST["focus_1"]) > 0){
  74. array_push($focus, intval($_POST["focus_1"]));
  75. }
  76. if (isset($_POST["focus_2"]) && intval($_POST["focus_2"]) > 0){
  77. array_push($focus, intval($_POST["focus_2"]));
  78. }
  79. // Remove doubles and sort. The order will be HP, ATK, DEF, SPD, CRR, CRD, RES, ACC
  80. $focus = array_unique($focus, SORT_NUMERIC);
  81. // Main stats in even slots.
  82. $stats = [];
  83. foreach ($_POST["stat"] as $x){
  84. array_push($stats, intval($x));
  85. }
  86. $source = filter_input(INPUT_POST, 'source');
  87. if ($source == null){
  88. $this->code = 400;
  89. $this->message = "POST parameter 'source' not specified.";
  90. return;
  91. }
  92. $tuning = filter_input(INPUT_POST, 'tuning');
  93. if ($tuning == null){
  94. $this->code = 400;
  95. $this->message = "POST parameter 'tuning' not specified.";
  96. return;
  97. }
  98. // Instantiate the unit
  99. $unit = new Unit($unit_id);
  100. // Get build query:
  101. $base_s = "
  102. SELECT
  103. id,
  104. type,
  105. slot,
  106. level,
  107. stars,
  108. (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::MAIN . " ) AS main_stat,
  109. (SELECT value FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::MAIN . " ) AS main_stat_value,
  110. (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::INNATE . " ) AS innate_stat,
  111. (SELECT value FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::INNATE . " ) AS innate_stat_value,
  112. (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_1 . " ) AS substat_1,
  113. (SELECT value + grind FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_1 . " ) AS substat_1_value,
  114. (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_2 . " ) AS substat_2,
  115. (SELECT value + grind FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_2 . " ) AS substat_2_value,
  116. (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_3 . " ) AS substat_3,
  117. (SELECT value + grind FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_3 . " ) AS substat_3_value,
  118. (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_4 . " ) AS substat_4,
  119. (SELECT value + grind FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_4 . " ) AS substat_4_value
  120. FROM rune
  121. WHERE
  122. player = :player AND
  123. type IN (
  124. ";
  125. foreach ($sets as $set){
  126. $base_s .= ($set . ",");
  127. }
  128. $base_s .= "-1) AND ";
  129. switch ($source){
  130. case 0: // Storage only (or itself)
  131. $base_s .= "
  132. (
  133. rune.id IN (SELECT DISTINCT rune FROM unit_rune WHERE unit = :unit_id AND rta = " . $game_mode . ")
  134. OR
  135. rune.id NOT IN (SELECT DISTINCT rune FROM unit_rune WHERE rta = " . $game_mode . ")
  136. )";
  137. break;
  138. case 1: // Units in no teams (or itself)
  139. $base_s .= "
  140. (
  141. rune.id IN (SELECT DISTINCT rune FROM unit_rune WHERE unit = :unit_id AND rta = " . $game_mode . ")
  142. OR rune.id NOT IN (SELECT DISTINCT rune FROM unit_rune WHERE rta = " . $game_mode . ")
  143. OR rune.id NOT IN (SELECT DISTINCT rune FROM unit_rune WHERE rta = " . $game_mode . " AND unit NOT IN (SELECT DISTINCT unit FROM team_unit))
  144. )
  145. ";
  146. break;
  147. case 2: // Units in teams with 0 score (or itself)
  148. $base_s .= "
  149. (
  150. rune.id IN (SELECT DISTINCT rune FROM unit_rune WHERE unit = :unit_id AND rta = " . $game_mode . ")
  151. OR rune.id NOT IN (SELECT DISTINCT rune FROM unit_rune WHERE rta = " . $game_mode . ")
  152. OR rune.id NOT IN (
  153. SELECT DISTINCT rune
  154. FROM unit_rune
  155. WHERE
  156. rta = " . $game_mode . "
  157. AND unit NOT IN (
  158. SELECT DISTINCT unit
  159. FROM
  160. team,
  161. team_unit
  162. WHERE
  163. team.id = team_unit.team
  164. AND team.score > 0
  165. )
  166. )
  167. )
  168. ";
  169. break;
  170. case 3: // Units with lower overall score (or itself)
  171. // TODO
  172. break;
  173. case 4: // All runes - dont filter
  174. $base_s .= " 1 = 1 ";
  175. break;
  176. default: // Invalid options - return nothing
  177. $base_s .= " 1 = 0 ";
  178. }
  179. $s_order = " ORDER BY stars DESC, original_quality DESC, max_efficiency DESC, efficiency DESC, level DESC";
  180. //$s_in = " main_stat IN (:stat_0, :stat_1, :stat_2) ";
  181. $s_main = [
  182. " main_stat = :stat_0 ",
  183. " main_stat = :stat_1 ",
  184. " main_stat = :stat_2 ",
  185. ];
  186. // Process focuses
  187. $focus_stats = [];
  188. foreach ($focus as $f){
  189. switch ($f){
  190. case STAT_ID::HP:
  191. array_push($focus_stats, RUNE_STAT_ID::HP);
  192. array_push($focus_stats, RUNE_STAT_ID::HP_P);
  193. break;
  194. case STAT_ID::ATK:
  195. array_push($focus_stats, RUNE_STAT_ID::ATK);
  196. array_push($focus_stats, RUNE_STAT_ID::ATK_P);
  197. break;
  198. case STAT_ID::DEF:
  199. array_push($focus_stats, RUNE_STAT_ID::DEF);
  200. array_push($focus_stats, RUNE_STAT_ID::DEF_P);
  201. break;
  202. case STAT_ID::SPD:
  203. array_push($focus_stats, RUNE_STAT_ID::SPD);
  204. break;
  205. case STAT_ID::CRR:
  206. array_push($focus_stats, RUNE_STAT_ID::CRR);
  207. break;
  208. case STAT_ID::CRD:
  209. array_push($focus_stats, RUNE_STAT_ID::CRD);
  210. break;
  211. case STAT_ID::ACC:
  212. array_push($focus_stats, RUNE_STAT_ID::ACC);
  213. break;
  214. case STAT_ID::RES:
  215. array_push($focus_stats, RUNE_STAT_ID::RES);
  216. break;
  217. }
  218. }
  219. $focus_cond = ["", "", "", "", "", "", ""];
  220. if (sizeof($focus) > 0){
  221. // Slot 1, no ATK flat, no DEF flat, no DEF %
  222. $focus_slot = $focus_stats;
  223. /*if (array_search(RUNE_STAT_ID::ATK, $focus_slot) !== false){
  224. $focus_slot = array_diff($focus_slot, [RUNE_STAT_ID::ATK])//array_splice($focus_slot, array_search(RUNE_STAT_ID::ATK, $focus_slot), 1);
  225. }
  226. if (array_search(RUNE_STAT_ID::DEF, $focus_slot) !== false){
  227. $focus_slot = array_splice($focus_slot, array_search(RUNE_STAT_ID::DEF, $focus_slot), 1);
  228. }
  229. if (array_search(RUNE_STAT_ID::DEF_P, $focus_slot) !== false){
  230. $focus_slot = array_splice($focus_slot, array_search(RUNE_STAT_ID::DEF_P, $focus_slot), 1);
  231. }*/
  232. $focus_slot = array_diff($focus_slot, [RUNE_STAT_ID::ATK, RUNE_STAT_ID::DEF, RUNE_STAT_ID::DEF_P]);
  233. if (sizeof($focus_slot) > 0){
  234. $focus_cond[1] .= "
  235. -- FOCUS 1
  236. AND (
  237. rune.id IN (
  238. SELECT DISTINCT rune FROM rune_stat WHERE slot != :slot_main AND stat IN
  239. (
  240. ";
  241. foreach ($focus_slot as $stat){
  242. $focus_cond[1] .= $stat . ", ";
  243. }
  244. $focus_cond[1] = rtrim($focus_cond[1], ", ");
  245. $focus_cond[1] .= "
  246. )
  247. )
  248. ) -- END FOCUS 1
  249. ";
  250. }
  251. // Slot 3, no ATK flat, no ATK %, no DEF flat.
  252. $focus_slot = $focus_stats;
  253. /*if (array_search(RUNE_STAT_ID::ATK, $focus_slot) !== false){
  254. $focus_slot = array_splice($focus_slot, array_search(RUNE_STAT_ID::ATK, $focus_slot), 1);
  255. }
  256. if (array_search(RUNE_STAT_ID::ATK_P, $focus_slot) !== false){
  257. $focus_slot = array_splice($focus_slot, array_search(RUNE_STAT_ID::ATK_P, $focus_slot), 1);
  258. }
  259. if (array_search(RUNE_STAT_ID::DEF, $focus_slot) !== false){
  260. $focus_slot = array_splice($focus_slot, array_search(RUNE_STAT_ID::DEF, $focus_slot), 1);
  261. }*/
  262. $focus_slot = array_diff($focus_slot, [RUNE_STAT_ID::ATK, RUNE_STAT_ID::ATK_P, RUNE_STAT_ID::DEF]);
  263. if (sizeof($focus_slot) > 0){
  264. $focus_cond[3] .= "
  265. -- FOCUS 3
  266. AND (
  267. rune.id IN (
  268. SELECT DISTINCT rune FROM rune_stat WHERE slot != :slot_main AND stat IN
  269. (
  270. ";
  271. foreach ($focus_slot as $stat){
  272. $focus_cond[3] .= $stat . ", ";
  273. }
  274. $focus_cond[3] = rtrim($focus_cond[3], ", ");
  275. $focus_cond[3] .= "
  276. )
  277. )
  278. ) -- END FOCUS 3
  279. ";
  280. }
  281. // Slot 5, no HP flat.
  282. $focus_slot = $focus_stats;
  283. /*if (array_search(RUNE_STAT_ID::HP, $focus_slot) !== false){
  284. $focus_slot = array_splice($focus_slot, array_search(RUNE_STAT_ID::HP, $focus_slot), 1);
  285. }*/
  286. $focus_slot = array_diff($focus_slot, [RUNE_STAT_ID::HP]);
  287. if (sizeof($focus_slot) > 0){
  288. $focus_cond[5] .= "
  289. -- FOCUS 5
  290. AND (
  291. rune.id IN (
  292. SELECT DISTINCT rune FROM rune_stat WHERE slot != :slot_main AND stat IN
  293. (
  294. ";
  295. foreach ($focus_slot as $stat){
  296. $focus_cond[5] .= $stat . ", ";
  297. }
  298. $focus_cond[5] = rtrim($focus_cond[5], ", ");
  299. $focus_cond[5] .= "
  300. )
  301. )
  302. ) -- END FOCUS 5
  303. ";
  304. }
  305. // TODO: Focus for even slots.
  306. // Slot 2, all stat, but include main
  307. // Slot 5, no HP flat.
  308. $focus_slot = $focus_stats;
  309. if (sizeof($focus_slot) > 0){
  310. $focus_cond[2] .= "
  311. -- FOCUS EVEN
  312. AND (
  313. rune.id IN (
  314. SELECT DISTINCT rune FROM rune_stat WHERE stat IN
  315. (
  316. ";
  317. foreach ($focus_slot as $stat){
  318. $focus_cond[2] .= $stat . ", ";
  319. }
  320. $focus_cond[2] = rtrim($focus_cond[2], ", ");
  321. $focus_cond[2] .= "
  322. )
  323. )
  324. ) -- END FOCUS EVEN
  325. ";
  326. }
  327. }
  328. //TODO DEBUG
  329. //$focus_cond[2] = "";
  330. $s = ["", "", "", "", "", "", ""];
  331. $s[1] = $base_s . " AND slot = 1 " . $focus_cond[1] . $s_order . " LIMIT :limit_odd;";
  332. $s[3] = $base_s . " AND slot = 3 " . $focus_cond[3] . $s_order . " LIMIT :limit_odd;";
  333. $s[5] = $base_s . " AND slot = 5 " . $focus_cond[5] . $s_order . " LIMIT :limit_odd;";
  334. $s[2] = $base_s . " AND slot = 2 AND " . $s_main[0] . $focus_cond[2] . $s_order . " LIMIT :limit_even;";
  335. $s[4] = $base_s . " AND slot = 4 AND " . $s_main[1] . $focus_cond[2] . $s_order . " LIMIT :limit_even;";
  336. $s[6] = $base_s . " AND slot = 6 AND " . $s_main[2] . $focus_cond[2] . $s_order . " LIMIT :limit_even;";
  337. $total_candidates = 0;
  338. for ($i = 1; $i <= 6; $i ++){
  339. //error_log($s[$i]);
  340. $statement = get_context()->get_db()->prepare($s[$i]);
  341. $statement->bindValue(':player', $player, SQLITE3_TEXT);
  342. $statement->bindValue(':unit_id', $unit_id, SQLITE3_TEXT);
  343. $statement->bindValue(':stat_0', $stats[0], SQLITE3_TEXT);
  344. $statement->bindValue(':stat_1', $stats[1], SQLITE3_TEXT);
  345. $statement->bindValue(':stat_2', $stats[2], SQLITE3_TEXT);
  346. $statement->bindValue(':slot_main', RUNE_STAT_SLOT_ID::MAIN, SQLITE3_INTEGER);
  347. $statement->bindValue(':limit_even', 150, SQLITE3_INTEGER);
  348. $statement->bindValue(':limit_odd', 100, SQLITE3_INTEGER);
  349. //error_log($statement->getSQL(true));
  350. $q = $statement->execute();
  351. while ($r = $q->fetchArray(SQLITE3_ASSOC)){
  352. $rune = $this->create_rune_array($unit, $r, $tuning);
  353. //array_push($candidates[$i], new Rune($r["id"]));
  354. array_push($candidates[$i], $rune);
  355. $total_candidates ++;
  356. }
  357. }
  358. //$max_combinations = sizeof($candidates[1]) * sizeof($candidates[2]) * sizeof($candidates[3]) * sizeof($candidates[4]) * sizeof($candidates[5]) * sizeof($candidates[6]);
  359. // Build response
  360. $response = json_encode($candidates);
  361. if ($response == null){
  362. $this->code = 201;
  363. $this->message = "No valid combinations found";
  364. return;
  365. }
  366. else{
  367. $this->code = 200;
  368. $this->message = "OK";
  369. $this->output = $response;
  370. return;
  371. }
  372. }
  373. /**
  374. * Creates an array with the stats provided by a rune on a unit.
  375. *
  376. * @param Unit $unit Target unit.
  377. * @param int $r Rune main stat ID.
  378. * @param int $stars Rune stars.
  379. * @return int Value of the main stat at the selected level.
  380. */
  381. private function create_rune_array($unit, $r, $tuning){
  382. $rune = [
  383. "ID" => $r["id"],
  384. "TYPE" => $r["type"],
  385. "ATK" => 0,
  386. "DEF" => 0,
  387. "HP" => 0,
  388. "SPD" => 0,
  389. "CRR" => 0,
  390. "CRD" => 0,
  391. "ACC" => 0,
  392. "RES" => 0
  393. ];
  394. // Calculate main stat value based on requested level.
  395. $level = $r["level"];
  396. $main_value = $r["main_stat_value"];
  397. switch ($tuning){
  398. case 1: // All +12
  399. if ($level < 12){
  400. $main_value = get_main_stat_at_level(12, $r["main_stat"], $r["stars"]);
  401. }
  402. break;
  403. case 2: // Even +15, Odd + 12
  404. if ($level < 15 && $r["slot"] % 2 == 0){
  405. $main_value = get_main_stat_at_level(15, $r["main_stat"], $r["stars"]);
  406. }
  407. elseif ($level < 12 && $r["slot"] % 2 != 0){
  408. $main_value = get_main_stat_at_level(12, $r["main_stat"], $r["stars"]);
  409. }
  410. break;
  411. case 3: // All +15
  412. if ($level < 15){
  413. $main_value = get_main_stat_at_level(15, $r["main_stat"], $r["stars"]);
  414. }
  415. break;
  416. }
  417. // Array to loop.
  418. $stats = [
  419. [
  420. "STAT" => $r["main_stat"],
  421. "VALUE" => $main_value
  422. ],
  423. [
  424. "STAT" => $r["innate_stat"],
  425. "VALUE" => $r["innate_stat_value"]
  426. ],
  427. [
  428. "STAT" => $r["substat_1"],
  429. "VALUE" => $r["substat_1_value"]
  430. ],
  431. [
  432. "STAT" => $r["substat_2"],
  433. "VALUE" => $r["substat_2_value"]
  434. ],
  435. [
  436. "STAT" => $r["substat_3"],
  437. "VALUE" => $r["substat_3_value"]
  438. ],
  439. [
  440. "STAT" => $r["substat_4"],
  441. "VALUE" => $r["substat_4_value"]
  442. ]
  443. ];
  444. foreach ($stats as $stat){
  445. switch ($stat["STAT"]){
  446. case RUNE_STAT_ID::ATK:
  447. $rune["ATK"] += $stat["VALUE"];
  448. break;
  449. case RUNE_STAT_ID::ATK_P:
  450. $rune["ATK"] += ($unit->get_base_stats()["atk"] * $stat["VALUE"] / 100);
  451. break;
  452. case RUNE_STAT_ID::DEF:
  453. $rune["DEF"] += $stat["VALUE"];
  454. break;
  455. case RUNE_STAT_ID::DEF_P:
  456. $rune["DEF"] += ($unit->get_base_stats()["def"] * $stat["VALUE"] / 100);
  457. break;
  458. case RUNE_STAT_ID::HP:
  459. $rune["HP"] += $stat["VALUE"];
  460. break;
  461. case RUNE_STAT_ID::HP_P:
  462. $rune["HP"] += ($unit->get_base_stats()["hp"] * $stat["VALUE"] / 100);
  463. break;
  464. case RUNE_STAT_ID::SPD:
  465. $rune["SPD"] += $stat["VALUE"];
  466. break;
  467. case RUNE_STAT_ID::CRR:
  468. $rune["CRR"] += $stat["VALUE"];
  469. break;
  470. case RUNE_STAT_ID::CRD:
  471. $rune["CRD"] += $stat["VALUE"];
  472. break;
  473. case RUNE_STAT_ID::ACC:
  474. $rune["ACC"] += $stat["VALUE"];
  475. break;
  476. case RUNE_STAT_ID::RES:
  477. $rune["RES"] += $stat["VALUE"];
  478. break;
  479. }
  480. }
  481. return $rune;
  482. }
  483. /**
  484. * Gets the value of the main stat at an arbitrary level.
  485. *
  486. * @param int $level Desired level.
  487. * @param int $stat Rune main stat ID.
  488. * @param int $stars Rune stars.
  489. * @return int Value of the main stat at the selected level.
  490. */
  491. private function get_main_stat_at_level($level, $stat, $stars){
  492. $level = intval($level);
  493. if ($level < 0 || $level > 15){
  494. return 0;
  495. }
  496. switch ($stat){
  497. case RUNE_STAT_ID::HP:
  498. return RUNE_STAT_VALUES::HP[$stars][$level];
  499. case RUNE_STAT_ID::HP_P:
  500. return RUNE_STAT_VALUES::HP_P[$stars][$level];
  501. case RUNE_STAT_ID::ATK:
  502. return RUNE_STAT_VALUES::ATK[$stars][$level];
  503. case RUNE_STAT_ID::ATK_P:
  504. return RUNE_STAT_VALUES::ATK_P[$stars][$level];
  505. case RUNE_STAT_ID::DEF:
  506. return RUNE_STAT_VALUES::DEF[$stars][$level];
  507. case RUNE_STAT_ID::DEF_P:
  508. return RUNE_STAT_VALUES::DEF_P[$stars][$level];
  509. case RUNE_STAT_ID::SPD:
  510. return RUNE_STAT_VALUES::SPD[$stars][$level];
  511. case RUNE_STAT_ID::CRR:
  512. return RUNE_STAT_VALUES::CRR[$stars][$level];
  513. case RUNE_STAT_ID::CRD:
  514. return RUNE_STAT_VALUES::CRD[$stars][$level];
  515. case RUNE_STAT_ID::RES:
  516. return RUNE_STAT_VALUES::RES[$stars][$level];
  517. case RUNE_STAT_ID::ACC:
  518. return RUNE_STAT_VALUES::ACC[$stars][$level];
  519. default:
  520. return 0;
  521. }
  522. }
  523. }