Selaa lähdekoodia

RTA and normal mode switcher. Rune stats are now separate entities.

Iñigo Valentin 5 vuotta sitten
vanhempi
sitoutus
b7cfc1e11b
39 muutettua tiedostoa jossa 1165 lisäystä ja 678 poistoa
  1. 97 97
      application/API/v3/profile/PUT.php
  2. 65 0
      application/Constant.php
  3. 22 0
      application/Controller.php
  4. 43 0
      application/action/change_game_mode.php
  5. 0 1
      application/action/login.php
  6. 32 26
      application/action/optimize_get_rune_list.php
  7. 115 21
      application/entity/Run.php
  8. 55 217
      application/entity/Rune.php
  9. 131 0
      application/entity/Rune_Stat.php
  10. 13 11
      application/entity/Unit.php
  11. 23 27
      application/helper/HTML_Helper.php
  12. 2 2
      application/page/Monsters_Page.php
  13. 133 119
      application/page/Report_Rune_Enchantment_Page.php
  14. 4 2
      application/page/Report_Skillup_Page.php
  15. 38 32
      application/page/Runes_Page.php
  16. 7 0
      application/view/artifacts.php
  17. 7 0
      application/view/catalog.php
  18. 7 0
      application/view/enchantments.php
  19. 7 0
      application/view/error.php
  20. 7 0
      application/view/fusion.php
  21. 7 0
      application/view/guild.php
  22. 7 0
      application/view/help.php
  23. 7 0
      application/view/home.php
  24. 127 53
      application/view/inc/header.php
  25. 11 0
      application/view/monster.php
  26. 7 0
      application/view/monster_info.php
  27. 11 0
      application/view/monsters.php
  28. 7 0
      application/view/optimizer.php
  29. 12 1
      application/view/optimizer_unit.php
  30. 7 0
      application/view/profile.php
  31. 7 0
      application/view/report.php
  32. 7 0
      application/view/report_rune_enchantment.php
  33. 7 0
      application/view/report_skillup.php
  34. 9 2
      application/view/runes.php
  35. 7 0
      application/view/runs.php
  36. 7 0
      application/view/stats.php
  37. 7 0
      application/view/teams.php
  38. 18 22
      install_data/install_data.sql
  39. 85 45
      public/css/ui.css

+ 97 - 97
application/API/v3/profile/PUT.php

@@ -336,7 +336,6 @@
           INSERT INTO rune (
             uid,
             id,
-            assigned_to,
             type,
             slot,
             stars,
@@ -347,31 +346,10 @@
             value,
             efficiency,
             max_efficiency,
-            main_stat,
-            main_stat_value,
-            innate_stat,
-            innate_stat_value,
-            substat_1,
-            substat_1_value,
-            substat_1_enchant,
-            substat_1_grind,
-            substat_2,
-            substat_2_value,
-            substat_2_enchant,
-            substat_2_grind,
-            substat_3,
-            substat_3_value,
-            substat_3_enchant,
-            substat_3_grind,
-            substat_4,
-            substat_4_value,
-            substat_4_enchant,
-            substat_4_grind,
             locked
           ) VALUES (
             :uid,
             :id,
-            :assigned_to,
             :type,
             :slot,
             :stars,
@@ -382,37 +360,11 @@
             :value,
             :efficiency,
             :max_efficiency,
-            :main_stat,
-            :main_stat_value,
-            :innate_stat,
-            :innate_stat_value,
-            :substat_1,
-            :substat_1_value,
-            :substat_1_enchant,
-            :substat_1_grind,
-            :substat_2,
-            :substat_2_value,
-            :substat_2_enchant,
-            :substat_2_grind,
-            :substat_3,
-            :substat_3_value,
-            :substat_3_enchant,
-            :substat_3_grind,
-            :substat_4,
-            :substat_4_value,
-            :substat_4_enchant,
-            :substat_4_grind,
             :locked
           );
         ");
         $statement->bindValue(":uid", $uid, SQLITE3_INTEGER);
         $statement->bindValue(":id", $rune->{"rune_id"}, SQLITE3_INTEGER);
-        if (intval($rune->{"occupied_id"}) == 0){
-            $statement->bindValue(":assigned_to", null, SQLITE3_INTEGER);
-        }
-        else{
-            $statement->bindValue(":assigned_to", $rune->{"occupied_id"}, SQLITE3_INTEGER);
-        }
         $statement->bindValue(":type", $rune->{"set_id"}, SQLITE3_INTEGER);
         $statement->bindValue(":slot", $rune->{"slot_no"}, SQLITE3_INTEGER);
         $statement->bindValue(":value", $rune->{"sell_value"}, SQLITE3_INTEGER);
@@ -456,65 +408,97 @@
         $max_efficiency = calculate_maximum_efficiency($rune);
         $statement->bindValue(":efficiency", $efficiency, SQLITE3_FLOAT);
         $statement->bindValue(":max_efficiency", $max_efficiency, SQLITE3_FLOAT);
-        $statement->bindValue(":main_stat", $rune->{"pri_eff"}[0], SQLITE3_INTEGER);
-        $statement->bindValue(":main_stat_value", $rune->{"pri_eff"}[1], SQLITE3_INTEGER);
+        $statement->execute();
+
+        $stat_statement = "
+          INSERT INTO rune_stat (rune, slot, stat, value, enchant, grind, rolls)
+          VALUES (:rune, :slot, :stat, :value, :enchant, :grind, :rolls);
+        ";
+
+        // Main stat
+        $statement = $db->prepare($stat_statement);
+        $statement->bindValue(":rune", $rune->{"rune_id"}, SQLITE3_INTEGER);
+        $statement->bindValue(":slot", RUNE_STAT_SLOT_ID::MAIN, SQLITE3_INTEGER);
+        $statement->bindValue(":stat", $rune->{"pri_eff"}[0], SQLITE3_INTEGER);
+        $statement->bindValue(":value", $rune->{"pri_eff"}[1], SQLITE3_INTEGER);
+        $statement->bindValue(":enchant", 0, SQLITE3_INTEGER);
+        $statement->bindValue(":grind", 0, SQLITE3_INTEGER);
+        $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
+        $statement->execute();
+
+        // Innate stat
         if ($rune->{"prefix_eff"}[0] > 0){
-            $statement->bindValue(":innate_stat", $rune->{"prefix_eff"}[0], SQLITE3_INTEGER);
-            $statement->bindValue(":innate_stat_value", $rune->{"prefix_eff"}[1], SQLITE3_INTEGER);
-        }
-        else{
-            $statement->bindValue(":innate_stat", null, SQLITE3_INTEGER);
-            $statement->bindValue(":innate_stat_value", 0, SQLITE3_INTEGER);
+            // Main stat
+            $statement = $db->prepare($stat_statement);
+            $statement->bindValue(":rune", $rune->{"rune_id"}, SQLITE3_INTEGER);
+            $statement->bindValue(":slot", RUNE_STAT_SLOT_ID::INNATE, SQLITE3_INTEGER);
+            $statement->bindValue(":stat", $rune->{"prefix_eff"}[0], SQLITE3_INTEGER);
+            $statement->bindValue(":value", $rune->{"prefix_eff"}[1], SQLITE3_INTEGER);
+            $statement->bindValue(":enchant", 0, SQLITE3_INTEGER);
+            $statement->bindValue(":grind", 0, SQLITE3_INTEGER);
+            $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
+            $statement->execute();
         }
         if (sizeof($rune->{"sec_eff"}) > 0){
-            $statement->bindValue(":substat_1", $rune->{"sec_eff"}[0][0], SQLITE3_INTEGER);
-            $statement->bindValue(":substat_1_value", $rune->{"sec_eff"}[0][1], SQLITE3_INTEGER);
-            $statement->bindValue(":substat_1_enchant", $rune->{"sec_eff"}[0][2], SQLITE3_INTEGER);
-            $statement->bindValue(":substat_1_grind", $rune->{"sec_eff"}[0][3], SQLITE3_INTEGER);
-        }
-        else{
-            $statement->bindValue(":substat_1", null, SQLITE3_INTEGER);
-            $statement->bindValue(":substat_1_value", 0, SQLITE3_INTEGER);
-            $statement->bindValue(":substat_1_enchant", 0, SQLITE3_INTEGER);
-            $statement->bindValue(":substat_1_grind", 0, SQLITE3_INTEGER);
+            $statement = $db->prepare($stat_statement);
+            $statement->bindValue(":rune", $rune->{"rune_id"}, SQLITE3_INTEGER);
+            $statement->bindValue(":slot", RUNE_STAT_SLOT_ID::SUBSTAT_1, SQLITE3_INTEGER);
+            $statement->bindValue(":stat", $rune->{"sec_eff"}[0][0], SQLITE3_INTEGER);
+            $statement->bindValue(":value", $rune->{"sec_eff"}[0][1], SQLITE3_INTEGER);
+            $statement->bindValue(":enchant", $rune->{"sec_eff"}[0][2], SQLITE3_INTEGER);
+            $statement->bindValue(":grind", $rune->{"sec_eff"}[0][3], SQLITE3_INTEGER);
+            // TODO: Calculate rolls
+            $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
+            $statement->execute();
         }
         if (sizeof($rune->{"sec_eff"}) > 1){
-            $statement->bindValue(":substat_2", $rune->{"sec_eff"}[1][0], SQLITE3_INTEGER);
-            $statement->bindValue(":substat_2_value", $rune->{"sec_eff"}[1][1], SQLITE3_INTEGER);
-            $statement->bindValue(":substat_2_enchant", $rune->{"sec_eff"}[1][2], SQLITE3_INTEGER);
-            $statement->bindValue(":substat_2_grind", $rune->{"sec_eff"}[1][3], SQLITE3_INTEGER);
-        }
-        else{
-            $statement->bindValue(":substat_2", null, SQLITE3_INTEGER);
-            $statement->bindValue(":substat_2_value", 0, SQLITE3_INTEGER);
-            $statement->bindValue(":substat_2_enchant", 0, SQLITE3_INTEGER);
-            $statement->bindValue(":substat_2_grind", 0, SQLITE3_INTEGER);
+            $statement = $db->prepare($stat_statement);
+            $statement->bindValue(":rune", $rune->{"rune_id"}, SQLITE3_INTEGER);
+            $statement->bindValue(":slot", RUNE_STAT_SLOT_ID::SUBSTAT_2, SQLITE3_INTEGER);
+            $statement->bindValue(":stat", $rune->{"sec_eff"}[1][0], SQLITE3_INTEGER);
+            $statement->bindValue(":value", $rune->{"sec_eff"}[1][1], SQLITE3_INTEGER);
+            $statement->bindValue(":enchant", $rune->{"sec_eff"}[1][2], SQLITE3_INTEGER);
+            $statement->bindValue(":grind", $rune->{"sec_eff"}[1][3], SQLITE3_INTEGER);
+            // TODO: Calculate rolls
+            $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
+            $statement->execute();
         }
         if (sizeof($rune->{"sec_eff"}) > 2){
-            $statement->bindValue(":substat_3", $rune->{"sec_eff"}[2][0], SQLITE3_INTEGER);
-            $statement->bindValue(":substat_3_value", $rune->{"sec_eff"}[2][1], SQLITE3_INTEGER);
-            $statement->bindValue(":substat_3_enchant", $rune->{"sec_eff"}[2][2], SQLITE3_INTEGER);
-            $statement->bindValue(":substat_3_grind", $rune->{"sec_eff"}[2][3], SQLITE3_INTEGER);
-        }
-        else{
-            $statement->bindValue(":substat_3", null, SQLITE3_INTEGER);
-            $statement->bindValue(":substat_3_value", 0, SQLITE3_INTEGER);
-            $statement->bindValue(":substat_3_enchant", 0, SQLITE3_INTEGER);
-            $statement->bindValue(":substat_3_grind", 0, SQLITE3_INTEGER);
+            $statement = $db->prepare($stat_statement);
+            $statement->bindValue(":rune", $rune->{"rune_id"}, SQLITE3_INTEGER);
+            $statement->bindValue(":slot", RUNE_STAT_SLOT_ID::SUBSTAT_3, SQLITE3_INTEGER);
+            $statement->bindValue(":stat", $rune->{"sec_eff"}[2][0], SQLITE3_INTEGER);
+            $statement->bindValue(":value", $rune->{"sec_eff"}[2][1], SQLITE3_INTEGER);
+            $statement->bindValue(":enchant", $rune->{"sec_eff"}[2][2], SQLITE3_INTEGER);
+            $statement->bindValue(":grind", $rune->{"sec_eff"}[2][3], SQLITE3_INTEGER);
+            // TODO: Calculate rolls
+            $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
+            $statement->execute();
         }
         if (sizeof($rune->{"sec_eff"}) > 3){
-            $statement->bindValue(":substat_4", $rune->{"sec_eff"}[3][0], SQLITE3_INTEGER);
-            $statement->bindValue(":substat_4_value", $rune->{"sec_eff"}[3][1], SQLITE3_INTEGER);
-            $statement->bindValue(":substat_4_enchant", $rune->{"sec_eff"}[3][2], SQLITE3_INTEGER);
-            $statement->bindValue(":substat_4_grind", $rune->{"sec_eff"}[3][3], SQLITE3_INTEGER);
+            $statement = $db->prepare($stat_statement);
+            $statement->bindValue(":rune", $rune->{"rune_id"}, SQLITE3_INTEGER);
+            $statement->bindValue(":slot", RUNE_STAT_SLOT_ID::SUBSTAT_4, SQLITE3_INTEGER);
+            $statement->bindValue(":stat", $rune->{"sec_eff"}[3][0], SQLITE3_INTEGER);
+            $statement->bindValue(":value", $rune->{"sec_eff"}[3][1], SQLITE3_INTEGER);
+            $statement->bindValue(":enchant", $rune->{"sec_eff"}[3][2], SQLITE3_INTEGER);
+            $statement->bindValue(":grind", $rune->{"sec_eff"}[3][3], SQLITE3_INTEGER);
+            // TODO: Calculate rolls
+            $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
+            $statement->execute();
         }
