| summaryrefslogtreecommitdiff | 
diff options
| author | nsensfel <SpamShield0@noot-noot.org> | 2018-06-15 13:47:17 +0200 | 
|---|---|---|
| committer | nsensfel <SpamShield0@noot-noot.org> | 2018-06-15 13:47:17 +0200 | 
| commit | 36992b435c76326bc575f75efbafac54dc2757a0 (patch) | |
| tree | 336bbe09bf38ffa1f66504307ab136b2e3df6972 /src/battlemap | |
| parent | 1e14bb938ab22976a63342bbd7b7fd2611588338 (diff) | |
Cleans up RangeIndicator.elm, tries marker icons.
Not satisfied with the current look of those markers, though.
Diffstat (limited to 'src/battlemap')
| -rw-r--r-- | src/battlemap/src/Struct/Navigator.elm | 2 | ||||
| -rw-r--r-- | src/battlemap/src/Struct/RangeIndicator.elm | 352 | ||||
| -rw-r--r-- | src/battlemap/www/style.css | 74 | 
3 files changed, 273 insertions, 155 deletions
diff --git a/src/battlemap/src/Struct/Navigator.elm b/src/battlemap/src/Struct/Navigator.elm index 1b3f170..46ad92c 100644 --- a/src/battlemap/src/Struct/Navigator.elm +++ b/src/battlemap/src/Struct/Navigator.elm @@ -80,7 +80,7 @@ new start_loc mov_dist atk_dist def_dist cost_fun =              start_loc              mov_dist              atk_dist -            0 +            def_dist              (cost_fun)           ),        cost_fun = cost_fun diff --git a/src/battlemap/src/Struct/RangeIndicator.elm b/src/battlemap/src/Struct/RangeIndicator.elm index 06b34ec..2b70ecd 100644 --- a/src/battlemap/src/Struct/RangeIndicator.elm +++ b/src/battlemap/src/Struct/RangeIndicator.elm @@ -6,8 +6,6 @@ module Struct.RangeIndicator exposing        get_path     ) --- FIXME: This module is still too much of a mess... -  -- Elm -------------------------------------------------------------------------  import Dict  import List @@ -31,6 +29,19 @@ type alias Type =        marker: Struct.Marker.Type     } +type alias SearchParameters = +   { +      maximum_distance: Int, +      maximum_attack_range: Int, +      minimum_defense_range: Int, +      cost_function: (Struct.Location.Type -> Int) +   } + +type alias LocatedIndicator = +   { +      location_ref: Struct.Location.Ref, +      indicator: Type +   }  --------------------------------------------------------------------------------  -- LOCAL -----------------------------------------------------------------------  -------------------------------------------------------------------------------- @@ -38,186 +49,238 @@ get_closest : (        Int ->        Struct.Location.Ref ->        Type -> -      (Struct.Location.Ref, Type) -> -      (Struct.Location.Ref, Type) +      LocatedIndicator -> +      LocatedIndicator     ) -get_closest dist ref indicator (prev_ref, prev_indicator) = -   if +get_closest max_dist ref indicator current_best = +   if (is_closer max_dist indicator current_best.indicator) +   then +      { +         location_ref = ref, +         indicator = indicator +      } +   else +      current_best + +is_closer : Int -> Type -> Type -> Bool +is_closer max_dist candidate current =     ( -      (indicator.distance < prev_indicator.distance) +      -- It's closer when moving +      (candidate.distance < current.distance)        ||        ( -         (indicator.distance > dist) -         && (prev_indicator.distance > dist) -         && (indicator.atk_range < prev_indicator.atk_range) +         -- Or neither are reachable by moving, +         (max_dist <= candidate.distance) +         && (max_dist <= current.distance) +         -- but the new one is closer when attacking. +         && (candidate.atk_range < current.atk_range)        )     ) -   then -      (ref, indicator) -   else -      (prev_ref, prev_indicator) -is_closer : Int -> Int -> Type -> Bool -is_closer new_dist new_range neighbor = +generate_neighbor : ( +      SearchParameters -> +      Struct.Location.Type -> +      Struct.Direction.Type -> +      Type -> +      (Int, Type) +   ) +generate_neighbor search_params neighbor_loc dir src_indicator = +   let +      node_cost = (search_params.cost_function neighbor_loc) +      new_dist = (src_indicator.distance + node_cost) +      new_atk_range = (src_indicator.atk_range + 1) +      new_true_range = (src_indicator.true_range + 1) +      can_defend = (new_true_range > search_params.minimum_defense_range) +   in +      if (new_dist > search_params.maximum_distance) +      then +         ( +            node_cost, +            { +               distance = (search_params.maximum_distance + 1), +               atk_range = new_atk_range, +               true_range = new_true_range, +               path = (dir :: src_indicator.path), +               marker = +                  if (can_defend) +                  then +                     Struct.Marker.CanAttackCanDefend +                  else +                     Struct.Marker.CanAttackCantDefend +            } +         ) +      else +         ( +            node_cost, +            { +               distance = new_dist, +               atk_range = 0, +               true_range = new_true_range, +               path = (dir :: src_indicator.path), +               marker = +                  if (can_defend) +                  then +                     Struct.Marker.CanGoToCanDefend +                  else +                     Struct.Marker.CanGoToCantDefend +            } +         ) + +candidate_is_acceptable : (SearchParameters -> Int -> Type -> Bool) +candidate_is_acceptable search_params cost candidate = +   (cost /= Constants.Movement.cost_when_out_of_bounds) +   &&     ( -      (new_dist < neighbor.distance) +      (candidate.distance <= search_params.maximum_distance)        || -      ( -         (neighbor.distance > new_dist) -         && (new_range < neighbor.atk_range) -      ) +      (candidate.atk_range <= search_params.maximum_attack_range)     ) +candidate_is_an_improvement : ( +      SearchParameters -> +      Struct.Location.Ref -> +      Type -> +      (Dict.Dict Struct.Location.Ref Type) -> +      Bool +   ) +candidate_is_an_improvement search_params loc_ref candidate alternatives = +   case (Dict.get loc_ref alternatives) of +      (Just alternative) -> +         (is_closer search_params.maximum_distance candidate alternative) + +      Nothing -> +         True  handle_neighbors : ( -      Type -> -      Struct.Location.Type -> -      Int -> -      Int -> -      Int -> +      LocatedIndicator ->        (Dict.Dict Struct.Location.Ref Type) -> -      (Struct.Location.Type -> Int) -> +      SearchParameters ->        Struct.Direction.Type ->        (Dict.Dict Struct.Location.Ref Type) ->        (Dict.Dict Struct.Location.Ref Type)     ) -handle_neighbors -   src_indicator src_loc -   dist -   atk_range def_range -   results cost_fun dir rem = +handle_neighbors src results search_params dir remaining =     let +      src_loc = (Struct.Location.from_ref src.location_ref)        neighbor_loc = (Struct.Location.neighbor dir src_loc) +      neighbor_loc_ref = (Struct.Location.get_ref neighbor_loc)     in -      case (Dict.get (Struct.Location.get_ref neighbor_loc) results) of -         (Just _) -> rem +      case (Dict.get neighbor_loc_ref results) of +         (Just _) -> +            -- A minimal path for this location has already been found +            remaining           Nothing ->              let -               node_cost = (cost_fun neighbor_loc) -               new_dist = (src_indicator.distance + node_cost) -               new_atk_range = (src_indicator.atk_range + 1) -               new_true_range = (src_indicator.true_range + 1) -               can_defend = (new_true_range >= def_range) +               (candidate_cost, candidate) = +                  (generate_neighbor +                     search_params +                     neighbor_loc +                     dir +                     src.indicator +                  )              in                 if -                  ( -                     ( -                        case -                           (Dict.get -                              (Struct.Location.get_ref neighbor_loc) -                              rem -                           ) -                        of -                           (Just neighbor) -> -                              (is_closer new_dist new_atk_range neighbor) - -                           Nothing -> -                              True -                     ) -                     && -                     (node_cost /= Constants.Movement.cost_when_out_of_bounds) -                     && -                     ( -                        (new_dist <= dist) -                        || -                        (new_atk_range <= atk_range) -                     ) +               ( +                  (candidate_is_acceptable +                     search_params +                     candidate_cost +                     candidate                    ) -               then -                  (Dict.insert -                     (Struct.Location.get_ref neighbor_loc) -                     ( -                        if (new_dist > dist) -                        then -                           { -                              distance = (dist + 1), -                              atk_range = new_atk_range, -                              true_range = new_true_range, -                              path = (dir :: src_indicator.path), -                              marker = -                                 if (can_defend) -                                 then -                                    Struct.Marker.CanAttackCanDefend -                                 else -                                    Struct.Marker.CanAttackCantDefend -                           } -                        else -                           { -                              distance = new_dist, -                              atk_range = 0, -                              true_range = new_true_range, -                              path = (dir :: src_indicator.path), -                              marker = -                                 if (can_defend) -                                 then -                                    Struct.Marker.CanGoToCanDefend -                                 else -                                    Struct.Marker.CanGoToCantDefend -                           } -                     ) -                     rem +                  && +                  (candidate_is_an_improvement +                     search_params +                     neighbor_loc_ref +                     candidate +                     remaining                    ) +               ) +               then +                  (Dict.insert neighbor_loc_ref candidate remaining)                 else -                  rem +                  remaining + +find_closest_in : ( +      SearchParameters -> +      (Dict.Dict Struct.Location.Ref Type) -> +      LocatedIndicator +   ) +find_closest_in search_params remaining = +   (Dict.foldl +      (get_closest search_params.maximum_distance) +      { +         location_ref = (-1, -1), +         indicator = +            { +               distance = Constants.Movement.cost_when_out_of_bounds, +               path = [], +               atk_range = Constants.Movement.cost_when_out_of_bounds, +               true_range = Constants.Movement.cost_when_out_of_bounds, +               marker = Struct.Marker.CanAttackCanDefend +            } +      } +      remaining +   ) + +resolve_marker_type : SearchParameters -> Type -> Type +resolve_marker_type search_params indicator = +   {indicator | +      marker = +         case +            ( +               (indicator.atk_range > 0), +               (indicator.true_range <= search_params.minimum_defense_range) +            ) +         of +            (True, True) -> Struct.Marker.CanAttackCantDefend +            (True, False) -> Struct.Marker.CanAttackCanDefend +            (False, True) -> Struct.Marker.CanGoToCantDefend +            (False, False) -> Struct.Marker.CanGoToCanDefend +   } + +insert_in_dictionary : ( +      LocatedIndicator -> +      (Dict.Dict Struct.Location.Ref Type) -> +      (Dict.Dict Struct.Location.Ref Type) +   ) +insert_in_dictionary located_indicator dict = +   (Dict.insert +      located_indicator.location_ref +      located_indicator.indicator +      dict +   )  search : (        (Dict.Dict Struct.Location.Ref Type) ->        (Dict.Dict Struct.Location.Ref Type) -> -      Int -> -      Int -> -      Int -> -      (Struct.Location.Type -> Int) -> +      SearchParameters ->        (Dict.Dict Struct.Location.Ref Type)     ) -search result remaining dist atk_range def_range cost_fun = +search result remaining search_params =     if (Dict.isEmpty remaining)     then        result     else        let -         (min_loc_ref, min) = -            (Dict.foldl -               (get_closest dist) -               ( -                  (-1,-1), -                  { -                     distance = Constants.Movement.cost_when_out_of_bounds, -                     path = [], -                     atk_range = Constants.Movement.cost_when_out_of_bounds, -                     true_range = Constants.Movement.cost_when_out_of_bounds, -                     marker = Struct.Marker.CanAttackCanDefend -                  } -               ) -               remaining -            ) +         closest_located_indicator = (find_closest_in search_params remaining) +         finalized_clos_loc_ind = +            {closest_located_indicator| +               indicator = +                  (resolve_marker_type +                     search_params +                     closest_located_indicator.indicator +                  ) +            }        in           (search -            (Dict.insert -               min_loc_ref -               {min | -                  marker = -                     case -                        ((min.atk_range > 0), (min.true_range <= def_range)) -                     of -                        (True, True) -> Struct.Marker.CanAttackCantDefend -                        (True, False) -> Struct.Marker.CanAttackCanDefend -                        (False, True) -> Struct.Marker.CanGoToCantDefend -                        (False, False) -> Struct.Marker.CanGoToCanDefend -               } -               result -            ) +            (insert_in_dictionary finalized_clos_loc_ind result)              (List.foldl                 (handle_neighbors -                  min -                  (Struct.Location.from_ref min_loc_ref) -                  dist -                  atk_range -                  def_range +                  finalized_clos_loc_ind                    result -                  (cost_fun) +                  search_params                 ) -               (Dict.remove min_loc_ref remaining) +               (Dict.remove finalized_clos_loc_ind.location_ref remaining)                 [                    Struct.Direction.Left,                    Struct.Direction.Right, @@ -225,10 +288,7 @@ search result remaining dist atk_range def_range cost_fun =                    Struct.Direction.Down                 ]              ) -            dist -            atk_range -            def_range -            (cost_fun) +            search_params           )  -------------------------------------------------------------------------------- @@ -242,7 +302,7 @@ generate : (        (Struct.Location.Type -> Int) ->        (Dict.Dict Struct.Location.Ref Type)     ) -generate location dist atk_range def_range cost_fun = +generate location max_dist atk_range def_range cost_fun =     (search        Dict.empty        (Dict.insert @@ -261,10 +321,12 @@ generate location dist atk_range def_range cost_fun =           }           Dict.empty        ) -      dist -      atk_range -      def_range -      (cost_fun) +      { +         maximum_distance = max_dist, +         maximum_attack_range = atk_range, +         minimum_defense_range = def_range, +         cost_function = (cost_fun) +      }     )  get_marker : Type -> Struct.Marker.Type diff --git a/src/battlemap/www/style.css b/src/battlemap/www/style.css index 04bce9a..4b1db1b 100644 --- a/src/battlemap/www/style.css +++ b/src/battlemap/www/style.css @@ -463,7 +463,6 @@  .battlemap-marker-icon     {z-index: 2;}  .battlemap-path-icon-above-markers {z-index: 3;}  .battlemap-character-icon  {z-index: 4;} -.battlemap-marker-icon.battlemap-navigator-non-interactive     {z-index: 5;}  .battlemap-marker-icon,  .battlemap-character-icon, @@ -549,29 +548,31 @@     opacity: 0.3;     transition: opacity 0.3s ease-out;  } +  .battlemap-can-go-to-cant-defend-marker.battlemap-navigator-interactive  {     background:        repeating-linear-gradient(          -55deg, -        rgba(255,255,255,0.3), -        rgba(255,255,255,0.3) 3px, -        rgba(0,0,0,0.3) 3px, -        rgba(0,0,0,0.3) 7px +        rgb(255,255,255), +        rgb(255,255,255) 3px, +        rgba(0,0,0,0) 3px, +        rgba(0,0,0,0) 7px        );     opacity: 0.3;     transition: opacity 0.3s ease-out;  } -.battlemap-can-go-to-can-defend-marker.battlemap-navigator-interactive:hover +.battlemap-can-go-to-can-defend-marker.battlemap-navigator-interactive:hover, +.battlemap-can-go-to-cant-defend-marker.battlemap-navigator-interactive:hover  { -   background-color: rgba(255, 255, 255, 0.9); -   opacity: 1; +   opacity: 0.9;  }  .battlemap-can-attack-can-defend-marker.battlemap-navigator-interactive  { -   background-color:rgba(0,0,0,0.7); +   background-color: #000; +   opacity: 0.7;     width: 28px;     /*min-width: 28px;     max-width: 28px;*/ @@ -580,14 +581,69 @@     border-radius: 0;  } +.battlemap-can-attack-cant-defend-marker.battlemap-navigator-interactive +{ +   background: +      repeating-linear-gradient( +        -55deg, +        rgba(255,255,255,0), +        rgba(255,255,255,0) 3px, +        rgb(0,0,0) 3px, +        rgb(0,0,0) 7px +      ); +   width: 28px; +   /*min-width: 28px; +   max-width: 28px;*/ +   opacity: 0.7; +   height: 28px; +   margin: 2px 0 0 2px; +   border-radius: 0; +} +  .battlemap-can-attack-can-defend-marker.battlemap-navigator-non-interactive  {     background-image: url(/asset/svg/marker/blade.svg); +}  + +.battlemap-can-attack-cant-defend-marker.battlemap-navigator-non-interactive +{ +   background-image: +      url(/asset/svg/marker/blade.svg), +      url(/asset/svg/marker/brokenshield.svg); +} + +.battlemap-can-go-to-cant-defend-marker.battlemap-navigator-non-interactive +{ +   background-image: +      url(/asset/svg/marker/pawprint.svg), +      url(/asset/svg/marker/brokenshield.svg); +} + +.battlemap-can-attack-cant-defend-marker.battlemap-navigator-non-interactive, +.battlemap-can-go-to-cant-defend-marker.battlemap-navigator-non-interactive +{ +   width: 24px; +   height: 24px; +   background-position: top left, bottom right; +   background-size: 50%, 50%; +   background-repeat: no-repeat, no-repeat; +   margin: 2px;  }  .battlemap-can-go-to-can-defend-marker.battlemap-navigator-non-interactive  {     background-image: url(/asset/svg/marker/pawprint.svg); +} + +.battlemap-can-attack-can-defend-marker.battlemap-navigator-non-interactive, +.battlemap-can-attack-cant-defend-marker..battlemap-navigator-non-interactive +{ +   z-index: 5; +} + +.battlemap-can-go-to-can-defend-marker, +.battlemap-can-go-to-cant-defend-marker +{     z-index: 3;  }  | 