-        else{
-            $statement->bindValue(":substat_4", null, SQLITE3_INTEGER);
-            $statement->bindValue(":substat_4_value", 0, SQLITE3_INTEGER);
-            $statement->bindValue(":substat_4_enchant", 0, SQLITE3_INTEGER);
-            $statement->bindValue(":substat_4_grind", 0, SQLITE3_INTEGER);
+
+        // Assigned?
+        if (intval($rune->{"occupied_id"}) != 0){
+            $statement = $db->prepare("
+              INSERT INTO unit_rune (unit, rune, rta)
+              VALUES (:unit, :rune, :rta);
+            ");
+            $statement->bindValue(":unit", $rune->{"occupied_id"}, SQLITE3_INTEGER);
+            $statement->bindValue(":rune", $rune->{"rune_id"}, SQLITE3_INTEGER);
+            $statement->bindValue(":rta", GAME_MODE_ID::NORMAL, SQLITE3_INTEGER);
+            $statement->execute();
         }
-        $statement->execute();
     }
 
     /**
@@ -543,6 +527,12 @@
         $statement = $db->prepare("DELETE FROM unit_skill WHERE unit IN (SELECT id FROM unit WHERE uid = :uid);");
         $statement->bindValue(":uid", $uid, SQLITE3_INTEGER);
         $statement->execute();
+        $statement = $db->prepare("DELETE FROM unit_rune WHERE unit IN (SELECT id FROM unit WHERE uid = :uid);");
+        $statement->bindValue(":uid", $uid, SQLITE3_INTEGER);
+        $statement->execute();
+        $statement = $db->prepare("DELETE FROM rune_stat WHERE rune IN (SELECT id FROM rune WHERE uid = :uid);");
+        $statement->bindValue(":uid", $uid, SQLITE3_INTEGER);
+        $statement->execute();
         $tables_to_clear = [
             "scenario",
             "defense",
@@ -876,7 +866,7 @@
             }
         }
 
-        // Parse invetory
+        // Parse inventory
         foreach ($json->{"inventory_info"} as $item){
             $statement = $db->prepare("
               INSERT INTO inventory (
@@ -968,6 +958,16 @@
                 parse_rune($uid, $rune, $rune_lock_list);
             }
         }
+        foreach ($json->{"world_arena_rune_equip_list"} as $rta_rune){
+            $statement = $db->prepare("
+              INSERT INTO unit_rune (unit, rune, rta)
+              VALUES (:unit, :rune, :rta);
+            ");
+            $statement->bindValue(":unit", $rta_rune->{"occupied_id"}, SQLITE3_INTEGER);
+            $statement->bindValue(":rune", $rta_rune->{"rune_id"}, SQLITE3_INTEGER);
+            $statement->bindValue(":rta", GAME_MODE_ID::RTA, SQLITE3_INTEGER);
+            $statement->execute();
+        }
 
         // Parse artifacts
         foreach ($json->{"artifacts"} as $artifact){

+ 65 - 0
application/Constant.php

@@ -1433,6 +1433,71 @@
         const TOLERANCE = 23;
     };
 
+
+    /**
+     * Rune stat slot constants.
+     *
+     * Includes all the stat slots a rune can have.
+     *
+     * @category Data
+     */
+    final class RUNE_STAT_SLOT_ID{
+
+        /**
+         * Main stat.
+         */
+        const MAIN = -1;
+
+        /**
+         * Innate stat.
+         */
+        const INNATE = 0;
+
+        /**
+         * Substat 1.
+         */
+        const SUBSTAT_1 = 1;
+
+        /**
+         * Substat 2.
+         */
+        const SUBSTAT_2 = 2;
+
+        /**
+         * Substat 3.
+         */
+        const SUBSTAT_3 = 3;
+
+        /**
+         * Substat 4.
+         */
+        const SUBSTAT_4 = 4;
+
+    }
+
+
+    /**
+     * Application modes.
+     *
+     * Modes to use RTA configurations or normal configuration.
+     *
+     * @category Data
+     */
+    final class GAME_MODE_ID{
+
+        /**
+         * Normal mode.
+         */
+        const NORMAL = 0;
+
+        /**
+         * RTA mode.
+         */
+        const RTA = 1;
+
+    }
+
+
     /**
      * Rune stat constants.
      *

+ 22 - 0
application/Controller.php

@@ -24,6 +24,11 @@
      */
     $UID = 0;
 
+    /**
+     * @global int $MODE.
+     */
+    $MODE = GAME_MODE_ID::NORMAL;
+
     /**
      * @global resource $DB.
      */
@@ -53,6 +58,7 @@
         public function __construct($params){
 
             global $UID;
+            global $MODE;
             global $db;
 
             $page = null;
@@ -99,6 +105,11 @@
             // Not redirecting to page, just execute a function
             elseif (count($pars) > 1 && strtoupper($pars[0]) == "ACTION"){
                 switch (strtoupper($pars[1])){
+                    case "CHANGE_GAME_MODE":
+                        require_once(PATH::ACTION . "change_game_mode.php");
+                        action();
+                        return;
+                        break;
                     case "LOGIN":
                         require_once(PATH::ACTION . "login.php");
                         action();
@@ -216,6 +227,17 @@
                 return;
             }
 
+            // Get game mode
+            $statement = $db->prepare("SELECT mode FROM player WHERE uid = :uid;");
+            $statement->bindValue(":uid", $UID);
+            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+            if ($r && $r["mode"] == GAME_MODE_ID::RTA){
+                $MODE = GAME_MODE_ID::RTA;
+            }
+            else{
+                $MODE = GAME_MODE_ID::NORMAL;
+            }
+
             // Select the model to load.
             array_shift($pars); // Remove first one, should be UID
             if (sizeof($pars) == 0){

+ 43 - 0
application/action/change_game_mode.php

@@ -0,0 +1,43 @@
+<?php
+
+    /**
+     * File for the team score modification.
+     *
+     * Implements an action function to be called from the {@see Controller}.
+     * 
+     * @category Action
+     */
+
+    /**
+     * Sets the score for a team.
+     *
+     * Reads the POST parameters looking for the following KEYS:
+     *  uid
+     *  team
+     *  score
+     * Validates the data and sets the score.
+     * 
+     * @return int 0 on success, negative values on error.
+     * @category Action
+     * @global resource Database connection.
+     */
+    function action(){
+        global $db;
+        $player = filter_input(INPUT_GET, "uid");
+        $mode = filter_input(INPUT_GET, "mode");
+        if (mode != GAME_MODE_ID::NORMAL && mode != GAME_MODE_ID::RTA){
+            return 400;
+        }
+        $statement = $db->prepare("
+          UPDATE player
+          SET mode = :mode
+          WHERE uid = :uid;
+        ");
+        $statement->bindValue(":mode", $mode, SQLITE3_INTEGER);
+        $statement->bindValue(":uid", $player, SQLITE3_INTEGER);
+        $statement->execute();
+        header("HTTP/1.1 201 OK");
+        die();
+        return 201;
+    }
+?>

+ 0 - 1
application/action/login.php

@@ -52,7 +52,6 @@
         $statement->execute();
         $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
         if (!$r){
-            error_log("REDIRECT TO:" . URL::BASE);
             header("Location: " . URL::BASE);
             exit();
             die();

+ 32 - 26
application/action/optimize_get_rune_list.php

@@ -26,6 +26,7 @@
     function action(){
 
         global $db;
+        global $MODE;
 
         // Increase max execution time.
         set_time_limit(60);
@@ -92,18 +93,18 @@
             slot,
             level,
             stars,
-            main_stat,
-            main_stat_value,
-            innate_stat,
-            innate_stat_value,
-            substat_1,
-            substat_1_value + substat_1_grind AS substat_1_value,
-            substat_2,
-            substat_2_value + substat_2_grind AS substat_2_value,
-            substat_3,
-            substat_3_value + substat_3_grind AS substat_3_value,
-            substat_4,
-            substat_4_value + substat_4_grind AS substat_4_value
+            (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::MAIN . " ) AS main_stat,
+            (SELECT value FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::MAIN . " ) AS main_stat_value,
+            (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::INNATE . " ) AS innate_stat,
+            (SELECT value FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::INNATE . " ) AS innate_stat_value,
+            (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_1 . " ) AS substat_1,
+            (SELECT value + grind FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_1 . " ) AS substat_1_value,
+            (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_2 . " ) AS substat_2,
+            (SELECT value + grind FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_2 . " ) AS substat_2_value,
+            (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_3 . " ) AS substat_3,
+            (SELECT value + grind FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_3 . " ) AS substat_3_value,
+            (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_4 . " ) AS substat_4,
+            (SELECT value + grind FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_4 . " ) AS substat_4_value
           FROM rune
           WHERE
             uid = :uid AND
@@ -117,33 +118,38 @@
             case 0: // Storage only (or itself)
                 $base_s .= "
                   (
-                    assigned_to = :unit_id OR
-                    assigned_to IS NULL
+                    rune.id IN (SELECT DISTINCT unit FROM unit_rune WHERE unit = :unit_id AND rta = $MODE)
+                    OR rune.id NOT IN (SELECT DISTINCT unit FROM unit_rune WHERE rta = $MODE)
                   )";
                 break;
             case 1: // Units in no teams (or itself)
                 $base_s .= "
                   (
-                    assigned_to = :unit_id OR
-                    assigned_to IS NULL OR 
-                    assigned_to NOT IN (SELECT DISTINCT unit FROM team_unit)
+                    rune.id IN (SELECT DISTINCT unit FROM unit_rune WHERE unit = :unit_id AND rta = $MODE)
+                    OR rune.id NOT IN (SELECT DISTINCT unit FROM unit_rune WHERE rta = $MODE)
+                    OR rune.id NOT IN (SELECT DISTINCT unit FROM unit_rune WHERE rta = $MODE AND unit NOT IN (SELECT DISTINCT unit FROM team_unit))
                   )
                 ";
                 break;
             case 2: // Units in teams with 0 score (or itself)
                 $base_s .= "
                   (
-                    assigned_to = :unit_id OR
-                    assigned_to IS NULL OR 
-                    assigned_to NOT IN (SELECT DISTINCT unit FROM team_unit) OR
-                    assigned_to NOT IN (
+                    rune.id IN (SELECT DISTINCT unit FROM unit_rune WHERE unit = :unit_id AND rta = $MODE)
+                    OR rune.id NOT IN (SELECT DISTINCT unit FROM unit_rune WHERE rta = $MODE)
+                    OR rune.id NOT IN (
                       SELECT DISTINCT unit 
-                      FROM
-                        team,
-                        team_unit
+                      FROM unit_rune 
                       WHERE
-                        team.id = team_unit.team AND
-                        team.score > 0
+                        rta = $MODE
+                        AND unit NOT IN (
+                          SELECT DISTINCT unit 
+                          FROM
+                            team,
+                            team_unit
+                          WHERE
+                            team.id = team_unit.team
+                            AND team.score > 0
+                        )
                     )
                   )
                 ";

+ 115 - 21
application/entity/Run.php

@@ -347,32 +347,57 @@
                         $rune->ancient = $r["ancient"];
                         $rune->quality = $r["quality"];
                         $rune->original_quality = $r["quality"];
+                        $rune->quality_name = $this->get_rune_quality_name($r["quality"]);
+                        $rune->original_quality_name = $this->get_rune_quality_name($r["quality"]);
                         $rune->value = $r["value"];
                         $rune->value = 0;
                         $rune->efficiency = $r["efficiency"];
                         // TODO: Calculate?
                         $rune->max_efficiency = $r["efficiency"];
-                        $rune->main_stat = $r["main_stat"];
-                        $rune->main_stat_value = $r["main_stat_value"];
-                        $rune->innate_stat = $r["innate_stat"];
-                        $rune->innate_stat_value = $r["innate_stat_value"];
-                        $rune->substat_1 = $r["substat_1"];
-                        $rune->substat_1_value = $r["substat_1_value"];
-                        $rune->substat_1_enchant = 0;
-                        $rune->substat_1_grind = 0;
-                        $rune->substat_2 = $r["substat_2"];
-                        $rune->substat_2_value = $r["substat_2_value"];
-                        $rune->substat_2_enchant = 0;
-                        $rune->substat_2_grind = 0;
-                        $rune->substat_3 = $r["substat_3"];
-                        $rune->substat_3_value = $r["substat_3_value"];
-                        $rune->substat_3_enchant = 0;
-                        $rune->substat_3_grind = 0;
-                        $rune->substat_4 = $r["substat_4"];
-                        $rune->substat_4_value = $r["substat_4_value"];
-                        $rune->substat_4_enchant = 0;
-                        $rune->substat_4_grind = 0;
-                        $rune->refresh_names();
+                        $rune->main_stat = new Rune_Stat(null, null);
+                        $rune->main_stat->slot = RUNE_STAT_SLOT_ID::MAIN;
+                        $rune->main_stat->stat = $r["main_stat"];
+                        $rune->main_stat->stat_name = $this->get_stat_name($r["main_stat"]);
+                        $rune->main_stat->value = $r["main_stat_value"];
+                        if ($r["innate_stat"] != null){
+                            $rune->innate_stat = new Rune_Stat(null, null);
+                            $rune->innate_stat->slot = RUNE_STAT_SLOT_ID::INNATE;
+                            $rune->innate_stat->stat = $r["innate_stat"];
+                            $rune->innate_stat->stat_name = $this->get_stat_name($r["innate_stat"]);
+                            $rune->innate_stat->value = $r["innate_stat_value"];
+                        }
+                        if ($r["substat_1"] != null){
+                            $substat = new Rune_Stat(null, null);
+                            $substat->slot = RUNE_STAT_SLOT_ID::SUBSTAT_1;
+                            $substat->stat = $r["substat_1"];
+                            $substat->stat_name = $this->get_stat_name($r["substat_1"]);
+                            $substat->value = $r["substat_1_value"];
+                            array_push($rune->substats, $substat);
+                        }
+                        if ($r["substat_2"] != null){
+                            $substat = new Rune_Stat(null, null);
+                            $substat->slot = RUNE_STAT_SLOT_ID::SUBSTAT_2;
+                            $substat->stat = $r["substat_2"];
+                            $substat->stat_name = $this->get_stat_name($r["substat_2"]);
+                            $substat->value = $r["substat_2_value"];
+                            array_push($rune->substats, $substat);
+                        }
+                        if ($r["substat_3"] != null){
+                            $substat = new Rune_Stat(null, null);
+                            $substat->slot = RUNE_STAT_SLOT_ID::SUBSTAT_3;
+                            $substat->stat = $r["substat_3"];
+                            $substat->stat_name = $this->get_stat_name($r["substat_3"]);
+                            $substat->value = $r["substat_3_value"];
+                            array_push($rune->substats, $substat);
+                        }
+                        if ($r["substat_4"] != null){
+                            $substat = new Rune_Stat(null, null);
+                            $substat->slot = RUNE_STAT_SLOT_ID::SUBSTAT_4;
+                            $substat->stat = $r["substat_4"];
+                            $substat->stat_name = $this->get_stat_name($r["substat_4"]);
+                            $substat->value = $r["substat_4_value"];
+                            array_push($rune->substats, $substat);
+                        }
                     }
                     array_push($this->rune, $rune);
                 }
@@ -433,5 +458,74 @@
             }
         }
 
+        /**
+         * Gets a quality name frm the mappings.
+         *
+         * @param int $quality Quality id.
+         * @return string Quality name (Uppercase)
+         */
+        private function get_rune_quality_name($quality){
+            switch ($quality){
+                case QUALITY_ID::NORMAL:
+                    return "NORMAL";
+                case QUALITY_ID::MAGIC:
+                    return "MAGIC";
+                case QUALITY_ID::RARE:
+                    return "RARE";
+                case QUALITY_ID::HERO:
+                    return "HERO";
+                case QUALITY_ID::LEGEND:
+                    return "LEGEND";
+                default:
+                    return "";
+            }
+        }
+
+        /**
+         * Gets a stat name from the mappings.
+         *
+         * @param int $stat Stat id.
+         * @return string Stat name (Uppercase)
+         */
+        private function get_stat_name($stat){
+            switch ($stat){
+                case RUNE_STAT_ID::HP:
+                    return "HP";
+                    break;
+                case RUNE_STAT_ID::HP_P:
+                    return "HP%";
+                    break;
+                case RUNE_STAT_ID::ATK:
+                    return "ATK";
+                    break;
+                case RUNE_STAT_ID::ATK_P:
+                    return "ATK%";
+                    break;
+                case RUNE_STAT_ID::DEF:
+                    return "DEF";
+                    break;
+                case RUNE_STAT_ID::DEF_P:
+                    return "DEF%";
+                    break;
+                case RUNE_STAT_ID::SPD:
+                    return "SPD";
+                    break;
+                case RUNE_STAT_ID::CRR:
+                    return "CRR";
+                    break;
+                case RUNE_STAT_ID::CRD:
+                    return "CRD";
+                    break;
+                case RUNE_STAT_ID::RES:
+                    return "RES";
+                    break;
+                case RUNE_STAT_ID::ACC:
+                    return "ACC";
+                    break;
+                default:
+                    return "";
+            }
+        }
+
     }
 ?>

+ 55 - 217
application/entity/Rune.php

@@ -12,6 +12,7 @@
      */
     require_once(PATH::ENTITY . "Entity.php");
     require_once(PATH::ENTITY . "K_Rune_Set.php");
+    require_once(PATH::ENTITY . "Rune_Stat.php");
 
     /**
      * Owned rune.
@@ -32,11 +33,6 @@
          */
         public $id;
 
-        /**
-         * @var int ID of the monster the rune is assigned to.
-         */
-        public $assigned_to;
-
         /**
          * @var K_Rune_Set Rune set.
          */
@@ -102,131 +98,36 @@
         public $max_efficiency;
 
         /**
-         * @var int Main stat of the rune.
-         *
-         * @see RUNE_STAT_ID
+         * @var int Indicates if the rune is locked.
          */
-        public $main_stat;
+        public $locked;
 
         /**
-         * @var string Main stat name (uppercase).
+         * @var Rune_Stat Main stat of the rune.
          */
-        public $main_stat_name;
-
-        /**
-         * @var int Main stat value of the rune.
-         */
-        public $main_stat_value;
+        public $main_stat;
 
         /**
-         * @var int Extra stat of the rune.
-         *
-         * @see RUNE_STAT_ID
+         * @var Rune_Stat Extra stat of the rune.
          */
         public $innate_stat;
 
         /**
-         * @var string Extra stat name (uppercase).
-         */
-        public $innate_stat_name;
-
-        /**
-         * @var string Extra stat value of the rune.
-         */
-        public $innate_stat_value;
-
-        /**
-         * @var int Number of substats.
-         */
-        public $substats;
-
-        /**
-         * @var int Substat 1 of the rune.
-         *
-         * @see RUNE_STAT_ID
-         */
-        public $substat_1;
-
-        /**
-         * @var string Substat 1 name (uppercase).
-         */
-        public $substat_1_name;
-
-        /**
-         * @var int Substat 1 value of the rune.
-         */
-        public $substat_1_value;
-
-        /**
-         * @var int Ammount gained by the substat 1 enchant.
-         */
-        public $substat_1_craft;
-
-        /**
-         * @var int Substat 2 of the rune.
-         *
-         * @see RUNE_STAT_ID
-         */
-        public $substat_2;
-
-        /**
-         * @var string Substat 2 name (uppercase).
+         * @var \Rune_Stat[] Substats of the rune.
          */
-        public $substat_2_name;
+        public $substats = [];
 
         /**
-         * @var int Substat 2 value of the rune.
-         */
-        public $substat_2_value;
-
-        /**
-         * @var int Ammount gained by the substat 2 enchant.
-         */
-        public $substat_2_craft;
-
-        /**
-         * @var int Substat 3 of the rune.
-         *
-         * @see RUNE_STAT_ID
-         */
-        public $substat_3;
-
-        /**
-         * @var string Substat 3 name (uppercase).
-         */
-        public $substat_3_name;
-
-        /**
-         * @var int Substat 3 value of the rune.
-         */
-        public $substat_3_value;
-
-        /**
-         * @var int Ammount gained by the substat 3 enchant.
-         */
-        public $substat_3_craft;
-
-        /**
-         * @var int Substat 4 of the rune.
+         * @var \Rune_Stat[] All stats.
          *
-         * @see RUNE_STAT_ID
+         * Includes main, innate and substats
          */
-        public $substat_4;
+        public $stats = [];
 
         /**
-         * @var string Substat 4 name (uppercase).
+         * @var Unit Unit the rune is assigned to.
          */
-        public $substat_4_name;
-
-        /**
-         * @var int Substat 4 value of the rune.
-         */
-        public $substat_4_value;
-
-        /**
-         * @var int Ammount gained by the substat 4 enchant.
-         */
-        public $substat_4_craft;
+        public $unit;
 
         /**
          * Constructor.
@@ -244,7 +145,6 @@
             $statement = $db->prepare("
               SELECT
                 id,
-                assigned_to,
                 type,
                 slot,
                 stars,
@@ -255,26 +155,7 @@
                 value,
                 efficiency,
                 max_efficiency,
-                main_stat,
-                main_stat_value,
-                innate_stat,
-                innate_stat_value,
-                substat_1,
-                substat_1_value,
-                substat_1_enchant,
-                substat_1_grind,
-                substat_2,
-                substat_2_value,
-                substat_2_enchant,
-                substat_2_grind,
-                substat_3,
-                substat_3_value,
-                substat_3_enchant,
-                substat_3_grind,
-                substat_4,
-                substat_4_value,
-                substat_4_enchant,
-                substat_4_grind
+                locked
               FROM rune
               WHERE id = :id;
             ");
@@ -282,7 +163,6 @@
             $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
             if ($r){
                 $this->id = $r["id"];
-                $this->assigned_to = $r["assigned_to"];
                 $this->type = new K_Rune_Set($r["type"]);
                 $this->slot = $r["slot"];
                 $this->stars = $r["stars"];
@@ -293,27 +173,34 @@
                 $this->value = $r["value"];
                 $this->efficiency = $r["efficiency"];
                 $this->max_efficiency = $r["max_efficiency"];
-                $this->main_stat = $r["main_stat"];
-                $this->main_stat_value = $r["main_stat_value"];
-                $this->innate_stat = $r["innate_stat"];
-                $this->innate_stat_value = $r["innate_stat_value"];
-                $this->substat_1 = $r["substat_1"];
-                $this->substat_1_value = $r["substat_1_value"];
-                $this->substat_1_enchant = $r["substat_1_enchant"];
-                $this->substat_1_grind = $r["substat_1_grind"];
-                $this->substat_2 = $r["substat_2"];
-                $this->substat_2_value = $r["substat_2_value"];
-                $this->substat_2_enchant = $r["substat_2_enchant"];
-                $this->substat_2_grind = $r["substat_2_grind"];
-                $this->substat_3 = $r["substat_3"];
-                $this->substat_3_value = $r["substat_3_value"];
-                $this->substat_3_enchant = $r["substat_3_enchant"];
-                $this->substat_3_grind = $r["substat_3_grind"];
-                $this->substat_4 = $r["substat_4"];
-                $this->substat_4_value = $r["substat_4_value"];
-                $this->substat_4_enchant = $r["substat_4_enchant"];
-                $this->substat_4_grind = $r["substat_4_grind"];
-                $this->refresh_names();
+                $this->locked = $r["locked"];
+
+                // Get substats
+                $statement = $db->prepare("
+                  SELECT slot
+                  FROM rune_stat
+                  WHERE rune = :rune
+                  ORDER BY slot;
+                ");
+                $statement->bindValue(':rune', $this->id, SQLITE3_INTEGER);
+                $q = $statement->execute();
+                while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                    $stat = new Rune_Stat($this->id, $r["slot"]);
+                    array_push($this->stats, $stat);
+                    switch ($r["slot"]){
+                        case RUNE_STAT_SLOT_ID::MAIN:
+                            $this->main_stat = $stat;
+                            break;
+                        case RUNE_STAT_SLOT_ID::INNATE:
+                            $this->innate_stat = $stat;
+                            break;
+                        default:
+                            array_push($this->substats, $stat);
+                            break;
+                    }
+                }
+                $this->quality_name = $this->get_quality_name($this->quality);
+                $this->original_quality_name = $this->get_quality_name($this->original_quality);
             }
         }
 
@@ -328,80 +215,31 @@
             if ($level < 0 || $level > 15){
                 return 0;
             }
-            switch ($this->main_stat){
-                    case RUNE_STAT_ID::HP:
-                        return RUNE_STAT_VALUES::HP[$this->stars][$level];
-                    case RUNE_STAT_ID::HP_P:
-                        return RUNE_STAT_VALUES::HP_P[$this->stars][$level];
-                    case RUNE_STAT_ID::ATK:
-                        return RUNE_STAT_VALUES::ATK[$this->stars][$level];
-                    case RUNE_STAT_ID::ATK_P:
-                        return RUNE_STAT_VALUES::ATK_P[$this->stars][$level];
-                    case RUNE_STAT_ID::DEF:
-                        return RUNE_STAT_VALUES::DEF[$this->stars][$level];
-                    case RUNE_STAT_ID::DEF_P:
-                        return RUNE_STAT_VALUES::DEF_P[$this->stars][$level];
-                    case RUNE_STAT_ID::SPD:
-                        return RUNE_STAT_VALUES::SPD[$this->stars][$level];
-                    case RUNE_STAT_ID::CRR:
-                        return RUNE_STAT_VALUES::CRR[$this->stars][$level];
-                    case RUNE_STAT_ID::CRD:
-                        return RUNE_STAT_VALUES::CRD[$this->stars][$level];
-                    case RUNE_STAT_ID::RES:
-                        return RUNE_STAT_VALUES::RES[$this->stars][$level];
-                    case RUNE_STAT_ID::ACC:
-                        return RUNE_STAT_VALUES::ACC[$this->stars][$level];
-                    default:
-                        return 0;
-            }
-        }
-
-        /**
-         * Calculates name variables.
-         */
-        public function refresh_names(){
-            $this->main_stat_name = $this->stat_name($this->main_stat);
-            $this->innate_stat_name = $this->stat_name($this->innate_stat);
-            $this->substat_1_name = $this->stat_name($this->substat_1);
-            $this->substat_2_name = $this->stat_name($this->substat_2);
-            $this->substat_3_name = $this->stat_name($this->substat_3);
-            $this->substat_4_name = $this->stat_name($this->substat_4);
-            $this->quality_name = $this->get_quality_name($this->quality);
-            $this->original_quality_name = $this->get_quality_name($this->original_quality);
-        }
-
-        /**
-         * Gets a stat name from the mappings.
-         *
-         * @param int $stat Stat id.
-         * @return string Stat name (Uppercase)
-         */
-        private function stat_name($stat){
-            switch ($stat){
+            switch ($this->main_stat->stat){
                 case RUNE_STAT_ID::HP:
-                    return "HP";
+                    return RUNE_STAT_VALUES::HP[$this->stars][$level];
                 case RUNE_STAT_ID::HP_P:
-                    return "HP%";
+                    return RUNE_STAT_VALUES::HP_P[$this->stars][$level];
                 case RUNE_STAT_ID::ATK:
-                    return "ATK";
+                    return RUNE_STAT_VALUES::ATK[$this->stars][$level];
                 case RUNE_STAT_ID::ATK_P:
-                    return "ATK%";
+                    return RUNE_STAT_VALUES::ATK_P[$this->stars][$level];
                 case RUNE_STAT_ID::DEF:
-                    return "DEF";
+                    return RUNE_STAT_VALUES::DEF[$this->stars][$level];
                 case RUNE_STAT_ID::DEF_P:
-                    return "DEF%";
+                    return RUNE_STAT_VALUES::DEF_P[$this->stars][$level];
                 case RUNE_STAT_ID::SPD:
-                    return "SPD";
+                    return RUNE_STAT_VALUES::SPD[$this->stars][$level];
                 case RUNE_STAT_ID::CRR:
-                    return "CRR";
+                    return RUNE_STAT_VALUES::CRR[$this->stars][$level];
                 case RUNE_STAT_ID::CRD:
-                    return "CRD";
+                    return RUNE_STAT_VALUES::CRD[$this->stars][$level];
                 case RUNE_STAT_ID::RES:
-                    return "RES";
+                    return RUNE_STAT_VALUES::RES[$this->stars][$level];
                 case RUNE_STAT_ID::ACC:
-                    return "ACC";
+                    return RUNE_STAT_VALUES::ACC[$this->stars][$level];
                 default:
-                    return "";
+                    return 0;
             }
         }
 

+ 131 - 0
application/entity/Rune_Stat.php

@@ -0,0 +1,131 @@
+<?php
+    /**
+     * Rune stat entity file.
+     *
+     * Creates the entity and makes it available.
+     *
+     * @category Entity
+     */
+
+    /**
+     * Require dependent entities if not present.
+     */
+    require_once(PATH::ENTITY . "Entity.php");
+
+    /**
+     * Rune_stat.
+     *
+     * Represents an object from the table 'rune'.
+     *
+     * @category Entity
+     */
+    class Rune_Stat extends Entity{
+
+        /**
+         * @var int Stat slot.
+         *
+         * @see RUNE_STAT_SLOT_ID
+         */
+        public $slot;
+
+        /**
+         * @var int Substat 1 of the rune.
+         *
+         * @see RUNE_STAT_ID
+         */
+        public $stat;
+
+        /**
+         * @var string Substat 1 name (uppercase).
+         */
+        public $stat_name = "";
+
+        /**
+         * @var int Substat 1 value of the rune.
+         */
+        public $value;
+
+        /**
+         * @var int Ammount gained by the substat 1 enchant.
+         */
+        public $grind;
+
+        /**
+         * @var int Indicates if a gem has been used.
+         */
+        public $enchant;
+
+        /**
+         * Constructor.
+         *
+         * Searches the database and retrieves the information about the
+         * rune, populating it and it's items.
+         *
+         * @param int $id Rune id.
+         * @global resource Database connection.
+         */
+        public function __construct($rune, $slot){
+
+            global $db;
+
+            $statement = $db->prepare("
+              SELECT
+                slot,
+                stat,
+                value,
+                enchant,
+                grind
+              FROM rune_stat
+              WHERE
+                rune = :rune AND
+                slot = :slot;
+            ");
+            $statement->bindValue(':rune', $rune, SQLITE3_INTEGER);
+            $statement->bindValue(':slot', $slot, SQLITE3_INTEGER);
+            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+            if ($r){
+                $this->slot = $r["slot"];
+                $this->stat = $r["stat"];
+                $this->value = $r["value"];
+                $this->enchant = $r["enchant"];
+                $this->grind = $r["grind"];
+                switch ($this->stat){
+                    case RUNE_STAT_ID::HP:
+                        $this->stat_name = "HP";
+                        break;
+                    case RUNE_STAT_ID::HP_P:
+                        $this->stat_name = "HP%";
+                        break;
+                    case RUNE_STAT_ID::ATK:
+                        $this->stat_name = "ATK";
+                        break;
+                    case RUNE_STAT_ID::ATK_P:
+                        $this->stat_name = "ATK%";
+                        break;
+                    case RUNE_STAT_ID::DEF:
+                        $this->stat_name = "DEF";
+                        break;
+                    case RUNE_STAT_ID::DEF_P:
+                        $this->stat_name = "DEF%";
+                        break;
+                    case RUNE_STAT_ID::SPD:
+                        $this->stat_name = "SPD";
+                        break;
+                    case RUNE_STAT_ID::CRR:
+                        $this->stat_name = "CRR";
+                        break;
+                    case RUNE_STAT_ID::CRD:
+                        $this->stat_name = "CRD";
+                        break;
+                    case RUNE_STAT_ID::RES:
+                        $this->stat_name = "RES";
+                        break;
+                    case RUNE_STAT_ID::ACC:
+                        $this->stat_name = "ACC";
+                        break;
+                }
+            }
+        }
+
+    }
+?>

+ 13 - 11
application/entity/Unit.php

@@ -519,32 +519,34 @@
          * Calculates the totalls and the effective stats.
          *
          * @gobal int User ID.
+         * @gobal int Game mode (Normal/RTA).
          * @global resource Database connection.
          */
         public function load_stats(){
 
             global $UID;
+            global $MODE;
             global $db;
 
             // Runes
             $this->rune = [];
             $statement = $db->prepare("
-              SELECT id
-              FROM rune
-              WHERE assigned_to = :assigned;
+              SELECT rune
+              FROM unit_rune
+              WHERE
+                unit = :unit AND
+                rta = :rta;
             ");
-            $statement->bindValue(':assigned', $this->id, SQLITE3_INTEGER);
+            $statement->bindValue(':unit', $this->id, SQLITE3_INTEGER);
+            $statement->bindValue(':rta', $MODE, SQLITE3_INTEGER);
             $q = $statement->execute();
             while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->rune, new Rune($r["id"]));
+                array_push($this->rune, new Rune($r["rune"]));
             }
             foreach ($this->rune as $rune){
-                $this->sum_rune_stat($rune->main_stat, $rune->main_stat_value);
-                $this->sum_rune_stat($rune->innate_stat, $rune->innate_stat_value);
-                $this->sum_rune_stat($rune->substat_1, $rune->substat_1_value + $rune->substat_1_grind);
-                $this->sum_rune_stat($rune->substat_2, $rune->substat_2_value + $rune->substat_2_grind);
-                $this->sum_rune_stat($rune->substat_3, $rune->substat_3_value + $rune->substat_3_grind);
-                $this->sum_rune_stat($rune->substat_4, $rune->substat_4_value + $rune->substat_4_grind);
+                foreach ($rune->stats as $stat){
+                    $this->sum_rune_stat($stat->stat, $stat->value + $stat->grind);
+                }
             }
             $this->rune_attack = ceil($this->rune_attack);
             $this->rune_defense = ceil($this->rune_defense);

+ 23 - 27
application/helper/HTML_Helper.php

@@ -225,13 +225,13 @@
             // Main stat
             $html .= "<tr class='main_stat'>\n";
             $html .= "<td class='stat'>\n";
-            if (in_array($rune->main_stat_name, array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
-                $stat_name = str_replace("%", "", $rune->main_stat_name);
-                $stat_value = "+" . $rune->main_stat_value . "%";
+            if (in_array($rune->main_stat->stat_name, array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
+                $stat_name = str_replace("%", "", $rune->main_stat->stat_name);
+                $stat_value = "+" . $rune->main_stat->value . "%";
             }
             else{
-                $stat_name = $rune->main_stat_name;
-                $stat_value = "+" . $rune->main_stat_value. "&nbsp;";
+                $stat_name = $rune->main_stat->stat_name;
+                $stat_value = "+" . $rune->main_stat->value. "&nbsp;";
             }
             $html .= $stat_name . "\n";
             $html .= "</td>\n";
@@ -246,17 +246,17 @@
             // Innate stat
             $html .= "<tr class='innate_stat'>\n";
             $html .= "<td class='stat'>\n";
-            if (strlen($rune->innate_stat) == 0){
+            if ($rune->innate_stat == null){
                 $stat_name = "&nbsp;";
                 $stat_value = "";
             }
-            elseif (in_array($rune->innate_stat_name, array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
-                $stat_name = str_replace("%", "", $rune->innate_stat_name);
-                $stat_value = "+" . $rune->innate_stat_value . "%";
+            elseif (in_array($rune->innate_stat->stat_name, array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
+                $stat_name = str_replace("%", "", $rune->innate_stat->stat_name);
+                $stat_value = "+" . $rune->innate_stat->value . "%";
             }
             else{
-                $stat_name = $rune->innate_stat_name;
-                $stat_value = "+" . $rune->innate_stat_value. "&nbsp;";;
+                $stat_name = $rune->innate_stat->stat_name;
+                $stat_value = "+" . $rune->innate_stat->value. "&nbsp;";
             }
             $html .= $stat_name . "\n";
             $html .= "</td>\n";
@@ -266,27 +266,23 @@
             $html .= "<td class='grind'>\n";
             $html .= "</td>\n";
             $html .= "</tr>\n";
-            $substats_name = array($rune->substat_1_name, $rune->substat_2_name, $rune->substat_3_name, $rune->substat_4_name);
-            $substats_value = array($rune->substat_1_value, $rune->substat_2_value, $rune->substat_3_value, $rune->substat_4_value);
-            $substats_grind = array($rune->substat_1_grind, $rune->substat_2_grind, $rune->substat_3_grind, $rune->substat_4_grind);
-            $substats_enchant = array($rune->substat_1_enchant, $rune->substat_2_enchant, $rune->substat_3_enchant, $rune->substat_4_enchant);
             for ($i = 0; $i < 4; $i ++){
-                if (strlen($substats_name[$i]) == 0){
+                if ($rune->substats[$i] == null){
                     $stat_name = "&nbsp;";
                     $stat_value = "";
                 }
-                elseif (in_array($substats_name[$i], array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
-                    $stat_name = str_replace("%", "", $substats_name[$i]);
-                    $stat_value = "+" . $substats_value[$i] . "%";
+                elseif (in_array($rune->substats[$i]->stat_name, array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
+                    $stat_name = str_replace("%", "", $rune->substats[$i]->stat_name);
+                    $stat_value = "+" . $rune->substats[$i]->value . "%";
                 }
                 else{
-                    $stat_name = $substats_name[$i];
-                    $stat_value = "+" . $substats_value[$i]. "&nbsp;";
+                    $stat_name = $rune->substats[$i]->stat_name;
+                    $stat_value = "+" . $rune->substats[$i]->value. "&nbsp;";
                 }
                 $grind = "";
-                if ($substats_grind[$i] > 0){
-                    $grind = "+" . $substats_grind[$i];
-                    if (in_array($substats_name[$i], array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
+                if ($rune->substats[$i] != null && $rune->substats[$i]->grind > 0){
+                    $grind = "+" . $rune->substats[$i]->grind;
+                    if (in_array($rune->substats[$i]->stat_name, array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
                         $grind = $grind . "%";
                     }
                 }
@@ -298,7 +294,7 @@
                 $html .= $stat_value . "\n";
                 $html .= "<td class='grind grind_$grind'>\n";
                 $html .= $grind . "\n";
-                if ($substats_enchant[$i] == 1){
+                if ($rune->substats[$i] != null && $rune->substats[$i]->enchant == 1){
                     $html .= "<img title='Enchanted' src='" . URL::IMG["RUNE"] . "enchanted.png'/>\n";
                 }
                 $html .= "</td>\n";
@@ -533,8 +529,8 @@
             $html .= "<img class='enchantment_base' src='" . $base . "'/>\n";
             $html .= $icon;
             $html .= "<span class='enchantment_stat'>\n";
-            $html .= "<span class='enchantment_stat_name'>" . $stat_name . "</span>\n";
-            $html .= "<span class='enchantment_stat_value'>" . $stat_value . "</span>\n";
+            $html .= "<span class='enchantment_stat->stat_name'>" . $stat_name . "</span>\n";
+            $html .= "<span class='enchantment_stat->value'>" . $stat_value . "</span>\n";
             $html .= "</span>\n";
             if ($enchantment->amount > 0){
                 $html .= "<span class='enchantment_amount'>\n";

+ 2 - 2
application/page/Monsters_Page.php

@@ -141,7 +141,7 @@
                 $s = $s . " AND building NOT IN (SELECT id FROM building WHERE building = " . BUILDING_ID::MONSTER_STORAGE . ") ";
             }
             if (!$this->filters["WITHOUT_RUNES"]){
-                $s = $s . " AND unit.id IN (SELECT DISTINCT assigned_to FROM rune) ";
+                $s = $s . " AND unit.id IN (SELECT DISTINCT unit FROM unit_rune) ";
             }
             if (sizeof($this->filters["EFFECT"]) > 0){
                 if ($this->filters["EFFECT_OPTION"] == "and"){
@@ -178,7 +178,7 @@
                 }
             }
             $s = $s . "
-                ORDER BY 
+                ORDER BY
                   stars DESC,
                   level DESC,
                   element = " . ELEMENT_ID::FIRE ." DESC,

+ 133 - 119
application/page/Report_Rune_Enchantment_Page.php

@@ -251,149 +251,163 @@
          */
         private function build_query(){
             global $UID;
+            global $MODE;
+
             $s = "
-                SELECT
-                  unit.id AS unit,
-                  rune.id AS rune,
-                  enchantment.id AS enchantment
-                FROM
-                  unit,
-                  k_unit,
-                  rune,
-                  enchantment,
-                  k_enchantment_type
-                WHERE
-                  unit.uid = '$UID' AND
-                  rune.uid = '$UID' AND
-                  enchantment.uid = '$UID' AND
-                  unit.id = rune.assigned_to AND
-                  unit.unit = k_unit.id AND
-                  enchantment.type = k_enchantment_type.id AND
-                  unit.stars >= " . $this->filters["RUNE_MIN_STARS"] . " AND
-                  unit.stars <= " . $this->filters["RUNE_MAX_STARS"] . " AND
-                  -- RUNE FILTERS
-                  rune.quality >= " . $this->filters["RUNE_MIN_QUALITY"] . " AND
-                  rune.quality <= " . $this->filters["RUNE_MAX_QUALITY"] . " AND
-                  rune.level >= " . $this->filters["RUNE_MIN_LEVEL"] . " AND
-                  rune.level <= " . $this->filters["RUNE_MAX_LEVEL"] . " AND
-                  rune.stars >= " . $this->filters["RUNE_MIN_STARS"] . " AND
-                  rune.stars <= " . $this->filters["RUNE_MAX_STARS"] . " AND
-                  rune.original_quality >= " . $this->filters["RUNE_MIN_ORIGINAL_QUALITY"] . " AND
-                  rune.original_quality <= " . $this->filters["RUNE_MAX_ORIGINAL_QUALITY"] . " AND
-                  rune.efficiency >= " . $this->filters["RUNE_MIN_EFFICIENCY"] . " AND
-                  rune.efficiency <= " . $this->filters["RUNE_MAX_EFFICIENCY"] . " AND
-                  rune.max_efficiency >= " . $this->filters["RUNE_MIN_MAX_EFFICIENCY"] . " AND
-                  rune.max_efficiency <= " . $this->filters["RUNE_MAX_MAX_EFFICIENCY"] . " AND
-                  (
-                    rune.type = enchantment.rune OR 
-                    k_enchantment_type.inmemorial = 1
-                  ) AND
-                  k_enchantment_type.ancient = rune.ancient AND
-                ";
+              SELECT DISTINCT
+                unit.id AS unit,
+                rune.id AS rune,
+                enchantment.id AS enchantment
+              FROM
+                unit,
+                k_unit,
+                rune,
+                unit_rune,
+                enchantment,
+                k_enchantment_type
+              WHERE 
+                unit.uid = '$UID'
+                AND rune.uid = '$UID'
+                AND enchantment.uid = '$UID'
+                AND unit.id = unit_rune.unit
+                AND rune.id = unit_rune.rune
+                AND unit_rune.rta = $MODE
+                AND unit.unit = k_unit.id
+                AND enchantment.type = k_enchantment_type.id
+                -- RUNE FILTERS
+                AND unit.stars >= " . $this->filters["RUNE_MIN_STARS"] . "
+                AND unit.stars <= " . $this->filters["RUNE_MAX_STARS"] . "
+                AND rune.quality >= " . $this->filters["RUNE_MIN_QUALITY"] . "
+                AND rune.quality <= " . $this->filters["RUNE_MAX_QUALITY"] . "
+                AND rune.level >= " . $this->filters["RUNE_MIN_LEVEL"] . "
+                AND rune.level <= " . $this->filters["RUNE_MAX_LEVEL"] . "
+                AND rune.stars >= " . $this->filters["RUNE_MIN_STARS"] . "
+                AND rune.stars <= " . $this->filters["RUNE_MAX_STARS"] . "
+                AND rune.original_quality >= " . $this->filters["RUNE_MIN_ORIGINAL_QUALITY"] . "
+                AND rune.original_quality <= " . $this->filters["RUNE_MAX_ORIGINAL_QUALITY"] . "
+                AND rune.efficiency >= " . $this->filters["RUNE_MIN_EFFICIENCY"] . "
+                AND rune.efficiency <= " . $this->filters["RUNE_MAX_EFFICIENCY"] . "
+                AND rune.max_efficiency >= " . $this->filters["RUNE_MIN_MAX_EFFICIENCY"] . "
+                AND rune.max_efficiency <= " . $this->filters["RUNE_MAX_MAX_EFFICIENCY"] . "
+                AND (
+                  rune.type = enchantment.rune
+                  OR k_enchantment_type.inmemorial = 1
+                )
+                AND k_enchantment_type.ancient = rune.ancient
+            ";
+
+            // Monster name
+            $cond = "";
             if (strlen($this->filters["MONSTER_NAME"]) > 0){
-                $s = $s . " upper(k_unit.name) LIKE upper('%" . $this->filters["MONSTER_NAME"] . "%') AND ";
+                $cond = "AND upper(k_unit.name) LIKE upper('%" . $this->filters["MONSTER_NAME"] . "%') ";
             }
+            $s .= $cond . " -- MONSTER NAME \n";
+
+            // Monsters in storage
+            $cond = "";
             if (!$this->filters["MONSTER_IN_STORAGE"]){
-                $s = $s . " unit.building <> " . BUILDING_ID::MONSTER_STORAGE . " AND ";
+                $cond = "AND unit.building <> " . BUILDING_ID::MONSTER_STORAGE . " ";
             }
+            $s .= $cond . " -- STORAGE \n";
+
+            // Rune slot
+            $cond = "";
             if (count($this->filters["RUNE_SLOT"]) > 0){
-                $s = $s . " rune.slot IN ( ";
+                $in = "(";
                 foreach($this->filters["RUNE_SLOT"] as $t){
-                    $s = $s . "$t, ";
+                    $in .= "$t, ";
                 }
-                $s = $s . "-1) AND ";
+                $in = rtrim($in, ", ") . ")";
+                $cond = "AND rune.slot IN $in";
             }
+            $s .= $cond . " -- RUNE SLOT \n";
+
+            // Nevermind the type, discard enchantments with the same stat as
+            // the main or inate substat
+            $s .= "
+              AND enchantment.stat NOT IN (
+                SELECT stat
+                FROM rune_stat
+                WHERE
+                  rune_stat.rune = rune.id
+                  AND (
+                    rune_stat.slot = " . RUNE_STAT_SLOT_ID::MAIN . "
+                    OR rune_stat.slot = " . RUNE_STAT_SLOT_ID::INNATE . "
+                  )
+              )
+            ";
+
+            // Begin type switch block
+            $s .= " AND ( -- TYPE SWITCH \n";
+
+            // Begin grindstone block
             $s .= "
-                enchantment.stat <> rune.main_stat AND
-                enchantment.stat <> rune.innate_stat AND
-                  (
-                    k_enchantment_type.gem = 1 AND
-                    (
-                      -- GEM FILTERS
-                      enchantment.quality >= " . $this->filters["GEM_MIN_QUALITY"] . " AND
+              (
+                k_enchantment_type.gem = 0
+                AND enchantment.stat IN (SELECT stat FROM rune_stat WHERE rune_stat.rune = rune.id)
+                AND enchantment.quality >= " . $this->filters["GRIND_MIN_QUALITY"] . " -- GRINDSTONE QUALITY
             ";
-            if (count($this->filters["GEM_STAT_FROM"]) > 0){
+
+            // Grindstone stat
+            $cond = "";
+            if (count($this->filters["GRIND_STAT"]) > 0){
                 $in = "(";
-                foreach($this->filters["GEM_STAT_FROM"] as $t){
-                    $in = $in . "$t, ";
+                foreach($this->filters["GRIND_STAT"] as $t){
+                    $in .= "$t, ";
                 }
-                $in = $in . "-1)";
-                $s .= " (rune.substat_1 IN $in OR rune.substat_2 IN $in OR rune.substat_3 IN $in OR rune.substat_4 IN $in) AND ";
+                $in = rtrim($in, ", ") . ")";
+                $cond = "AND enchantment.stat IN $in";
             }
+            $s .= $cond . " -- GRINDSTONE STAT \n";
+            $s .= "
+              )\n
+            ";
+
+            // Begin gem block
+            $s .= " OR (
+              k_enchantment_type.gem = 1
+              AND enchantment.stat NOT IN (SELECT stat FROM rune_stat WHERE rune_stat.rune = rune.id)
+              AND enchantment.quality >= " . $this->filters["GEM_MIN_QUALITY"] . " -- GEM QUALITY
+            ";
+
+            // Gem stat to
+            $cond = "";
             if (count($this->filters["GEM_STAT_TO"]) > 0){
                 $in = "(";
                 foreach($this->filters["GEM_STAT_TO"] as $t){
-                    $in = $in . "$t, ";
+                    $in .= "$t, ";
                 }
-                $in = $in . "-1)";
-                $s .= " enchantment.stat IN $in AND ";
+                $in = rtrim($in, ", ") . ")";
+                $cond = "AND enchantment.stat IN $in";
             }
-            $s .= "
-                      (
-                        enchantment.stat <> rune.substat_1 AND
-                        enchantment.stat <> rune.substat_2 AND
-                        enchantment.stat <> rune.substat_3 AND
-                        enchantment.stat <> rune.substat_4
-                      )
-                    )
-                  ) |
-                  (
-                    k_enchantment_type.gem = 0 AND
-                    (
-                      -- GRINDSTONE FILTERS
-            ";
-            if (count($this->filters["GRIND_STAT"]) > 0){
+            $s .= $cond . " -- GEM STAT TO \n";
+
+            // Gem stat from
+            $cond = "";
+            if (count($this->filters["GEM_STAT_FROM"]) > 0){
                 $in = "(";
-                foreach($this->filters["GRIND_STAT"] as $t){
-                    $in = $in . "$t, ";
+                foreach($this->filters["GEM_STAT_FROM"] as $t){
+                    $in .= "$t, ";
                 }
-                $in = $in . "-1)";
-                $s .= " enchantment.stat IN $in AND ";
-            }
-            $s .= "
-                      enchantment.quality >= " . $this->filters["GRIND_MIN_QUALITY"] . " AND
-                      (
-                        (
-                          enchantment.stat = rune.substat_1 AND
-                          enchantment.stat <> rune.substat_2 AND
-                          enchantment.stat <> rune.substat_3 AND
-                          enchantment.stat <> rune.substat_4 
-                        ) OR
-                        (
-                          enchantment.stat <> rune.substat_1 AND
-                          enchantment.stat = rune.substat_2 AND
-                          enchantment.stat <> rune.substat_3 AND
-                          enchantment.stat <> rune.substat_4
-                        ) OR
-                        (
-                          enchantment.stat <> rune.substat_1 AND
-                          enchantment.stat <> rune.substat_2 AND
-                          enchantment.stat = rune.substat_3 AND
-                          enchantment.stat <> rune.substat_4
-                        ) OR
-                        (
-                          enchantment.stat <> rune.substat_1 AND
-                          enchantment.stat <> rune.substat_2 AND
-                          enchantment.stat <> rune.substat_3 AND
-                          enchantment.stat = rune.substat_4
-                        )
-                      )
-                    )
+                $in = rtrim($in, ", ") . ")";
+                $cond = "
+                  AND rune.id IN(
+                    SELECT DISTINCT rune
+                    FROM rune_stat
+                    WHERE
+                      rune_stat.rune = rune.id
+                      AND stat IN $in
                   )
                 ";
+            }
+            $s .= $cond . " -- GEM STAT FROM \n";
             $s .= "
-                ORDER BY
-                  unit.stars DESC,
-                  unit.level DESC,
-                  unit.id,
-                  rune.stars DESC,
-                  rune.original_quality DESC,
-                  rune.level DESC,
-                  rune.id, 
-                  rune.slot, 
-                  enchantment.quality DESC,
-                  enchantment.stat DESC;
-                ";
+              )\n
+            ";
+
+            // End type switch block
+            $s .= " ) -- END TYPE SWITCH \n";
+
             return $s;
         }
     }

+ 4 - 2
application/page/Report_Skillup_Page.php

@@ -69,7 +69,7 @@
          * and adds them to the $filters array.
          */
         private function parse_filters(){
-            //$this->filters = FILTER::SKILLUP;
+
             if (isset($_GET["min_stars"]) && intval($_GET["min_stars"]) > 0 && intval($_GET["min_stars"]) < 7){
                 $this->filters["MIN_STARS"] = intval($_GET["min_stars"]);
             }
@@ -124,9 +124,11 @@
          *
          * @return string The query to be executed.
          * @global int Player ID.
+         * @global int Game mode.
          */
         private function build_query(){
             global $UID;
+            global $MODE;
             $s = "
               SELECT DISTINCT
                 unit.id AS id,
@@ -247,7 +249,7 @@
                 $s = $s . " AND unit.building <> " . BUILDING_ID::MONSTER_STORAGE;
             }
             if (!$this->filters["WITHOUT_RUNES"]){
-                $s = $s . " AND unit.id IN (SELECT DISTINCT assigned_to FROM rune) ";
+                $s = $s . " AND unit.id IN (SELECT DISTINCT unit FROM unit_rune WHERE rta = $MODE) ";
             }
             if (!$this->filters["FAMILY"]){
                 $s = $s . " AND unit.unit NOT IN (SELECT id FROM k_unit m WHERE family IN (SELECT family FROM k_unit k WHERE k.family = m.family AND k.natural_stars < m.natural_stars AND k.natural_stars < " . $this->filters["MIN_NATURAL_STARS"] . ")) ";

+ 38 - 32
application/page/Runes_Page.php

@@ -68,27 +68,16 @@
             global $db;
             $this->view = PATH::VIEW . "runes.php";
             $this->parse_filters();
-                $s = $this->build_query();
-                $this->filters["GROUP"] = 1;
+            $s = $this->build_query();
+            $this->filters["GROUP"] = 1;
             $q = $db->query($s);
             while ($r = $q->fetchArray(SQLITE3_ASSOC)){
                 $rune = new Rune($r["id"]);
-                if (strlen($rune->assigned_to) > 0){
-                    $rune->assigned_to = new Unit($rune->assigned_to, false);
+                if ($r["unit"]){
+                    $rune->unit = new Unit($r["unit"], false);
                 }
                 array_push($this->runes, $rune);
             }
-            $s = "
-              SELECT id
-              FROM filter
-              WHERE
-                uid = '$UID' AND
-                page = 'RUNES';
-            ";
-            $q = $db->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->custom_filters, new Custom_Filter($r["id"]));
-            }
             $this->title = "Runes - SWDB";
             $this->description = "Rune inventory";
             $this->canonical = URL::BASE . "runes/";
@@ -178,11 +167,19 @@
          */
         private function build_query(){
             global $UID;
+            global $MODE;
             $s = "
               SELECT
                 id,
-                assigned_to
-              FROM rune
+                (
+                  SELECT DISTINCT unit
+                  FROM unit_rune
+                  WHERE
+                    rune = rune.id AND
+                    rta = $MODE
+                ) AS unit
+              FROM
+                rune
               WHERE
                 uid = '$UID' AND
                 stars >= " . $this->filters["MIN_STARS"] . " AND
@@ -199,11 +196,20 @@
                 max_efficiency <= " . $this->filters["MAX_MAX_EFFICIENCY"] . "
             ";
             if (count($this->filters["MAIN"]) > 0){
-                $s = $s . " AND main_stat IN ( ";
+                $values = "(";
                 foreach($this->filters["MAIN"] as $t){
-                    $s = $s . "'$t', ";
+                    $values = $values . "'$t', ";
                 }
-                $s = $s . "'DUMMY0') ";
+                $values = $values . "'DUMMY0') ";
+                $s .= "
+                  AND id IN (
+                    SELECT rune
+                    FROM rune_stat
+                    WHERE
+                      slot = " . RUNE_STAT_SLOT_ID::MAIN . " AND
+                      stat IN $values
+                  )
+                ";
             }
             if (count($this->filters["SUB"]) > 0){
                 $values = "(";
@@ -211,13 +217,13 @@
                     $values = $values . "'$t', ";
                 }
                 $values = $values . "'DUMMY0') ";
-                $s = $s . "
-                  AND ( 
-                    innate_stat IN $values OR
-                    substat_1 IN $values OR
-                    substat_2 IN $values OR
-                    substat_3 IN $values OR
-                    substat_4 IN $values
+                $s .= "
+                  AND id IN (
+                    SELECT rune
+                    FROM rune_stat
+                    WHERE
+                      slot != " . RUNE_STAT_SLOT_ID::MAIN . " AND
+                      stat IN $values
                   )
                 ";
             }
@@ -237,16 +243,16 @@
             }
             switch ($this->filters["ASSIGNED"]){
                 case 1:
-                    $s = $s . " AND assigned_to IS NOT NULL ";
+                    $s = $s . " AND unit IS NOT NULL ";
                     break;
                 case 2:
-                    $s = $s . " AND assigned_to IS NULL ";
+                    $s = $s . " AND unit IS NULL ";
                     break;
                 case 3:
-                    $s = $s . " AND (assigned_to IS NULL OR assigned_to IN (SELECT DISTINCT id FROM unit WHERE building <> " . BUILDING_ID::MONSTER_STORAGE . ")) ";
+                    $s = $s . " AND (unit IS NULL OR unit IN (SELECT DISTINCT id FROM unit WHERE building <> " . BUILDING_ID::MONSTER_STORAGE . ")) ";
                     break;
                 case 4:
-                    $s = $s . " AND assigned_to IN (SELECT DISTINCT id FROM unit WHERE building <> " . BUILDING_ID::MONSTER_STORAGE . ") ";
+                    $s = $s . " AND unit IN (SELECT DISTINCT id FROM unit WHERE building <> " . BUILDING_ID::MONSTER_STORAGE . ") ";
                     break;
             }
             $s = $s . " ORDER BY ";
@@ -254,7 +260,7 @@
                 $s = $s . " type, slot, stars DESC, original_quality DESC, quality DESC, level;";
             }
             else{
-                $s = $s . " slot, type, stars DESC, original_quality DESC, quality DESC, level, main_stat;";
+                $s = $s . " slot, type, stars DESC, original_quality DESC, quality DESC, level;";
             }
             return $s;
         }

+ 7 - 0
application/view/artifacts.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>artifacts.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>

+ 7 - 0
application/view/catalog.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>catalog.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>

+ 7 - 0
application/view/enchantments.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>enchantments.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>

+ 7 - 0
application/view/error.php

@@ -17,6 +17,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>error.css'/>
         <!-- Meta tags -->
         <meta name='robots' content='noindex nofollow'/>

+ 7 - 0
application/view/fusion.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>fusion.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>

+ 7 - 0
application/view/guild.php

@@ -17,6 +17,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>guild.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>

+ 7 - 0
application/view/help.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>help.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>

+ 7 - 0
application/view/home.php

@@ -19,6 +19,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>home.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>

+ 127 - 53
application/view/inc/header.php

@@ -9,64 +9,138 @@
 
     /** @var int $UID User id. */
 ?>
+<script>
+    function setMode(rta){
+        if (rta === true){
+            mode = <?=GAME_MODE_ID::RTA?>;
+        }
+        else if (rta === false){
+            mode = <?=GAME_MODE_ID::NORMAL?>;
+        }
+        else{
+            return false;
+        }
+        params = '?uid=<?=$UID?>&mode=' + mode;
+        var xhttp = new XMLHttpRequest();
+        xhttp.onreadystatechange = function() {
+            if (this.readyState == 4){
+                if (this.status == 201){
+                    window.location.reload(false);
+                }
+            }
+        };
+        xhttp.open('GET', '/action/change_game_mode/' + params, true);
+        xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
+        xhttp.send();
+        return true;
+    }
+</script>
 <header>
-    <div id='logo'>
-        <img id='logo_img' src='<?=URL::IMG["LOGO"]?>sw.png' alt=''/>
-        <h1 id='logo_text'>
-            <span class='large'>D</span>
-            <span class='small'>ata</span>
-            <span class='large'>B</span>
-            <span class='small'>ase</span>
-        </h1>
-    </div>
 <?php
     if ($_SESSION['session'] == true){
 ?>
         <nav id='menu'>
-            <a href='/<?=$UID?>/'>
-                Home
-            </a>
-            <a href='/<?=$UID?>/catalog/'>
-                Catalog
-            </a>
-            <a href='/<?=$UID?>/monsters/'>
-                Monsters
-            </a>
-            <a href='/<?=$UID?>/runes/'>
-                Runes
-            </a>
-            <a href='/<?=$UID?>/enchantments/'>
-                Enchantments
-            </a>
-            <a href='/<?=$UID?>/artifacts/'>
-                Artifacts
-            </a>
-            <a href='/<?=$UID?>/fusion/'>
-                Fusion
-            </a>
-            <a href='/<?=$UID?>/guild/'>
-                Guild
-            </a>
-            <a href='/<?=$UID?>/runs/'>
-                Runs
-            </a>
-            <a href='/<?=$UID?>/stats/'>
-                Stats
-            </a>
-            <a href='/<?=$UID?>/teams/'>
-                Teams
-            </a>
-            <a href='/<?=$UID?>/report/'>
-                Reports
-            </a>
-            <a href='/<?=$UID?>/optimizer/'>
-                Optimizer
-            </a>
-        </nav>
-        <nav id='profile'>
-            <a href='/<?=$UID?>/profile/'>
-                <?=$_SESSION['name']?>
-            </a>
+            <table>
+                <tr>
+                    <td rowspan='2'>
+                        <div id='logo'>
+                            <img id='logo_img' src='<?=URL::IMG["LOGO"]?>sw.png' alt=''/>
+                            <h1 id='logo_text'>
+                                <span class='large'>D</span>
+                                <span class='small'>ata</span>
+                                <span class='large'>B</span>
+                                <span class='small'>ase</span>
+                            </h1>
+                        </div>
+                    </td>
+                    <td class='item'>
+                        <a href='/<?=$UID?>/'>
+                            Home
+                        </a>
+                    </td>
+                    <td class='item'>
+                        <a href='/<?=$UID?>/monsters/'>
+                            Monsters
+                        </a>
+                    </td>
+                    <td class='item'>
+                        <a href='/<?=$UID?>/runes/'>
+                            Runes
+                        </a>
+                    </td>
+                    <td class='item'>
+                        <a href='/<?=$UID?>/artifacts/'>
+                            Artifacts
+                        </a>
+                    </td>
+                    <td class='item'>
+                        <a href='/<?=$UID?>/enchantments/'>
+                            Enchantments
+                        </a>
+                    </td>
+                    <td class='item'>
+                        <a href='/<?=$UID?>/teams/'>
+                            Teams
+                        </a>
+                    </td>
+                    <td class='last profile'>
+                        <a href='/<?=$UID?>/profile/'>
+                            <?=$_SESSION['name']?>
+                        </a>
+                    </td>
+                </tr>
+                <tr>
+                    <td class='item'>
+                        <a href='/<?=$UID?>/catalog/'>
+                            Catalog
+                        </a>
+                    </td>
+                    <td class='item'>
+                        <a href='/<?=$UID?>/fusion/'>
+                            Fusion
+                        </a>
+                    </td>
+                    <td class='item'>
+                        <a href='/<?=$UID?>/guild/'>
+                            Guild
+                        </a>
+                    </td>
+                    <td class='item'>
+                        <a href='/<?=$UID?>/runs/'>
+                            Runs
+                        </a>
+                    </td>
+                    <td class='item'>
+                        <a href='/<?=$UID?>/report/'>
+                            Reports
+                        </a>
+                    </td>
+                    <td class='item'>
+                        <a href='/<?=$UID?>/optimizer/'>
+                            Optimizer
+                        </a>
+                    </td>
+                    <!--<td class='item'>
+                        <a href='/<?=$UID?>/stats/'>
+                            Stats
+                        </a>
+                    </td>-->
+                    <td class='last mode'>
+                        <div id='mode_switch'>
+                            <span class='mode'>
+                                Normal
+                            </span>
+                            <label class='switch'>
+                                <input type="checkbox" <?=($MODE == GAME_MODE_ID::RTA ? "checked='cheecked'" : "")?> onChange='setMode(this.checked);'/>
+                                <span class="slider round"></span>
+                            </label>
+                            <span class='mode'>
+                                RTA
+                            </span>
+                        </div>
+                    </td>
+                </tr>
+            </table>
         </nav>
 <?php
     }

+ 11 - 0
application/view/monster.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>monster.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>
@@ -102,6 +109,10 @@
                     </a>
                 </div>
             </div>
+<?php
+            include __DIR__ . "/inc/mode.php";
+?>
+
         </aside>
         <main>
             <section id='monster' class='content'>

+ 7 - 0
application/view/monster_info.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>monster_info.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>

+ 11 - 0
application/view/monsters.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>monsters.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>
@@ -158,6 +165,10 @@
                 </table>
                 <input type='submit' value='Apply'/>
             </form>
+<?php
+            include __DIR__ . "/inc/mode.php";
+?>
+
         </aside> <!-- #filters -->
         <main>
             <section id='list' class='list'>

+ 7 - 0
application/view/optimizer.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>optimizer.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>

+ 12 - 1
application/view/optimizer_unit.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>optimizer.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>
@@ -426,6 +433,7 @@
                             break;
                     }
                 }
+                set_stats['hp'] = Math.floor(set_stats['hp']);
 
                 // Send the request
                 var xhttp = new XMLHttpRequest();
@@ -446,7 +454,7 @@
                 };
 
                 // DEBUG
-                //params = 'uid=8114048&unit=6441802832&limit=6&set[]=2&set[]=4&set[]=4&stat[]=4&stat[]=4&stat[]=4&source=0&tuning=2&min_defense=800';
+                //params = 'uid=8114048&unit=6441802832&limit=6&set[]=1&set[]=1&set[]=1&stat[]=2&stat[]=2&stat[]=2&source=0&tuning=2&min_defense=800';
 
 
                 // Clear result table, disable button and show spinner
@@ -570,6 +578,9 @@
                     new_stats["ACC"] += candidates[i].ACC;
                     new_stats["RES"] += candidates[i].RES;
                 }
+                new_stats["HP"] = Math.floor(new_stats["HP"]);
+                //console.log("CANDIDATES NEW HP: " + new_stats["HP"]);
+                
                 new_stats["EHP"] = Math.ceil((((new_stats["DEF"] * 3.5) + 1140) * new_stats["HP"]) / 1000);
                 new_stats["DMG"] = Math.ceil((new_stats["ATK"] * (100 - new_stats["CRR"]) / 100) + ((new_stats["ATK"] + (new_stats["ATK"] * new_stats["CRD"] / 100)) * new_stats["CRR"] / 100));
                 if (

+ 7 - 0
application/view/profile.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>profile.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>

+ 7 - 0
application/view/report.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>report.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>

+ 7 - 0
application/view/report_rune_enchantment.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>report_rune_enchantment.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>

+ 7 - 0
application/view/report_skillup.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>report_skillup.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>

+ 9 - 2
application/view/runes.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>runes.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>
@@ -262,7 +269,7 @@
 <?php
                                         if (($i + 1) % 2 == 0){
 ?>
-                                            </select><select multiple name='main_stat[]' class='select_sub' id='filter_sub_stat_<?=$j?>' onMouseDown='fixSubSelect(<?=$j?>, event);'>
+                                            </select><select multiple name='sub_stat[]' class='select_sub' id='filter_sub_stat_<?=$j?>' onMouseDown='fixSubSelect(<?=$j?>, event);'>
 <?php
                                             $j ++;
                                         }
@@ -419,7 +426,7 @@
 <?php
                         }
 ?>
-                        <?=HTML::rune_table($rune, $rune->assigned_to)?>
+                        <?=HTML::rune_table($rune, $rune->unit)?>
 <?php
                     }
 ?>

+ 7 - 0
application/view/runs.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>runs.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>

+ 7 - 0
application/view/stats.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>stats.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>

+ 7 - 0
application/view/teams.php

@@ -18,6 +18,13 @@
         <link rel='shortcut icon' href='<?=$page->favicon?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+<?php
+        if ($MODE == GAME_MODE_ID::RTA){
+?>
+            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
+<?php
+        }
+?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>teams.css'/>
         <!-- Meta tags -->
         <link rel='canonical' href='<?=$page->canonical?>'/>

+ 18 - 22
install_data/install_data.sql

@@ -39,7 +39,8 @@ CREATE TABLE player(
     top_rank_wboss INT DEFAULT 0,
     top_rank_toan INT DEFAULT 0,
     top_rank_toah INT DEFAULT 0,
-    public INT NOT NULL DEFAULT 0 CHECK(public IN (0, 1))
+    public INT NOT NULL DEFAULT 0 CHECK(public IN (0, 1)),
+    mode INT NOT NULL CHECK(mode IN (0, 1)) DEFAULT 0
 );
 CREATE TABLE record(
     uid INT NOT NULL REFERENCES player(id),
@@ -118,7 +119,6 @@ CREATE TABLE unit_skill(
 CREATE TABLE rune(
     uid INT NOT NULL REFERENCES player(id),
     id INT PRIMARY KEY NOT NULL,
-    assigned_to INT REFERENCES unit(id),
     type INT REFERENCES k_rune_set(id),
     slot INT NOT NULL CHECK(slot BETWEEN 1 AND 6),
     stars INT NOT NULL CHECK(stars BETWEEN 1 AND 6),
@@ -129,28 +129,24 @@ CREATE TABLE rune(
     value INT NOT NULL CHECK(value > 0),
     efficiency FLOAT NOT NULL CHECK(efficiency BETWEEN 0 AND 100),
     max_efficiency FLOAT NOT NULL CHECK(max_efficiency BETWEEN 0 AND 100),
-    main_stat INT NOT NULL REFERENCES k_rune_stat(id),
-    main_stat_value INT NOT NULL CHECK(main_stat_value > 0),
-    innate_stat INT REFERENCES k_rune_stat(id),
-    innate_stat_value INT CHECK(innate_stat_value >= 0),
-    substat_1 INT REFERENCES k_rune_stat(id),
-    substat_1_value INT CHECK(substat_1_value >= 0),
-    substat_1_enchant INT CHECK(substat_1_enchant IN (0, 1)),
-    substat_1_grind INT CHECK(substat_1_grind >= 0),
-    substat_2 INT REFERENCES k_rune_stat(id),
-    substat_2_value INT CHECK(substat_2_value >= 0),
-    substat_2_enchant INT CHECK(substat_2_enchant IN (0, 1)),
-    substat_2_grind INT CHECK(substat_2_grind >= 0),
-    substat_3 INT REFERENCES k_rune_stat(id),
-    substat_3_value INT CHECK(substat_3_value >= 0),
-    substat_3_enchant INT CHECK(substat_3_enchant IN (0, 1)),
-    substat_3_grind INT CHECK(substat_3_grind >= 0),
-    substat_4 INT REFERENCES k_rune_stat(id),
-    substat_4_value INT CHECK(substat_4_value >= 0),
-    substat_4_enchant INT CHECK(substat_4_enchant IN (0, 1)),
-    substat_4_grind INT CHECK(substat_4_grind >= 0),
     locked INT NOT NULL CHECK(locked IN (0, 1))
 );
+CREATE TABLE rune_stat(
+    rune INT NOT NULL references rune(id),
+    slot INT NOT NULL CHECK(slot BETWEEN -1 AND 4),
+    stat INT NOT NULL REFERENCES k_rune_stat(id),
+    value INT NOT NULL CHECK(value >= 0),
+    enchant INT NOT NULL CHECK(enchant IN (0, 1)),
+    grind INT NOT NULL CHECK(grind >= 0),
+    rolls INT NOT NULL CHECK(rolls BETWEEN 0 AND 4),
+    PRIMARY KEY (rune, slot)
+);
+CREATE TABLE unit_rune(
+    unit INT NOT NULL REFERENCES unit(id),
+    rune INT NOT NULL REFERENCES rune(id),
+    rta INT NOT NULL DEFAULT 0 CHECK(rta IN (0, 1)),
+    PRIMARY KEY(unit, rune, rta)
+);
 CREATE TABLE artifact(
     uid INT NOT NULL REFERENCES player(id),
     id INT PRIMARY KEY NOT NULL,

+ 85 - 45
public/css/ui.css

@@ -194,17 +194,17 @@ header{
     }
 }
 header div#logo{
-    font-size: 70%;
+    font-size: 100%;
     margin: auto;
     display: inline-block;
     vertical-align: middle;
-    width: 10em;
+    width: 9em;
     text-align: center;
     float: left;
 }
 header div#logo img#logo_img{
-    max-width: 8em;
-    max-height: 4em;
+    max-width: 9em;
+    max-height: 6em;
 }
 header div#logo h1#logo_text{
     font-style: italic;
@@ -233,55 +233,41 @@ header div#logo h1#logo_text span.small{
     header div#logo h1#logo_text span.small{/*display: none;*/}
 }
 header nav#menu{
-    display: inline-block;
-    height: 2em;
-}
-@media only screen and (max-width: 788px){
-    header nav#menu{
-        display: block;
-        position: absolute;
-        left: 0em;
-        right: 7em;
-        top: 0em;
-        text-align: left;
-    }
+    display: block;
+    height: 4.5em;
 }
-header nav#menu a{
+header nav#menu table td{
     font-size: 100%;
     font-weight: bold;
     text-transform: capitalize;
     font-variant: small-caps;
-    margin: 0 -0.2em 0 0; /* -0.2 to compensate for strange space. */
     text-decoration: none;
     position: relative;
-    transition: all .4s ease-in-out;
-    color: var(--nav-color);
-    border-left: var(--nav-separator);
-    padding: 0.3em;
-    text-align: center;
-    display: inline-block;
+    padding: 0;
     vertical-align: middle;
+}
+header nav#menu table td.item{
+    border: var(--nav-separator);
+    text-align: center;
+}
+header nav#menu table td.last{
+    width: 100%;
+    text-align: right;
+    padding-right: 0.5em;
+}
+header nav#menu table td.item a{
+    color: var(--nav-color);
     text-shadow: var(--nav-shadow);
+    transition: all .4s ease-in-out;
+    display: block;
+    padding: 0.3em 0.1em;
 }
-header nav#menu a:last-of-type{border-right: var(--nav-separator)}
-header nav#menu a:hover{
+header nav#menu table td.item a:hover{
     background-color: var(--nav-background-hover);
     color: var(--nav-color-hover);
     text-shadow: var(--nav-shadow-hover);
 }
-@media only screen and (max-width: 768px){
-    header nav#menu a{
-        font-size: 80%;
-        padding: 0.6em 0.2em;
-        margin: 0em -0.2em;
-        display: inline-block;
-        text-align: center;
-        border-top: var(--nav-separator);
-        border-bottom: var(--nav-separator);
-        border-right: var(--nav-separator);
-    }
-}
-header nav#profile{
+header table td.profile nav#profile{
     float: right;
     margin-right: 0.5em;
     position: absolute;
@@ -289,15 +275,14 @@ header nav#profile{
     top: 0em;
 }
 @media screen and (max-width : 768px){
-    header nav#profile{
+    header table td.profile nav#profile{
         margin-right: 0.5em;
         position: absolute;
         top: 2em;
         right: 0.5em;
     }
 }
-
-header nav#profile a{
+header table td.profile a{
     border-left: 0;
     font-size: 110%;
     font-weight: bold;
@@ -314,10 +299,64 @@ header nav#profile a{
     vertical-align: middle;
     text-shadow: var(--nav-shadow);
 }
-header nav#profile a:hover{
+header table td.profile a:hover{
     color: var(--nav-color-hover);
     text-shadow: var(--nav-shadow-hover);
 }
+header table td.mode div#mode_switch{
+    display: inline-block;
+    font-size: 70%;
+}
+header table td.mode div#mode_switch .switch {
+    position: relative;
+    display: inline-block;
+    width: 3.5em;
+    height: 2em;
+}
+header table td.mode div#mode_switch .switch input {
+    opacity: 0;
+    width: 0;
+    height: 0;
+}
+header table td.mode div#mode_switch .slider {
+    position: absolute;
+    cursor: pointer;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: #755739;
+    -webkit-transition: .4s;
+    transition: .4s;
+}
+header table td.mode div#mode_switch .slider:before {
+    position: absolute;
+    content: "";
+    height: 1.5em;
+    width: 1.5em;
+    left: 0.25em;
+    bottom: 0.25em;
+    background-color: white;
+    -webkit-transition: .4s;
+    transition: .4s;
+}
+header table td.mode div#mode_switch input:checked + .slider {
+  background-color: #396f75;
+}
+header table td.mode div#mode_switch input:focus + .slider {
+  box-shadow: 0 0 1px #2196F3;
+}
+header table td.mode div#mode_switch input:checked + .slider:before {
+  -webkit-transform: translateX(1.5em);
+  -ms-transform: translateX(1.5em);
+  transform: translateX(1.5em);
+}
+header table td.mode div#mode_switch .slider.round {
+    border-radius: 1.5em;
+}
+header table td.mode div#mode_switch .slider.round:before {
+    border-radius: 50%;
+}
 
 aside{
     grid-area: sidebar;
@@ -329,7 +368,7 @@ aside{
     overflow-y: hidden;
     text-align: left;
     border-right: var(--sidebar-border);
-    padding: 0.3em
+    padding: 0.3em;
     margin: 0;
     background: var(--sidebar-background);
 }
@@ -358,7 +397,7 @@ aside h2{
     text-transform: capitalize;
     font-variant: small-caps;
     height: 1.2em;
-    padding-top: 3em;
+    padding-top: 5em;
 }
 @media only screen and (max-width: 788px){
     aside h2{
@@ -387,6 +426,7 @@ aside form.filter input[type='submit']{
     margin: 1em auto;
     display: block;
 }
+
 main{
     grid-area: content;
     overflow-y: auto;