From f63602557a2f7320a7e02a3bf7dd9b339efaf4d1 Mon Sep 17 00:00:00 2001 From: nsensfel Date: Tue, 10 Jul 2018 16:44:13 +0200 Subject: Starting work on the map editor... --- src/map-editor/Makefile | 36 +++ src/map-editor/elm-package.json | 19 ++ src/map-editor/src/Comm/AddTile.elm | 24 ++ src/map-editor/src/Comm/LoadBattlemap.elm | 42 +++ src/map-editor/src/Comm/Send.elm | 76 +++++ src/map-editor/src/Comm/SetMap.elm | 62 ++++ src/map-editor/src/Constants/IO.elm.m4 | 16 + src/map-editor/src/Constants/UI.elm | 16 + src/map-editor/src/ElmModule/Init.elm | 28 ++ src/map-editor/src/ElmModule/Subscriptions.elm | 17 + src/map-editor/src/ElmModule/Update.elm | 54 ++++ src/map-editor/src/ElmModule/View.elm | 56 ++++ src/map-editor/src/Main.elm | 23 ++ src/map-editor/src/Struct/Battlemap.elm | 123 +++++++ src/map-editor/src/Struct/Direction.elm | 52 +++ src/map-editor/src/Struct/Error.elm | 45 +++ src/map-editor/src/Struct/Event.elm | 44 +++ src/map-editor/src/Struct/Flags.elm | 42 +++ src/map-editor/src/Struct/HelpRequest.elm | 13 + src/map-editor/src/Struct/Location.elm | 59 ++++ src/map-editor/src/Struct/Model.elm | 254 +++++++++++++++ src/map-editor/src/Struct/ServerReply.elm | 33 ++ src/map-editor/src/Struct/Tile.elm | 203 ++++++++++++ src/map-editor/src/Struct/UI.elm | 139 ++++++++ src/map-editor/src/Update/ChangeScale.elm | 26 ++ src/map-editor/src/Update/HandleServerReply.elm | 230 +++++++++++++ src/map-editor/src/Update/SelectTab.elm | 32 ++ src/map-editor/src/Update/SelectTile.elm | 158 +++++++++ src/map-editor/src/Update/SetRequestedHelp.elm | 22 ++ src/map-editor/src/Util/Array.elm | 34 ++ src/map-editor/src/Util/Html.elm | 6 + src/map-editor/src/Util/List.elm | 16 + src/map-editor/src/View/MainMenu.elm | 38 +++ src/map-editor/src/View/Map.elm | 162 ++++++++++ src/map-editor/src/View/Map/Character.elm | 218 +++++++++++++ src/map-editor/src/View/Map/Navigator.elm | 245 ++++++++++++++ src/map-editor/src/View/Map/Tile.elm | 69 ++++ src/map-editor/src/View/MessageBoard.elm | 30 ++ src/map-editor/src/View/MessageBoard/Animator.elm | 57 ++++ .../src/View/MessageBoard/Animator/Attack.elm | 297 +++++++++++++++++ src/map-editor/src/View/MessageBoard/Error.elm | 33 ++ src/map-editor/src/View/MessageBoard/Help.elm | 37 +++ .../src/View/MessageBoard/Help/Guide.elm | 100 ++++++ src/map-editor/src/View/MessageBoard/Help/Rank.elm | 97 ++++++ src/map-editor/src/View/SubMenu.elm | 85 +++++ src/map-editor/src/View/SubMenu/Characters.elm | 69 ++++ src/map-editor/src/View/SubMenu/Settings.elm | 59 ++++ src/map-editor/src/View/SubMenu/Status.elm | 55 ++++ .../src/View/SubMenu/Status/CharacterInfo.elm | 34 ++ .../src/View/SubMenu/Status/TileInfo.elm | 142 ++++++++ src/map-editor/src/View/ToolBox.elm | 133 ++++++++ src/map-editor/www/index.html | 30 ++ src/map-editor/www/style.css | 356 +++++++++++++++++++++ 53 files changed, 4346 insertions(+) create mode 100644 src/map-editor/Makefile create mode 100644 src/map-editor/elm-package.json create mode 100644 src/map-editor/src/Comm/AddTile.elm create mode 100644 src/map-editor/src/Comm/LoadBattlemap.elm create mode 100644 src/map-editor/src/Comm/Send.elm create mode 100644 src/map-editor/src/Comm/SetMap.elm create mode 100644 src/map-editor/src/Constants/IO.elm.m4 create mode 100644 src/map-editor/src/Constants/UI.elm create mode 100644 src/map-editor/src/ElmModule/Init.elm create mode 100644 src/map-editor/src/ElmModule/Subscriptions.elm create mode 100644 src/map-editor/src/ElmModule/Update.elm create mode 100644 src/map-editor/src/ElmModule/View.elm create mode 100644 src/map-editor/src/Main.elm create mode 100644 src/map-editor/src/Struct/Battlemap.elm create mode 100644 src/map-editor/src/Struct/Direction.elm create mode 100644 src/map-editor/src/Struct/Error.elm create mode 100644 src/map-editor/src/Struct/Event.elm create mode 100644 src/map-editor/src/Struct/Flags.elm create mode 100644 src/map-editor/src/Struct/HelpRequest.elm create mode 100644 src/map-editor/src/Struct/Location.elm create mode 100644 src/map-editor/src/Struct/Model.elm create mode 100644 src/map-editor/src/Struct/ServerReply.elm create mode 100644 src/map-editor/src/Struct/Tile.elm create mode 100644 src/map-editor/src/Struct/UI.elm create mode 100644 src/map-editor/src/Update/ChangeScale.elm create mode 100644 src/map-editor/src/Update/HandleServerReply.elm create mode 100644 src/map-editor/src/Update/SelectTab.elm create mode 100644 src/map-editor/src/Update/SelectTile.elm create mode 100644 src/map-editor/src/Update/SetRequestedHelp.elm create mode 100644 src/map-editor/src/Util/Array.elm create mode 100644 src/map-editor/src/Util/Html.elm create mode 100644 src/map-editor/src/Util/List.elm create mode 100644 src/map-editor/src/View/MainMenu.elm create mode 100644 src/map-editor/src/View/Map.elm create mode 100644 src/map-editor/src/View/Map/Character.elm create mode 100644 src/map-editor/src/View/Map/Navigator.elm create mode 100644 src/map-editor/src/View/Map/Tile.elm create mode 100644 src/map-editor/src/View/MessageBoard.elm create mode 100644 src/map-editor/src/View/MessageBoard/Animator.elm create mode 100644 src/map-editor/src/View/MessageBoard/Animator/Attack.elm create mode 100644 src/map-editor/src/View/MessageBoard/Error.elm create mode 100644 src/map-editor/src/View/MessageBoard/Help.elm create mode 100644 src/map-editor/src/View/MessageBoard/Help/Guide.elm create mode 100644 src/map-editor/src/View/MessageBoard/Help/Rank.elm create mode 100644 src/map-editor/src/View/SubMenu.elm create mode 100644 src/map-editor/src/View/SubMenu/Characters.elm create mode 100644 src/map-editor/src/View/SubMenu/Settings.elm create mode 100644 src/map-editor/src/View/SubMenu/Status.elm create mode 100644 src/map-editor/src/View/SubMenu/Status/CharacterInfo.elm create mode 100644 src/map-editor/src/View/SubMenu/Status/TileInfo.elm create mode 100644 src/map-editor/src/View/ToolBox.elm create mode 100644 src/map-editor/www/index.html create mode 100644 src/map-editor/www/style.css diff --git a/src/map-editor/Makefile b/src/map-editor/Makefile new file mode 100644 index 0000000..3b58a08 --- /dev/null +++ b/src/map-editor/Makefile @@ -0,0 +1,36 @@ +################################################################################ +## CONFIG ###################################################################### +################################################################################ +SRC_DIR ?= src +WWW_DIR ?= www +WWW_SCRIPT_DIR ?= $(WWW_DIR)/script + +ELM_CC ?= elm-make --warn + +MAIN_MODULE ?= $(SRC_DIR)/Main.elm + +################################################################################ +## MAKEFILE MAGIC ############################################################## +################################################################################ +SUB_MODULES = $(shell find $(SRC_DIR) -type f | grep "elm$$") + +################################################################################ +## SANITY CHECKS ############################################################### +################################################################################ + +################################################################################ +## TARGET RULES ################################################################ +################################################################################ +build: $(WWW_SCRIPT_DIR)/main.js + +clean: + rm -f $(WWW_SCRIPT_DIR)/main.js + +reset: + rm -rf elm-stuff + +################################################################################ +## INTERNAL RULES ############################################################## +################################################################################ +$(WWW_SCRIPT_DIR)/main.js: $(MAIN_MODULE) $(SUB_MODULES) + $(ELM_CC) $(MAIN_MODULE) --output $@ diff --git a/src/map-editor/elm-package.json b/src/map-editor/elm-package.json new file mode 100644 index 0000000..43957bf --- /dev/null +++ b/src/map-editor/elm-package.json @@ -0,0 +1,19 @@ +{ + "version": "1.0.0", + "summary": "helpful summary of your project, less than 80 characters", + "repository": "https://github.com/nsensfel/tacticians-client.git", + "license": "Apache 2.0", + "source-directories": [ + "src" + ], + "exposed-modules": [], + "dependencies": { + "NoRedInk/elm-decode-pipeline": "3.0.0 <= v < 4.0.0", + "andrewMacmurray/elm-delay": "2.0.3 <= v < 3.0.0", + "elm-lang/core": "5.1.1 <= v < 6.0.0", + "elm-lang/dom": "1.1.1 <= v < 2.0.0", + "elm-lang/html": "2.0.0 <= v < 3.0.0", + "elm-lang/http": "1.0.0 <= v < 2.0.0" + }, + "elm-version": "0.18.0 <= v < 0.19.0" +} diff --git a/src/map-editor/src/Comm/AddTile.elm b/src/map-editor/src/Comm/AddTile.elm new file mode 100644 index 0000000..d0a3ce8 --- /dev/null +++ b/src/map-editor/src/Comm/AddTile.elm @@ -0,0 +1,24 @@ +module Comm.AddTile exposing (decode) + +-- Elm ------------------------------------------------------------------------- +import Json.Decode + +-- Battlemap ------------------------------------------------------------------- +import Struct.Tile +import Struct.ServerReply + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +internal_decoder : Struct.Tile.Type -> Struct.ServerReply.Type +internal_decoder wp = (Struct.ServerReply.AddTile wp) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +decode : (Json.Decode.Decoder Struct.ServerReply.Type) +decode = (Json.Decode.map (internal_decoder) (Struct.Tile.decoder)) diff --git a/src/map-editor/src/Comm/LoadBattlemap.elm b/src/map-editor/src/Comm/LoadBattlemap.elm new file mode 100644 index 0000000..cd29acf --- /dev/null +++ b/src/map-editor/src/Comm/LoadBattlemap.elm @@ -0,0 +1,42 @@ +module Comm.LoadBattlemap exposing (try) + +-- Elm ------------------------------------------------------------------------- +import Json.Encode + +-- Battlemap ------------------------------------------------------------------- +import Comm.Send + +import Constants.IO + +import Struct.Event +import Struct.Model + +-------------------------------------------------------------------------------- +-- TYPES ------------------------------------------------------------------------ +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +try_encoding : Struct.Model.Type -> (Maybe Json.Encode.Value) +try_encoding model = + (Just + (Json.Encode.object + [ + ("stk", (Json.Encode.string model.session_token)), + ("pid", (Json.Encode.string model.player_id)), + ("bmi", (Json.Encode.string model.battlemap_id)) + ] + ) + ) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +try : Struct.Model.Type -> (Maybe (Cmd Struct.Event.Type)) +try model = + (Comm.Send.try_sending + model + Constants.IO.battlemap_loading_handler + try_encoding + ) diff --git a/src/map-editor/src/Comm/Send.elm b/src/map-editor/src/Comm/Send.elm new file mode 100644 index 0000000..a6129cd --- /dev/null +++ b/src/map-editor/src/Comm/Send.elm @@ -0,0 +1,76 @@ +module Comm.Send exposing (try_sending) + +-- Elm ------------------------------------------------------------------------- +import Http + +import Json.Decode +import Json.Encode + +-- Battlemap ------------------------------------------------------------------- +import Comm.AddArmor +import Comm.AddChar +import Comm.AddTile +import Comm.AddWeapon +import Comm.SetMap +import Comm.SetTimeline +import Comm.TurnResults + +import Struct.Event +import Struct.ServerReply +import Struct.Model + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +internal_decoder : String -> (Json.Decode.Decoder Struct.ServerReply.Type) +internal_decoder reply_type = + case reply_type of + "add_tile" -> (Comm.AddTile.decode) + "add_armor" -> (Comm.AddArmor.decode) + "add_char" -> (Comm.AddChar.decode) + "add_weapon" -> (Comm.AddWeapon.decode) + "set_map" -> (Comm.SetMap.decode) + "turn_results" -> (Comm.TurnResults.decode) + "set_timeline" -> (Comm.SetTimeline.decode) + other -> + (Json.Decode.fail + ( + "Unknown server command \"" + ++ other + ++ "\"" + ) + ) + +decode : (Json.Decode.Decoder Struct.ServerReply.Type) +decode = + (Json.Decode.field "msg" Json.Decode.string) + |> (Json.Decode.andThen (internal_decoder)) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +try_sending : ( + Struct.Model.Type -> + String -> + (Struct.Model.Type -> (Maybe Json.Encode.Value)) -> + (Maybe (Cmd Struct.Event.Type)) + ) +try_sending model recipient try_encoding_fun = + case (try_encoding_fun model) of + (Just serial) -> + (Just + (Http.send + Struct.Event.ServerReplied + (Http.post + recipient + (Http.jsonBody serial) + (Json.Decode.list (decode)) + ) + ) + ) + + Nothing -> Nothing diff --git a/src/map-editor/src/Comm/SetMap.elm b/src/map-editor/src/Comm/SetMap.elm new file mode 100644 index 0000000..dc499cf --- /dev/null +++ b/src/map-editor/src/Comm/SetMap.elm @@ -0,0 +1,62 @@ +module Comm.SetMap exposing (decode) + +-- Elm ------------------------------------------------------------------------- +import Json.Decode + +-- Battlemap ------------------------------------------------------------------- +import Struct.Battlemap +import Struct.ServerReply +import Struct.Tile + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type alias MapData = + { + w : Int, + h : Int, + t : (List Int) + } + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +deserialize_tile_instance : Int -> Int -> Int -> Struct.Tile.Instance +deserialize_tile_instance map_width index id = + (Struct.Tile.new_instance + (index % map_width) + (index // map_width) + id + -1 + -1 + ) + +internal_decoder : MapData -> Struct.ServerReply.Type +internal_decoder map_data = + (Struct.ServerReply.SetMap + (Struct.Battlemap.new + map_data.w + map_data.h + (List.indexedMap + (deserialize_tile_instance map_data.w) + map_data.t + ) + ) + ) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +decode : (Json.Decode.Decoder Struct.ServerReply.Type) +decode = + (Json.Decode.map + internal_decoder + (Json.Decode.map3 MapData + (Json.Decode.field "w" Json.Decode.int) + (Json.Decode.field "h" Json.Decode.int) + (Json.Decode.field + "t" + (Json.Decode.list Json.Decode.int) + ) + ) + ) diff --git a/src/map-editor/src/Constants/IO.elm.m4 b/src/map-editor/src/Constants/IO.elm.m4 new file mode 100644 index 0000000..645ad14 --- /dev/null +++ b/src/map-editor/src/Constants/IO.elm.m4 @@ -0,0 +1,16 @@ +module Constants.IO exposing (..) + +base_url : String +base_url = "__CONF_SERVER_URL" + +map_editor_handler_url : String +map_editor_handler_url = (base_url ++ "/handler/map-editor") + +map_update_handler : String +map_update_handler = (map_editor_handler_url ++ "/me_update") + +map_loading_handler : String +map_loading_handler = (map_edit_handler_url ++ "/me_load_state") + +tile_assets_url : String +tile_assets_url = (base_url ++ "/asset/svg/tile/") diff --git a/src/map-editor/src/Constants/UI.elm b/src/map-editor/src/Constants/UI.elm new file mode 100644 index 0000000..e56553a --- /dev/null +++ b/src/map-editor/src/Constants/UI.elm @@ -0,0 +1,16 @@ +module Constants.UI exposing (..) + +tile_size : Int +tile_size = 32 + +variants_per_tile : Int +variants_per_tile = 9 + +viewer_html_id : String +viewer_html_id = "map_viewer" + +half_viewer_min_width : Float +half_viewer_min_width = 109.0 + +half_viewer_min_height : Float +half_viewer_min_height = 180.0 diff --git a/src/map-editor/src/ElmModule/Init.elm b/src/map-editor/src/ElmModule/Init.elm new file mode 100644 index 0000000..73230a3 --- /dev/null +++ b/src/map-editor/src/ElmModule/Init.elm @@ -0,0 +1,28 @@ +module ElmModule.Init exposing (init) + +-- Elm ------------------------------------------------------------------------- + +-- Battlemap ------------------------------------------------------------------- +import Comm.LoadMap + +import Struct.Event +import Struct.Flags +import Struct.Model + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +init : Struct.Flags.Type -> (Struct.Model.Type, (Cmd Struct.Event.Type)) +init flags = + let model = (Struct.Model.new flags) in + ( + model, + (case (Comm.LoadMap.try model) of + (Just cmd) -> cmd + Nothing -> Cmd.none + ) + ) diff --git a/src/map-editor/src/ElmModule/Subscriptions.elm b/src/map-editor/src/ElmModule/Subscriptions.elm new file mode 100644 index 0000000..f342b30 --- /dev/null +++ b/src/map-editor/src/ElmModule/Subscriptions.elm @@ -0,0 +1,17 @@ +module ElmModule.Subscriptions exposing (..) + +-- Elm ------------------------------------------------------------------------- + +-- Battlemap ------------------------------------------------------------------- +import Struct.Model +import Struct.Event + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +subscriptions : Struct.Model.Type -> (Sub Struct.Event.Type) +subscriptions model = Sub.none diff --git a/src/map-editor/src/ElmModule/Update.elm b/src/map-editor/src/ElmModule/Update.elm new file mode 100644 index 0000000..01ff72b --- /dev/null +++ b/src/map-editor/src/ElmModule/Update.elm @@ -0,0 +1,54 @@ +module ElmModule.Update exposing (update) + +-- Elm ------------------------------------------------------------------------- + +-- Battlemap ------------------------------------------------------------------- +import Struct.Event +import Struct.Model + +import Update.ChangeScale +import Update.HandleServerReply +import Update.SelectTab +import Update.SelectTile +import Update.SetRequestedHelp + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +update : ( + Struct.Event.Type -> + Struct.Model.Type -> + (Struct.Model.Type, (Cmd Struct.Event.Type)) + ) +update event model = + let + new_model = (Struct.Model.clear_error model) + in + case event of + Struct.Event.None -> (model, Cmd.none) + + (Struct.Event.Failed err) -> + ( + (Struct.Model.invalidate err new_model), + Cmd.none + ) + + (Struct.Event.TileSelected loc) -> + (Update.SelectTile.apply_to new_model loc) + + (Struct.Event.ScaleChangeRequested mod) -> + (Update.ChangeScale.apply_to new_model mod) + + (Struct.Event.TabSelected tab) -> + (Update.SelectTab.apply_to new_model tab) + + (Struct.Event.ServerReplied result) -> + (Update.HandleServerReply.apply_to model result) + + (Struct.Event.RequestedHelp help_request) -> + (Update.SetRequestedHelp.apply_to new_model help_request) diff --git a/src/map-editor/src/ElmModule/View.elm b/src/map-editor/src/ElmModule/View.elm new file mode 100644 index 0000000..de86372 --- /dev/null +++ b/src/map-editor/src/ElmModule/View.elm @@ -0,0 +1,56 @@ +module ElmModule.View exposing (view) + +-- Elm ------------------------------------------------------------------------- +import Html +import Html.Lazy +import Html.Attributes + +-- Battlemap ------------------------------------------------------------------- +import Constants.UI + +import Struct.Event +import Struct.Model + +import View.Map +import View.Controlled +import View.MessageBoard +import View.MainMenu +import View.SubMenu + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +view : Struct.Model.Type -> (Html.Html Struct.Event.Type) +view model = + (Html.div + [ + (Html.Attributes.class "fullscreen-module") + ] + [ + (View.MainMenu.get_html), + (Html.Lazy.lazy2 + (View.ToolBox.get_html) + model.toolbox + ), + (Html.div + [ + (Html.Attributes.class "map-container-centerer") + ] + [ + (Html.div + [ + (Html.Attributes.class "map-container"), + (Html.Attributes.id Constants.UI.viewer_html_id) + ] + [(View.Map.get_html model)] + ) + ] + ), + (View.SubMenu.get_html model), + (View.MessageBoard.get_html model) + ] + ) diff --git a/src/map-editor/src/Main.elm b/src/map-editor/src/Main.elm new file mode 100644 index 0000000..0d22cd5 --- /dev/null +++ b/src/map-editor/src/Main.elm @@ -0,0 +1,23 @@ +-- Elm ------------------------------------------------------------------------ +import Html + +-- Battlemap ------------------------------------------------------------------- +import Struct.Model +import Struct.Event +import Struct.Flags + +import ElmModule.Init +import ElmModule.Subscriptions +import ElmModule.View +import ElmModule.Update + +main : (Program Struct.Flags.Type Struct.Model.Type Struct.Event.Type) +main = + (Html.programWithFlags + { + init = ElmModule.Init.init, + view = ElmModule.View.view, + update = ElmModule.Update.update, + subscriptions = ElmModule.Subscriptions.subscriptions + } + ) diff --git a/src/map-editor/src/Struct/Battlemap.elm b/src/map-editor/src/Struct/Battlemap.elm new file mode 100644 index 0000000..fee4901 --- /dev/null +++ b/src/map-editor/src/Struct/Battlemap.elm @@ -0,0 +1,123 @@ +module Struct.Battlemap exposing + ( + Type, + empty, + new, + get_width, + get_height, + get_tiles, + get_movement_cost_function, + solve_tiles, + try_getting_tile_at + ) + +-- Elm ------------------------------------------------------------------------- +import Array + +-- Battlemap ------------------------------------------------------------------- +import Struct.Character +import Struct.Tile +import Struct.Location + +import Constants.Movement + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type alias Type = + { + width: Int, + height: Int, + content: (Array.Array Struct.Tile.Instance) + } + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +location_to_index : Struct.Location.Type -> Type -> Int +location_to_index loc bmap = + ((loc.y * bmap.width) + loc.x) + +has_location : Struct.Location.Type -> Type -> Bool +has_location loc bmap = + ( + (loc.x >= 0) + && (loc.y >= 0) + && (loc.x < bmap.width) + && (loc.y < bmap.height) + ) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_width : Type -> Int +get_width bmap = bmap.width + +get_height : Type -> Int +get_height bmap = bmap.height + +get_tiles : Type -> (Array.Array Struct.Tile.Instance) +get_tiles bmap = bmap.content + +empty : Type +empty = + { + width = 0, + height = 0, + content = (Array.empty) + } + +new : Int -> Int -> (List Struct.Tile.Instance) -> Type +new width height tiles = + { + width = width, + height = height, + content = (Array.fromList tiles) + } + +try_getting_tile_at : ( + Struct.Location.Type -> + Type -> + (Maybe Struct.Tile.Instance) + ) +try_getting_tile_at loc bmap = + (Array.get (location_to_index loc bmap) bmap.content) + +get_movement_cost_function : ( + Type -> + Struct.Location.Type -> + (List Struct.Character.Type) -> + Struct.Location.Type -> + Int + ) +get_movement_cost_function bmap start_loc char_list loc = + if (has_location loc bmap) + then + case (Array.get (location_to_index loc bmap) bmap.content) of + (Just tile) -> + if + (List.any + ( + \c -> + ( + ((Struct.Character.get_location c) == loc) + && (loc /= start_loc) + && (Struct.Character.is_alive c) + ) + ) + char_list + ) + then + Constants.Movement.cost_when_occupied_tile + else + (Struct.Tile.get_instance_cost tile) + + Nothing -> Constants.Movement.cost_when_out_of_bounds + else + Constants.Movement.cost_when_out_of_bounds + +solve_tiles : (List Struct.Tile.Type) -> Type -> Type +solve_tiles tiles bmap = + {bmap | + content = (Array.map (Struct.Tile.solve_tile_instance tiles) bmap.content) + } diff --git a/src/map-editor/src/Struct/Direction.elm b/src/map-editor/src/Struct/Direction.elm new file mode 100644 index 0000000..600138c --- /dev/null +++ b/src/map-editor/src/Struct/Direction.elm @@ -0,0 +1,52 @@ +module Struct.Direction exposing (Type(..), opposite_of, to_string, decoder) + +-- Elm ------------------------------------------------------------------------- +import Json.Decode + +-- Battlemap ------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type Type = + None + | Left + | Right + | Up + | Down + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +from_string : String -> Type +from_string str = + case str of + "R" -> Right + "L" -> Left + "U" -> Up + "D" -> Down + _ -> None + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +opposite_of : Type -> Type +opposite_of d = + case d of + Left -> Right + Right -> Left + Up -> Down + Down -> Up + None -> None + +to_string : Type -> String +to_string dir = + case dir of + Right -> "R" + Left -> "L" + Up -> "U" + Down -> "D" + None -> "N" + +decoder : (Json.Decode.Decoder Type) +decoder = (Json.Decode.map (from_string) Json.Decode.string) diff --git a/src/map-editor/src/Struct/Error.elm b/src/map-editor/src/Struct/Error.elm new file mode 100644 index 0000000..5f40c09 --- /dev/null +++ b/src/map-editor/src/Struct/Error.elm @@ -0,0 +1,45 @@ +module Struct.Error exposing (Type, Mode(..), new, to_string) + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type Mode = + IllegalAction + | Programming + | Unimplemented + | Networking + | Failure + +type alias Type = + { + mode: Mode, + message: String + } + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +new : Mode -> String -> Type +new mode str = + { + mode = mode, + message = str + } + +to_string : Type -> String +to_string e = + ( + (case e.mode of + Failure -> "The action failed: " + IllegalAction -> "Request discarded: " + Programming -> "Error in the program (please report): " + Unimplemented -> "Update discarded due to unimplemented feature: " + Networking -> "Error while conversing with the server: " + ) + ++ e.message + ) + diff --git a/src/map-editor/src/Struct/Event.elm b/src/map-editor/src/Struct/Event.elm new file mode 100644 index 0000000..716718e --- /dev/null +++ b/src/map-editor/src/Struct/Event.elm @@ -0,0 +1,44 @@ +module Struct.Event exposing (Type(..), attempted) + +-- Elm ------------------------------------------------------------------------- +import Http + +-- Battlemap ------------------------------------------------------------------- +import Struct.Direction +import Struct.Error +import Struct.Location +import Struct.ServerReply +import Struct.HelpRequest +import Struct.UI + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type Type = + AbortTurnRequest + | AnimationEnded + | AttackWithoutMovingRequest + | CharacterInfoRequested Int + | CharacterSelected Int + | DebugLoadBattlemapRequest + | DebugTeamSwitchRequest + | DebugTestAnimation + | DirectionRequested Struct.Direction.Type + | Failed Struct.Error.Type + | LookingForCharacter Int + | None + | ScaleChangeRequested Float + | ServerReplied (Result Http.Error (List Struct.ServerReply.Type)) + | TabSelected Struct.UI.Tab + | TileSelected Struct.Location.Ref + | CharacterOrTileSelected Struct.Location.Ref + | TurnEnded + | RequestedHelp Struct.HelpRequest.Type + | WeaponSwitchRequest + +attempted : (Result.Result err val) -> Type +attempted act = + case act of + (Result.Ok _) -> None + (Result.Err msg) -> + (Failed (Struct.Error.new Struct.Error.Failure (toString msg))) diff --git a/src/map-editor/src/Struct/Flags.elm b/src/map-editor/src/Struct/Flags.elm new file mode 100644 index 0000000..c0316f0 --- /dev/null +++ b/src/map-editor/src/Struct/Flags.elm @@ -0,0 +1,42 @@ +module Struct.Flags exposing + ( + Type, + maybe_get_param + ) + +-- Elm ------------------------------------------------------------------------- +import List + +-- Battlemap ------------------------------------------------------------------- +import Util.List + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type alias Type = + { + user_id : String, + token : String, + url_params : (List (List String)) + } + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +maybe_get_param : String -> Type -> (Maybe String) +maybe_get_param param flags = + case + (Util.List.get_first + (\e -> ((List.head e) == (Just param))) + flags.url_params + ) + of + Nothing -> Nothing + (Just a) -> + case (List.tail a) of + Nothing -> Nothing + (Just b) -> (List.head b) diff --git a/src/map-editor/src/Struct/HelpRequest.elm b/src/map-editor/src/Struct/HelpRequest.elm new file mode 100644 index 0000000..3357b56 --- /dev/null +++ b/src/map-editor/src/Struct/HelpRequest.elm @@ -0,0 +1,13 @@ +module Struct.HelpRequest exposing (Type(..)) + +-- Elm ------------------------------------------------------------------------- + +-- Battlemap ------------------------------------------------------------------- +import Struct.Character + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type Type = + None + | HelpOnRank Struct.Character.Rank diff --git a/src/map-editor/src/Struct/Location.elm b/src/map-editor/src/Struct/Location.elm new file mode 100644 index 0000000..d284d05 --- /dev/null +++ b/src/map-editor/src/Struct/Location.elm @@ -0,0 +1,59 @@ +module Struct.Location exposing (..) + +-- Elm ------------------------------------------------------------------------- +import Json.Decode +import Json.Decode.Pipeline + +-- Battlemap ------------------------------------------------------------------- +import Struct.Direction + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type alias Type = + { + x : Int, + y : Int + } + +type alias Ref = (Int, Int) + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +neighbor : Struct.Direction.Type -> Type -> Type +neighbor dir loc = + case dir of + Struct.Direction.Right -> {loc | x = (loc.x + 1)} + Struct.Direction.Left -> {loc | x = (loc.x - 1)} + Struct.Direction.Up -> {loc | y = (loc.y - 1)} + Struct.Direction.Down -> {loc | y = (loc.y + 1)} + Struct.Direction.None -> loc + +get_ref : Type -> Ref +get_ref l = + (l.x, l.y) + +from_ref : Ref -> Type +from_ref (x, y) = + {x = x, y = y} + +dist : Type -> Type -> Int +dist loc_a loc_b = + ( + (abs (loc_a.x - loc_b.x)) + + + (abs (loc_a.y - loc_b.y)) + ) + +decoder : (Json.Decode.Decoder Type) +decoder = + (Json.Decode.Pipeline.decode + Type + |> (Json.Decode.Pipeline.required "x" Json.Decode.int) + |> (Json.Decode.Pipeline.required "y" Json.Decode.int) + ) diff --git a/src/map-editor/src/Struct/Model.elm b/src/map-editor/src/Struct/Model.elm new file mode 100644 index 0000000..0095364 --- /dev/null +++ b/src/map-editor/src/Struct/Model.elm @@ -0,0 +1,254 @@ +module Struct.Model exposing + ( + Type, + new, + add_character, + update_character, + update_character_fun, + add_weapon, + add_armor, + add_tile, + invalidate, + initialize_animator, + apply_animator_step, + move_animator_to_next_step, + reset, + full_debug_reset, + clear_error + ) + +-- Elm ------------------------------------------------------------------------- +import Array + +import Dict + +-- Battlemap ------------------------------------------------------------------- +import Struct.Armor +import Struct.Battlemap +import Struct.Character +import Struct.CharacterTurn +import Struct.Error +import Struct.Flags +import Struct.HelpRequest +import Struct.Tile +import Struct.TurnResult +import Struct.TurnResultAnimator +import Struct.UI +import Struct.Weapon + +import Util.Array + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type alias Type = + { + help_request: Struct.HelpRequest.Type, + animator: (Maybe Struct.TurnResultAnimator.Type), + battlemap: Struct.Battlemap.Type, + characters: (Array.Array Struct.Character.Type), + weapons: (Dict.Dict Struct.Weapon.Ref Struct.Weapon.Type), + armors: (Dict.Dict Struct.Armor.Ref Struct.Armor.Type), + tiles: (Dict.Dict Struct.Tile.Ref Struct.Tile.Type), + error: (Maybe Struct.Error.Type), + player_id: String, + battlemap_id: String, + session_token: String, + player_ix: Int, + ui: Struct.UI.Type, + char_turn: Struct.CharacterTurn.Type, + timeline: (Array.Array Struct.TurnResult.Type) + } + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +new : Struct.Flags.Type -> Type +new flags = + let + maybe_battlemap_id = (Struct.Flags.maybe_get_param "id" flags) + model = + { + help_request = Struct.HelpRequest.None, + animator = Nothing, + battlemap = (Struct.Battlemap.empty), + characters = (Array.empty), + weapons = (Dict.empty), + armors = (Dict.empty), + tiles = (Dict.empty), + error = Nothing, + battlemap_id = "", + player_id = + ( + if (flags.user_id == "") + then "0" + else flags.user_id + ), + session_token = flags.token, + player_ix = 0, + ui = (Struct.UI.default), + char_turn = (Struct.CharacterTurn.new), + timeline = (Array.empty) + } + in + case maybe_battlemap_id of + Nothing -> + (invalidate + (Struct.Error.new + Struct.Error.Failure + "Could not find battlemap id." + ) + model + ) + + (Just id) -> {model | battlemap_id = id} + +add_character : Struct.Character.Type -> Type -> Type +add_character char model = + {model | + characters = + (Array.push + char + model.characters + ) + } + +add_weapon : Struct.Weapon.Type -> Type -> Type +add_weapon wp model = + {model | + weapons = + (Dict.insert + (Struct.Weapon.get_id wp) + wp + model.weapons + ) + } + +add_armor : Struct.Armor.Type -> Type -> Type +add_armor ar model = + {model | + armors = + (Dict.insert + (Struct.Armor.get_id ar) + ar + model.armors + ) + } + +add_tile : Struct.Tile.Type -> Type -> Type +add_tile tl model = + {model | + tiles = + (Dict.insert + (Struct.Tile.get_id tl) + tl + model.tiles + ) + } + +reset : Type -> Type +reset model = + {model | + help_request = Struct.HelpRequest.None, + error = Nothing, + ui = + (Struct.UI.reset_displayed_nav + (Struct.UI.set_previous_action Nothing model.ui) + ), + char_turn = (Struct.CharacterTurn.new) + } + +full_debug_reset : Type -> Type +full_debug_reset model = + {model | + help_request = Struct.HelpRequest.None, + animator = Nothing, + battlemap = (Struct.Battlemap.empty), + characters = (Array.empty), + weapons = (Dict.empty), + armors = (Dict.empty), + tiles = (Dict.empty), + error = Nothing, + ui = (Struct.UI.default), + char_turn = (Struct.CharacterTurn.new), + timeline = (Array.empty) + } + +initialize_animator : Type -> Type +initialize_animator model = + let + timeline_list = (Array.toList model.timeline) + in + {model | + animator = + (Struct.TurnResultAnimator.maybe_new + (List.reverse timeline_list) + True + ), + ui = (Struct.UI.default), + characters = + (List.foldr + (Struct.TurnResult.apply_inverse_to_characters) + model.characters + timeline_list + ) + } + +move_animator_to_next_step : Type -> Type +move_animator_to_next_step model = + case model.animator of + Nothing -> model + (Just animator) -> + {model | + animator = + (Struct.TurnResultAnimator.maybe_trigger_next_step animator) + } + +apply_animator_step : Type -> Type +apply_animator_step model = + case model.animator of + Nothing -> model + (Just animator) -> + {model | + characters = + case + (Struct.TurnResultAnimator.get_current_animation animator) + of + (Struct.TurnResultAnimator.TurnResult turn_result) -> + (Struct.TurnResult.apply_step_to_characters + turn_result + model.characters + ) + + _ -> model.characters + } + +update_character : Int -> Struct.Character.Type -> Type -> Type +update_character ix new_val model = + {model | + characters = (Array.set ix new_val model.characters) + } + +update_character_fun : ( + Int -> + ((Maybe Struct.Character.Type) -> (Maybe Struct.Character.Type)) -> + Type -> + Type + ) +update_character_fun ix fun model = + {model | + characters = (Util.Array.update ix (fun) model.characters) + } + +invalidate : Struct.Error.Type -> Type -> Type +invalidate err model = + {model | + error = (Just err) + } + +clear_error : Type -> Type +clear_error model = {model | error = Nothing} diff --git a/src/map-editor/src/Struct/ServerReply.elm b/src/map-editor/src/Struct/ServerReply.elm new file mode 100644 index 0000000..5b88933 --- /dev/null +++ b/src/map-editor/src/Struct/ServerReply.elm @@ -0,0 +1,33 @@ +module Struct.ServerReply exposing (Type(..)) + +-- Elm ------------------------------------------------------------------------- + +-- Battlemap ------------------------------------------------------------------- +import Struct.Armor +import Struct.Battlemap +import Struct.Character +import Struct.Tile +import Struct.TurnResult +import Struct.Weapon + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +type Type = + Okay + | AddArmor Struct.Armor.Type + | AddWeapon Struct.Weapon.Type + | AddCharacter (Struct.Character.Type, Int, Int, Int) + | AddTile Struct.Tile.Type + | SetMap Struct.Battlemap.Type + | TurnResults (List Struct.TurnResult.Type) + | SetTimeline (List Struct.TurnResult.Type) + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- diff --git a/src/map-editor/src/Struct/Tile.elm b/src/map-editor/src/Struct/Tile.elm new file mode 100644 index 0000000..a683be3 --- /dev/null +++ b/src/map-editor/src/Struct/Tile.elm @@ -0,0 +1,203 @@ +module Struct.Tile exposing + ( + Ref, + Type, + Instance, + new, + new_instance, + error_tile_instance, + get_id, + get_name, + get_range_minimum, + get_range_maximum, + get_cost, + get_instance_cost, + get_location, + get_icon_id, + get_type_id, + get_variant_id, + solve_tile_instance, + decoder + ) + +-- Elm ------------------------------------------------------------------------- +import List + +import Json.Decode +import Json.Decode.Pipeline + +-- Battlemap ------------------------------------------------------------------- +import Constants.UI +import Constants.Movement + +import Struct.Location + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type alias Ref = Int + +type alias PartiallyDecoded = + { + id : Int, + nam : String, + ct : Int, + rmi : Int, + rma : Int + } + +type alias Type = + { + id : Int, + name : String, + crossing_cost : Int, + range_minimum : Int, + range_maximum : Int + } + +type alias Instance = + { + location : Struct.Location.Type, + icon_id : Int, + crossing_cost : Int, + type_id : Int + } + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +noise_function : Int -> Int -> Int -> Int +noise_function a b c = + (round (radians (toFloat ((a + 1) * 2 + (b + 1) * 3 + c)))) + +finish_decoding : PartiallyDecoded -> Type +finish_decoding add_tile = + { + id = add_tile.id, + name = add_tile.nam, + crossing_cost = add_tile.ct, + range_minimum = add_tile.rmi, + range_maximum = add_tile.rma + } + +seek_tile_instance_type : Instance -> Type -> (Maybe Type) -> (Maybe Type) +seek_tile_instance_type instance candidate current_sol = + if (current_sol == Nothing) + then + let + icon_id = instance.icon_id + in + if + ( + (icon_id >= candidate.range_minimum) + && (icon_id <= candidate.range_maximum) + ) + then + (Just candidate) + else + current_sol + else + current_sol + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +new : Int -> String -> Int -> Int -> Int -> Type +new id name crossing_cost range_minimum range_maximum = + { + id = id, + name = name, + crossing_cost = crossing_cost, + range_minimum = range_minimum, + range_maximum = range_maximum + } + +new_instance : Int -> Int -> Int -> Int -> Int -> Instance +new_instance x y icon_id crossing_cost type_id = + { + location = {x = x, y = y}, + icon_id = icon_id, + crossing_cost = crossing_cost, + type_id = type_id + } + +error_tile_instance : Int -> Int -> Instance +error_tile_instance x y = + { + location = {x = x, y = y}, + icon_id = -1, + type_id = -1, + crossing_cost = Constants.Movement.cost_when_out_of_bounds + } + + +get_id : Type -> Int +get_id tile = tile.id + +get_cost : Type -> Int +get_cost tile = tile.crossing_cost + +get_instance_cost : Instance -> Int +get_instance_cost tile_inst = tile_inst.crossing_cost + +get_name : Type -> String +get_name tile = tile.name + +get_range_minimum : Type -> Int +get_range_minimum tile = tile.range_minimum + +get_range_maximum : Type -> Int +get_range_maximum tile = tile.range_maximum + +get_location : Instance -> Struct.Location.Type +get_location tile_inst = tile_inst.location + +get_icon_id : Instance -> String +get_icon_id tile_inst = (toString tile_inst.icon_id) + +get_type_id: Instance -> Int +get_type_id tile_inst = tile_inst.type_id + +get_variant_id : Instance -> Int +get_variant_id tile_inst = + ( + (noise_function + tile_inst.location.x + tile_inst.location.y + tile_inst.crossing_cost + ) + % Constants.UI.variants_per_tile + ) + +solve_tile_instance : (List Type) -> Instance -> Instance +solve_tile_instance tiles tile_instance = + let + maybe_type = + (List.foldr (seek_tile_instance_type tile_instance) Nothing tiles) + in + case maybe_type of + (Just tile) -> + {tile_instance | + type_id = tile.id, + crossing_cost = tile.crossing_cost + } + + Nothing -> + (error_tile_instance + tile_instance.location.x + tile_instance.location.y + ) + +decoder : (Json.Decode.Decoder Type) +decoder = + (Json.Decode.map + (finish_decoding) + (Json.Decode.Pipeline.decode + PartiallyDecoded + |> (Json.Decode.Pipeline.required "id" Json.Decode.int) + |> (Json.Decode.Pipeline.required "nam" Json.Decode.string) + |> (Json.Decode.Pipeline.required "ct" Json.Decode.int) + |> (Json.Decode.Pipeline.required "rmi" Json.Decode.int) + |> (Json.Decode.Pipeline.required "rma" Json.Decode.int) + ) + ) diff --git a/src/map-editor/src/Struct/UI.elm b/src/map-editor/src/Struct/UI.elm new file mode 100644 index 0000000..447cfc4 --- /dev/null +++ b/src/map-editor/src/Struct/UI.elm @@ -0,0 +1,139 @@ +module Struct.UI exposing + ( + Type, + Tab(..), + Action(..), + default, + -- Zoom + get_zoom_level, + reset_zoom_level, + mod_zoom_level, + -- Tab + try_getting_displayed_tab, + set_displayed_tab, + reset_displayed_tab, + to_string, + get_all_tabs, + -- Navigator + try_getting_displayed_nav, + set_displayed_nav, + reset_displayed_nav, + -- Manual Controls + has_manual_controls_enabled, + -- Previous Action + has_focus, + get_previous_action, + set_previous_action + ) + +-- Battlemap ------------------------------------------------------------------- +import Struct.Location +import Struct.Navigator + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type Tab = + StatusTab + | CharactersTab + | SettingsTab + | TimelineTab + +type Action = + UsedManualControls + | SelectedLocation Struct.Location.Ref + | SelectedCharacter Int + | AttackedCharacter Int + +type alias Type = + { + zoom_level : Float, + show_manual_controls : Bool, + displayed_tab : (Maybe Tab), + previous_action : (Maybe Action), + displayed_nav : (Maybe Struct.Navigator.Type) + } + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +default : Type +default = + { + zoom_level = 1.0, + show_manual_controls = True, + displayed_tab = Nothing, + previous_action = Nothing, + displayed_nav = Nothing + } + +-- Zoom ------------------------------------------------------------------------ +get_zoom_level : Type -> Float +get_zoom_level ui = ui.zoom_level + +reset_zoom_level : Type -> Type +reset_zoom_level ui = {ui | zoom_level = 1.0} + +mod_zoom_level : Float -> Type -> Type +mod_zoom_level mod ui = {ui | zoom_level = (mod * ui.zoom_level)} + +-- Tab ------------------------------------------------------------------------- +try_getting_displayed_tab : Type -> (Maybe Tab) +try_getting_displayed_tab ui = ui.displayed_tab + +set_displayed_tab : Tab -> Type -> Type +set_displayed_tab tab ui = {ui | displayed_tab = (Just tab)} + +reset_displayed_tab : Type -> Type +reset_displayed_tab ui = {ui | displayed_tab = Nothing} + +to_string : Tab -> String +to_string tab = + case tab of + StatusTab -> "Status" + CharactersTab -> "Characters" + SettingsTab -> "Settings" + TimelineTab -> "Timeline" + +get_all_tabs : (List Tab) +get_all_tabs = + [StatusTab, CharactersTab, SettingsTab, TimelineTab] + +-- Navigator ------------------------------------------------------------------- +try_getting_displayed_nav : Type -> (Maybe Struct.Navigator.Type) +try_getting_displayed_nav ui = ui.displayed_nav + +set_displayed_nav : Struct.Navigator.Type -> Type -> Type +set_displayed_nav nav ui = {ui | displayed_nav = (Just nav)} + +reset_displayed_nav : Type -> Type +reset_displayed_nav ui = {ui | displayed_nav = Nothing} + +-- ManualControls -------------------------------------------------------------- +has_manual_controls_enabled : Type -> Bool +has_manual_controls_enabled ui = ui.show_manual_controls + +toggle_manual_controls : Type -> Type +toggle_manual_controls ui = + if (ui.show_manual_controls) + then + {ui | show_manual_controls = False} + else + {ui | show_manual_controls = True} + +set_enable_manual_controls : Bool -> Type -> Type +set_enable_manual_controls val ui = {ui | show_manual_controls = val} + +-- Previous Action ------------------------------------------------------------- +has_focus : Type -> Bool +has_focus ui = True + +set_previous_action : (Maybe Action) -> Type -> Type +set_previous_action act ui = {ui | previous_action = act} + +get_previous_action : Type -> (Maybe Action) +get_previous_action ui = ui.previous_action diff --git a/src/map-editor/src/Update/ChangeScale.elm b/src/map-editor/src/Update/ChangeScale.elm new file mode 100644 index 0000000..a2e10ce --- /dev/null +++ b/src/map-editor/src/Update/ChangeScale.elm @@ -0,0 +1,26 @@ +module Update.ChangeScale exposing (apply_to) +-- Elm ------------------------------------------------------------------------- + +-- Battlemap ------------------------------------------------------------------- +import Struct.Event +import Struct.Model +import Struct.UI + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +apply_to : ( + Struct.Model.Type -> + Float -> + (Struct.Model.Type, (Cmd Struct.Event.Type)) + ) +apply_to model mod = + if (mod == 0.0) + then + ({model | ui = (Struct.UI.reset_zoom_level model.ui)}, Cmd.none) + else + ({model | ui = (Struct.UI.mod_zoom_level mod model.ui)}, Cmd.none) diff --git a/src/map-editor/src/Update/HandleServerReply.elm b/src/map-editor/src/Update/HandleServerReply.elm new file mode 100644 index 0000000..bc347c9 --- /dev/null +++ b/src/map-editor/src/Update/HandleServerReply.elm @@ -0,0 +1,230 @@ +module Update.HandleServerReply exposing (apply_to) + +-- Elm ------------------------------------------------------------------------- +import Array + +import Delay + +import Dict + +import Http + +import Time + +-- Battlemap ------------------------------------------------------------------- +import Struct.Armor +import Struct.Battlemap +import Struct.Character +import Struct.Error +import Struct.Event +import Struct.Model +import Struct.ServerReply +import Struct.Tile +import Struct.TurnResult +import Struct.TurnResultAnimator +import Struct.UI +import Struct.Weapon + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +weapon_getter : Struct.Model.Type -> Struct.Weapon.Ref -> Struct.Weapon.Type +weapon_getter model ref = + case (Dict.get ref model.weapons) of + (Just w) -> w + Nothing -> Struct.Weapon.none + +armor_getter : Struct.Model.Type -> Struct.Armor.Ref -> Struct.Armor.Type +armor_getter model ref = + case (Dict.get ref model.armors) of + (Just w) -> w + Nothing -> Struct.Armor.none + +----------- + +add_armor : ( + Struct.Armor.Type -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) + ) +add_armor ar current_state = + case current_state of + (_, (Just _)) -> current_state + (model, _) -> ((Struct.Model.add_armor ar model), Nothing) + +add_tile : ( + Struct.Tile.Type -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) + ) +add_tile tl current_state = + case current_state of + (_, (Just _)) -> current_state + (model, _) -> ((Struct.Model.add_tile tl model), Nothing) + +add_weapon : ( + Struct.Weapon.Type -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) + ) +add_weapon wp current_state = + case current_state of + (_, (Just _)) -> current_state + (model, _) -> ((Struct.Model.add_weapon wp model), Nothing) + +add_character : ( + (Struct.Character.Type, Int, Int, Int) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) + ) +add_character char_and_refs current_state = + case current_state of + (_, (Just _)) -> current_state + (model, _) -> + let + (char, awp_ref, swp_ref, ar_ref) = char_and_refs + awp = (weapon_getter model awp_ref) + swp = (weapon_getter model swp_ref) + ar = (armor_getter model ar_ref) + in + ( + (Struct.Model.add_character + (Struct.Character.fill_missing_equipment awp swp ar char) + model + ), + Nothing + ) + +set_map : ( + Struct.Battlemap.Type -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) + ) +set_map map current_state = + case current_state of + (_, (Just _)) -> current_state + (model, _) -> + ( + {model | + battlemap = + (Struct.Battlemap.solve_tiles (Dict.values model.tiles) map) + }, + Nothing + ) + +add_to_timeline : ( + (List Struct.TurnResult.Type) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) + ) +add_to_timeline turn_results current_state = + case current_state of + (_, (Just _)) -> current_state + + (model, _) -> + ( + {model | + animator = + (Struct.TurnResultAnimator.maybe_new + (List.reverse turn_results) + False + ), + timeline = + (Array.append + (Array.fromList turn_results) + model.timeline + ), + ui = + (Struct.UI.set_displayed_tab + Struct.UI.TimelineTab + model.ui + ) + }, + Nothing + ) + +set_timeline : ( + (List Struct.TurnResult.Type) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) + ) +set_timeline turn_results current_state = + case current_state of + (_, (Just _)) -> current_state + + (model, _) -> + ( + {model | timeline = (Array.fromList turn_results)}, + Nothing + ) + +apply_command : ( + Struct.ServerReply.Type -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) + ) +apply_command command current_state = + case command of + (Struct.ServerReply.AddWeapon wp) -> + (add_weapon wp current_state) + + (Struct.ServerReply.AddArmor ar) -> + (add_armor ar current_state) + + (Struct.ServerReply.AddTile tl) -> + (add_tile tl current_state) + + (Struct.ServerReply.AddCharacter char) -> + (add_character char current_state) + + (Struct.ServerReply.SetMap map) -> + (set_map map current_state) + + (Struct.ServerReply.TurnResults results) -> + (add_to_timeline results current_state) + + (Struct.ServerReply.SetTimeline timeline) -> + (set_timeline timeline current_state) + + Struct.ServerReply.Okay -> current_state + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +apply_to : ( + Struct.Model.Type -> + (Result Http.Error (List Struct.ServerReply.Type)) -> + (Struct.Model.Type, (Cmd Struct.Event.Type)) + ) +apply_to model query_result = + case query_result of + (Result.Err error) -> + ( + (Struct.Model.invalidate + (Struct.Error.new Struct.Error.Networking (toString error)) + model + ), + Cmd.none + ) + + (Result.Ok commands) -> + let + new_model = + ( + case (List.foldl (apply_command) (model, Nothing) commands) of + (updated_model, Nothing) -> updated_model + (_, (Just error)) -> (Struct.Model.invalidate error model) + ) + in + ( + new_model, + if (new_model.animator == Nothing) + then + Cmd.none + else + (Delay.after 1 Time.millisecond Struct.Event.AnimationEnded) + ) diff --git a/src/map-editor/src/Update/SelectTab.elm b/src/map-editor/src/Update/SelectTab.elm new file mode 100644 index 0000000..c25ec56 --- /dev/null +++ b/src/map-editor/src/Update/SelectTab.elm @@ -0,0 +1,32 @@ +module Update.SelectTab exposing (apply_to) +-- Elm ------------------------------------------------------------------------- + +-- Battlemap ------------------------------------------------------------------- +import Struct.Model +import Struct.Event +import Struct.UI + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +apply_to : ( + Struct.Model.Type -> + Struct.UI.Tab -> + (Struct.Model.Type, (Cmd Struct.Event.Type)) + ) +apply_to model tab = + if ((Struct.UI.try_getting_displayed_tab model.ui) == (Just tab)) + then + ( + {model | ui = (Struct.UI.reset_displayed_tab model.ui)}, + Cmd.none + ) + else + ( + {model | ui = (Struct.UI.set_displayed_tab tab model.ui)}, + Cmd.none + ) diff --git a/src/map-editor/src/Update/SelectTile.elm b/src/map-editor/src/Update/SelectTile.elm new file mode 100644 index 0000000..6d05476 --- /dev/null +++ b/src/map-editor/src/Update/SelectTile.elm @@ -0,0 +1,158 @@ +module Update.SelectTile exposing (apply_to) + +-- Elm ------------------------------------------------------------------------- + +-- Battlemap ------------------------------------------------------------------- +import Struct.CharacterTurn +import Struct.Direction +import Struct.Error +import Struct.Event +import Struct.Location +import Struct.Model +import Struct.Navigator +import Struct.UI + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +try_autopiloting : ( + Struct.Direction.Type -> + (Maybe Struct.Navigator.Type) -> + (Maybe Struct.Navigator.Type) + ) +try_autopiloting dir maybe_nav = + case maybe_nav of + (Just navigator) -> + (Struct.Navigator.try_adding_step dir navigator) + + Nothing -> Nothing + +go_to_tile : ( + Struct.Model.Type -> + Struct.Navigator.Type -> + Struct.Location.Ref -> + (Struct.Model.Type, (Cmd Struct.Event.Type)) + ) +go_to_tile model navigator loc_ref = + if + ( + loc_ref + == + (Struct.Location.get_ref + (Struct.Navigator.get_current_location navigator) + ) + ) + then + -- We are already there. + if + ( + (Struct.UI.get_previous_action model.ui) + == + (Just (Struct.UI.SelectedLocation loc_ref)) + ) + then + -- And we just clicked on that tile. + ( + {model | + char_turn = + (Struct.CharacterTurn.lock_path model.char_turn) + }, + Cmd.none + ) + else + -- And we didn't just click on that tile. + ( + {model | + ui = + (Struct.UI.reset_displayed_nav + (Struct.UI.set_displayed_tab + Struct.UI.StatusTab + (Struct.UI.set_previous_action + (Just (Struct.UI.SelectedLocation loc_ref)) + model.ui + ) + ) + ) + }, + Cmd.none + ) + else + -- We have to try getting there. + case + (Struct.Navigator.try_getting_path_to + loc_ref + navigator + ) + of + (Just path) -> + case + (List.foldr + (try_autopiloting) + (Just (Struct.Navigator.clear_path navigator)) + path + ) + of + (Just new_navigator) -> + ( + {model | + char_turn = + (Struct.CharacterTurn.set_navigator + new_navigator + model.char_turn + ), + ui = + (Struct.UI.set_displayed_tab + Struct.UI.StatusTab + (Struct.UI.set_previous_action + (Just (Struct.UI.SelectedLocation loc_ref)) + model.ui + ) + ) + }, + Cmd.none + ) + + Nothing -> + ( + (Struct.Model.invalidate + (Struct.Error.new + Struct.Error.Programming + "SelectTile/Navigator: Could not follow own path." + ) + model + ), + Cmd.none + ) + + Nothing -> -- Clicked outside of the range indicator + ((Struct.Model.reset model), Cmd.none) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +apply_to : ( + Struct.Model.Type -> + Struct.Location.Ref -> + (Struct.Model.Type, (Cmd Struct.Event.Type)) + ) +apply_to model loc_ref = + case (Struct.CharacterTurn.try_getting_navigator model.char_turn) of + (Just navigator) -> + (go_to_tile model navigator loc_ref) + + _ -> + ( + {model | + ui = + (Struct.UI.reset_displayed_nav + (Struct.UI.set_displayed_tab + Struct.UI.StatusTab + (Struct.UI.set_previous_action + (Just (Struct.UI.SelectedLocation loc_ref)) + model.ui + ) + ) + ) + }, + Cmd.none + ) diff --git a/src/map-editor/src/Update/SetRequestedHelp.elm b/src/map-editor/src/Update/SetRequestedHelp.elm new file mode 100644 index 0000000..8f76e3b --- /dev/null +++ b/src/map-editor/src/Update/SetRequestedHelp.elm @@ -0,0 +1,22 @@ +module Update.SetRequestedHelp exposing (apply_to) +-- Elm ------------------------------------------------------------------------- + +-- Battlemap ------------------------------------------------------------------- +import Struct.Event +import Struct.HelpRequest +import Struct.Model + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +apply_to : ( + Struct.Model.Type -> + Struct.HelpRequest.Type -> + (Struct.Model.Type, (Cmd Struct.Event.Type)) + ) +apply_to model help_request = + ({model | help_request = help_request}, Cmd.none) diff --git a/src/map-editor/src/Util/Array.elm b/src/map-editor/src/Util/Array.elm new file mode 100644 index 0000000..9e57c18 --- /dev/null +++ b/src/map-editor/src/Util/Array.elm @@ -0,0 +1,34 @@ +module Util.Array exposing + ( + update, + update_unsafe, + filter_first + ) + +import Array + +update : ( + Int -> + ((Maybe t) -> (Maybe t)) -> + (Array.Array t) -> + (Array.Array t) + ) +update index fun array = + case (fun (Array.get index array)) of + Nothing -> array + (Just e) -> (Array.set index e array) + +update_unsafe : ( + Int -> + (t -> t) -> + (Array.Array t) -> + (Array.Array t) + ) +update_unsafe index fun array = + case (Array.get index array) of + Nothing -> array + (Just e) -> (Array.set index (fun e) array) + +filter_first : (t -> Bool) -> (Array.Array t) -> (Maybe t) +filter_first fun array = + (Array.get 0 (Array.filter fun array)) diff --git a/src/map-editor/src/Util/Html.elm b/src/map-editor/src/Util/Html.elm new file mode 100644 index 0000000..42eadba --- /dev/null +++ b/src/map-editor/src/Util/Html.elm @@ -0,0 +1,6 @@ +module Util.Html exposing (nothing) + +import Html + +nothing : (Html.Html a) +nothing = (Html.text "") diff --git a/src/map-editor/src/Util/List.elm b/src/map-editor/src/Util/List.elm new file mode 100644 index 0000000..2bc5217 --- /dev/null +++ b/src/map-editor/src/Util/List.elm @@ -0,0 +1,16 @@ +module Util.List exposing (..) + +import List + +pop : List a -> (Maybe (a, List a)) +pop l = + case + ((List.head l), (List.tail l)) + of + (Nothing, _) -> Nothing + (_ , Nothing) -> Nothing + ((Just head), (Just tail)) -> (Just (head, tail)) + +get_first : (a -> Bool) -> (List a) -> (Maybe a) +get_first fun list = + (List.head (List.filter fun list)) diff --git a/src/map-editor/src/View/MainMenu.elm b/src/map-editor/src/View/MainMenu.elm new file mode 100644 index 0000000..f301ea6 --- /dev/null +++ b/src/map-editor/src/View/MainMenu.elm @@ -0,0 +1,38 @@ +module View.MainMenu exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Html +import Html.Attributes +import Html.Events + +-- Battlemap ------------------------------------------------------------------- +import Struct.Event +import Struct.UI + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_menu_button_html : ( + Struct.UI.Tab -> + (Html.Html Struct.Event.Type) + ) +get_menu_button_html tab = + (Html.button + [ (Html.Events.onClick (Struct.Event.TabSelected tab)) ] + [ (Html.text (Struct.UI.to_string tab)) ] + ) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : (Html.Html Struct.Event.Type) +get_html = + (Html.div + [ + (Html.Attributes.class "battlemap-main-menu") + ] + (List.map + (get_menu_button_html) + (Struct.UI.get_all_tabs) + ) + ) diff --git a/src/map-editor/src/View/Map.elm b/src/map-editor/src/View/Map.elm new file mode 100644 index 0000000..c185486 --- /dev/null +++ b/src/map-editor/src/View/Map.elm @@ -0,0 +1,162 @@ +module View.Battlemap exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Array + +import Html +import Html.Attributes +import Html.Lazy + +import List + +-- Battlemap ------------------------------------------------------------------- +import Constants.UI + +import Struct.Battlemap +import Struct.Character +import Struct.Event +import Struct.Model +import Struct.Navigator +import Struct.UI + +import Util.Html + +import View.Battlemap.Character +import View.Battlemap.Navigator +import View.Battlemap.Tile + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_tiles_html : Struct.Battlemap.Type -> (Html.Html Struct.Event.Type) +get_tiles_html battlemap = + (Html.div + [ + (Html.Attributes.class "battlemap-tiles-layer"), + (Html.Attributes.style + [ + ( + "width", + ( + (toString + ( + (Struct.Battlemap.get_width battlemap) + * Constants.UI.tile_size + ) + ) + ++ "px" + ) + ), + ( + "height", + ( + (toString + ( + (Struct.Battlemap.get_height battlemap) + * Constants.UI.tile_size + ) + ) + ++ "px" + ) + ) + ] + ) + ] + (List.map + (View.Battlemap.Tile.get_html) + (Array.toList (Struct.Battlemap.get_tiles battlemap)) + ) + ) + +maybe_print_navigator : ( + Bool -> + (Maybe Struct.Navigator.Type) -> + (Html.Html Struct.Event.Type) + ) +maybe_print_navigator interactive maybe_nav = + let + name_suffix = + if (interactive) + then + "interactive" + else + "non-interactive" + in + case maybe_nav of + (Just nav) -> + (Html.div + [ + (Html.Attributes.class ("battlemap-navigator" ++ name_suffix)) + ] + (View.Battlemap.Navigator.get_html + (Struct.Navigator.get_summary nav) + interactive + ) + ) + + Nothing -> + (Util.Html.nothing) + +get_characters_html : ( + Struct.Model.Type -> + (Array.Array Struct.Character.Type) -> + (Html.Html Struct.Event.Type) + ) +get_characters_html model characters = + (Html.div + [ + (Html.Attributes.class "battlemap-characters") + ] + (List.map + (View.Battlemap.Character.get_html model) + (Array.toList model.characters) + ) + ) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : ( + Struct.Model.Type -> + (Html.Html Struct.Event.Type) + ) +get_html model = + (Html.div + [ + (Html.Attributes.class "battlemap-actual"), + (Html.Attributes.style + ( + if ((Struct.UI.get_zoom_level model.ui) == 1) + then [] + else + [ + ( + "transform", + ( + "scale(" + ++ + (toString (Struct.UI.get_zoom_level model.ui)) + ++ ")" + ) + ) + ] + ) + ) + ] + [ + (Html.Lazy.lazy (get_tiles_html) model.battlemap), + -- Not in lazy mode, because I can't easily get rid of that 'model' + -- parameter. + (get_characters_html model model.characters), + (Html.Lazy.lazy2 + (maybe_print_navigator) + True + model.char_turn.navigator + ), + (Html.Lazy.lazy2 + (maybe_print_navigator) + False + (Struct.UI.try_getting_displayed_nav model.ui) + ) + ] + ) diff --git a/src/map-editor/src/View/Map/Character.elm b/src/map-editor/src/View/Map/Character.elm new file mode 100644 index 0000000..fa1bdc1 --- /dev/null +++ b/src/map-editor/src/View/Map/Character.elm @@ -0,0 +1,218 @@ +module View.Battlemap.Character exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Html +import Html.Attributes +import Html.Events + +-- Battlemap ------------------------------------------------------------------ +import Constants.UI + +import Util.Html + +import Struct.Character +import Struct.CharacterTurn +import Struct.Event +import Struct.Model +import Struct.TurnResult +import Struct.TurnResultAnimator +import Struct.UI + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_animation_class : ( + Struct.Model.Type -> + Struct.Character.Type -> + (Html.Attribute Struct.Event.Type) + ) +get_animation_class model char = + case model.animator of + Nothing -> (Html.Attributes.class "") + (Just animator) -> + case (Struct.TurnResultAnimator.get_current_animation animator) of + (Struct.TurnResultAnimator.Focus char_index) -> + if ((Struct.Character.get_index char) /= char_index) + then + (Html.Attributes.class "") + else + (Html.Attributes.class "battlemap-character-selected") + + (Struct.TurnResultAnimator.TurnResult current_action) -> + if + ( + (Struct.TurnResult.get_actor_index current_action) + /= + (Struct.Character.get_index char) + ) + then + (Html.Attributes.class "") + else + case current_action of + (Struct.TurnResult.Moved _) -> + (Html.Attributes.class + "battlemap-animated-character-icon" + ) + + _ -> (Html.Attributes.class "") + _ -> (Html.Attributes.class "") + +get_activation_level_class : ( + Struct.Character.Type -> + (Html.Attribute Struct.Event.Type) + ) +get_activation_level_class char = + if (Struct.Character.is_enabled char) + then + (Html.Attributes.class "battlemap-character-icon-enabled") + else + (Html.Attributes.class "battlemap-character-icon-disabled") + +get_alliance_class : ( + Struct.Model.Type -> + Struct.Character.Type -> + (Html.Attribute Struct.Event.Type) + ) +get_alliance_class model char = + if ((Struct.Character.get_player_ix char) == model.player_ix) + then + (Html.Attributes.class "battlemap-character-ally") + else + (Html.Attributes.class "battlemap-character-enemy") + +get_position_style : ( + Struct.Character.Type -> + (Html.Attribute Struct.Event.Type) + ) +get_position_style char = + let char_loc = (Struct.Character.get_location char) in + (Html.Attributes.style + [ + ("top", ((toString (char_loc.y * Constants.UI.tile_size)) ++ "px")), + ("left", ((toString (char_loc.x * Constants.UI.tile_size)) ++ "px")) + ] + ) + +get_focus_class : ( + Struct.Model.Type -> + Struct.Character.Type -> + (Html.Attribute Struct.Event.Type) + ) +get_focus_class model char = + if + ( + (Struct.UI.get_previous_action model.ui) + == + (Just (Struct.UI.SelectedCharacter (Struct.Character.get_index char))) + ) + then + (Html.Attributes.class "battlemap-character-selected") + else + if + ( + (Struct.CharacterTurn.try_getting_target model.char_turn) + == + (Just (Struct.Character.get_index char)) + ) + then + (Html.Attributes.class "battlemap-character-targeted") + else + (Html.Attributes.class "") + +get_body_html : Struct.Character.Type -> (Html.Html Struct.Event.Type) +get_body_html char = + (Html.div + [ + (Html.Attributes.class "battlemap-character-icon-body"), + (Html.Attributes.class + ( + "asset-character-team-body-" + ++ (toString (Struct.Character.get_player_ix char)) + ) + ) + ] + [ + ] + ) + +get_head_html : Struct.Character.Type -> (Html.Html Struct.Event.Type) +get_head_html char = + (Html.div + [ + (Html.Attributes.class "battlemap-character-icon-head"), + (Html.Attributes.class + ("asset-character-icon-" ++ (Struct.Character.get_icon_id char)) + ) + ] + [ + ] + ) + +get_banner_html : Struct.Character.Type -> (Html.Html Struct.Event.Type) +get_banner_html char = + case (Struct.Character.get_rank char) of + Struct.Character.Commander -> + (Html.div + [ + (Html.Attributes.class "battlemap-character-icon-banner"), + (Html.Attributes.class "asset-character-icon-commander-banner") + ] + [ + ] + ) + + Struct.Character.Target -> + (Html.div + [ + (Html.Attributes.class "battlemap-character-icon-banner"), + (Html.Attributes.class "asset-character-icon-target-banner") + ] + [ + ] + ) + + _ -> (Util.Html.nothing) + +get_actual_html : ( + Struct.Model.Type -> + Struct.Character.Type -> + (Html.Html Struct.Event.Type) + ) +get_actual_html model char = + (Html.div + [ + (Html.Attributes.class "battlemap-tiled"), + (Html.Attributes.class "battlemap-character-icon"), + (get_animation_class model char), + (get_activation_level_class char), + (get_alliance_class model char), + (get_position_style char), + (get_focus_class model char), + (Html.Attributes.class "clickable"), + (Html.Events.onClick + (Struct.Event.CharacterSelected + (Struct.Character.get_index char) + ) + ) + ] + [ + (get_body_html char), + (get_head_html char), + (get_banner_html char) + ] + ) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : ( + Struct.Model.Type -> + Struct.Character.Type -> + (Html.Html Struct.Event.Type) + ) +get_html model char = + if (Struct.Character.is_alive char) + then + (get_actual_html model char) + else + (Util.Html.nothing) diff --git a/src/map-editor/src/View/Map/Navigator.elm b/src/map-editor/src/View/Map/Navigator.elm new file mode 100644 index 0000000..a03e7d0 --- /dev/null +++ b/src/map-editor/src/View/Map/Navigator.elm @@ -0,0 +1,245 @@ +module View.Battlemap.Navigator exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Html +import Html.Attributes +import Html.Events + +import List + +-- Battlemap ------------------------------------------------------------------- +import Constants.UI + +import Struct.Direction +import Struct.Event +import Struct.Location +import Struct.Marker +import Struct.Navigator + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +marker_get_html : ( + Bool -> + (Struct.Location.Ref, Struct.Marker.Type) -> + (Html.Html Struct.Event.Type) + ) +marker_get_html is_interactive (loc_ref, marker) = + (Html.div + ( + [ + (Html.Attributes.class "battlemap-marker-icon"), + (Html.Attributes.class "battlemap-tiled"), + (Html.Attributes.class + ( + "battlemap-" + ++ + ( + case marker of + Struct.Marker.CanGoToCanDefend -> "can-go-to-can-defend" + Struct.Marker.CanGoToCantDefend -> + "can-go-to-cant-defend" + + Struct.Marker.CanAttackCanDefend -> + "can-attack-can-defend" + + Struct.Marker.CanAttackCantDefend -> + "can-attack-cant-defend" + ) + ++ + "-marker" + ) + ), + (Html.Attributes.style + ( + let + loc = (Struct.Location.from_ref loc_ref) + in + [ + ( + "top", + ((toString (loc.y * Constants.UI.tile_size)) ++ "px") + ), + ( + "left", + ((toString (loc.x * Constants.UI.tile_size)) ++ "px") + ) + ] + ) + ) + ] + ++ + ( + if (is_interactive) + then + if + ( + (marker == Struct.Marker.CanGoToCanDefend) + || (marker == Struct.Marker.CanGoToCantDefend) + ) + then + [ + (Html.Attributes.class "battlemap-navigator-interactive"), + (Html.Attributes.class "clickable"), + (Html.Events.onClick + (Struct.Event.CharacterOrTileSelected loc_ref) + ) + ] + else + [ + (Html.Attributes.class "battlemap-navigator-interactive") + ] + else + [ + (Html.Attributes.class "battlemap-navigator-non-interactive"), + (Html.Events.onClick + (Struct.Event.CharacterOrTileSelected loc_ref) + ) + ] + ) + ) + [ + ] + ) + +path_node_get_html : ( + Bool -> + Struct.Direction.Type -> + ( + Struct.Location.Type, + Struct.Direction.Type, + (List (Html.Html Struct.Event.Type)) + ) -> + ( + Struct.Location.Type, + Struct.Direction.Type, + (List (Html.Html Struct.Event.Type)) + ) + ) +path_node_get_html is_below_markers next_dir (curr_loc, curr_dir, curr_nodes) = + ( + (Struct.Location.neighbor next_dir curr_loc), + next_dir, + ( + (Html.div + [ + (Html.Attributes.class "battlemap-path-icon"), + (Html.Attributes.class + ( + if (is_below_markers) + then + "battlemap-path-icon-below-markers" + else + "battlemap-path-icon-above-markers" + ) + ), + (Html.Attributes.class "battlemap-tiled"), + (Html.Attributes.class + ( + "battlemap-path-icon-" + ++ + (Struct.Direction.to_string curr_dir) + ++ + (Struct.Direction.to_string next_dir) + ) + ), + (Html.Events.onClick + (Struct.Event.CharacterOrTileSelected + (Struct.Location.get_ref curr_loc) + ) + ), + (Html.Attributes.style + [ + ( + "top", + ( + (toString (curr_loc.y * Constants.UI.tile_size)) + ++ + "px" + ) + ), + ( + "left", + ( + (toString (curr_loc.x * Constants.UI.tile_size)) + ++ + "px" + ) + ) + ] + ) + ] + [ + ] + ) + :: + curr_nodes + ) + ) + +mark_the_spot : ( + Struct.Location.Type -> + Struct.Direction.Type -> + (Html.Html Struct.Event.Type) + ) +mark_the_spot loc origin_dir = + (Html.div + [ + (Html.Attributes.class "battlemap-path-icon"), + (Html.Attributes.class "battlemap-path-icon-above-markers"), + (Html.Attributes.class "battlemap-tiled"), + (Html.Attributes.class + ( + "battlemap-path-icon-mark" + ++ + (Struct.Direction.to_string origin_dir) + ) + ), + (Html.Events.onClick + (Struct.Event.CharacterOrTileSelected (Struct.Location.get_ref loc)) + ), + (Html.Attributes.style + [ + ( + "top", + ((toString (loc.y * Constants.UI.tile_size)) ++ "px") + ), + ( + "left", + ((toString (loc.x * Constants.UI.tile_size)) ++ "px") + ) + ] + ) + ] + [ + ] + ) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : ( + Struct.Navigator.Summary -> + Bool -> + (List (Html.Html Struct.Event.Type)) + ) +get_html nav_summary is_interactive = + if (is_interactive) + then + ( + (List.map (marker_get_html True) nav_summary.markers) + ++ + ( + let + (final_loc, final_dir, path_node_htmls) = + (List.foldr + (path_node_get_html nav_summary.locked_path) + (nav_summary.starting_location, Struct.Direction.None, []) + nav_summary.path + ) + in + ((mark_the_spot final_loc final_dir) :: path_node_htmls) + ) + ) + else + (List.map (marker_get_html False) nav_summary.markers) diff --git a/src/map-editor/src/View/Map/Tile.elm b/src/map-editor/src/View/Map/Tile.elm new file mode 100644 index 0000000..a049acf --- /dev/null +++ b/src/map-editor/src/View/Map/Tile.elm @@ -0,0 +1,69 @@ +module View.Battlemap.Tile exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Html +import Html.Attributes +import Html.Events + +-- Battlemap ------------------------------------------------------------------- +import Constants.UI +import Constants.IO + +import Struct.Event +import Struct.Location +import Struct.Tile + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : ( + Struct.Tile.Instance -> + (Html.Html Struct.Event.Type) + ) +get_html tile = + let + tile_loc = (Struct.Tile.get_location tile) + in + (Html.div + [ + (Html.Attributes.class "battlemap-tile-icon"), + (Html.Attributes.class "battlemap-tiled"), + (Html.Attributes.class + ( + "battlemap-tile-variant-" + ++ (toString (Struct.Tile.get_variant_id tile)) + ) + ), + (Html.Attributes.class "clickable"), + (Html.Events.onClick + (Struct.Event.TileSelected (Struct.Location.get_ref tile_loc)) + ), + (Html.Attributes.style + [ + ( + "top", + ((toString (tile_loc.y * Constants.UI.tile_size)) ++ "px") + ), + ( + "left", + ((toString (tile_loc.x * Constants.UI.tile_size)) ++ "px") + ), + ( + "background-image", + ( + "url(" + ++ Constants.IO.tile_assets_url + ++ (Struct.Tile.get_icon_id tile) + ++".svg)" + ) + ) + ] + ) + ] + [ + ] + ) diff --git a/src/map-editor/src/View/MessageBoard.elm b/src/map-editor/src/View/MessageBoard.elm new file mode 100644 index 0000000..5de6e8d --- /dev/null +++ b/src/map-editor/src/View/MessageBoard.elm @@ -0,0 +1,30 @@ +module View.MessageBoard exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Html + +-- Struct.Battlemap ------------------------------------------------------------------- +import Struct.Event +import Struct.Model + +import View.MessageBoard.Animator +import View.MessageBoard.Error +import View.MessageBoard.Help + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : Struct.Model.Type -> (Html.Html Struct.Event.Type) +get_html model = + case (model.error) of + (Just error) -> (View.MessageBoard.Error.get_html model error) + Nothing -> + case model.animator of + (Just animator) -> + (View.MessageBoard.Animator.get_html model animator) + + Nothing -> (View.MessageBoard.Help.get_html model) diff --git a/src/map-editor/src/View/MessageBoard/Animator.elm b/src/map-editor/src/View/MessageBoard/Animator.elm new file mode 100644 index 0000000..5c8938b --- /dev/null +++ b/src/map-editor/src/View/MessageBoard/Animator.elm @@ -0,0 +1,57 @@ +module View.MessageBoard.Animator exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Html + +-- Battlemap ------------------------------------------------------------------- +import Struct.Event +import Struct.Model +import Struct.TurnResult +import Struct.TurnResultAnimator + +import Util.Html + +import View.MessageBoard.Animator.Attack + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_turn_result_html : ( + Struct.Model.Type -> + Struct.TurnResult.Type -> + (Html.Html Struct.Event.Type) + ) +get_turn_result_html model turn_result = + case turn_result of + (Struct.TurnResult.Attacked attack) -> + (View.MessageBoard.Animator.Attack.get_html + model + (Struct.TurnResult.get_actor_index turn_result) + (Struct.TurnResult.get_attack_defender_index attack) + (Struct.TurnResult.maybe_get_attack_next_step attack) + ) + + _ -> (Util.Html.nothing) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : ( + Struct.Model.Type -> + Struct.TurnResultAnimator.Type -> + (Html.Html Struct.Event.Type) + ) +get_html model animator = + case (Struct.TurnResultAnimator.get_current_animation animator) of + (Struct.TurnResultAnimator.TurnResult turn_result) -> + (get_turn_result_html model turn_result) + + (Struct.TurnResultAnimator.AttackSetup (attacker_id, defender_id)) -> + (View.MessageBoard.Animator.Attack.get_html + model + attacker_id + defender_id + Nothing + ) + + _ -> (Util.Html.nothing) diff --git a/src/map-editor/src/View/MessageBoard/Animator/Attack.elm b/src/map-editor/src/View/MessageBoard/Animator/Attack.elm new file mode 100644 index 0000000..211ada4 --- /dev/null +++ b/src/map-editor/src/View/MessageBoard/Animator/Attack.elm @@ -0,0 +1,297 @@ +module View.MessageBoard.Animator.Attack exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Array + +import Html +import Html.Attributes + +-- Battlemap ------------------------------------------------------------------- +import Struct.Attack +import Struct.Character +import Struct.Event +import Struct.Model + +import View.Controlled.CharacterCard +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_effect_text : Struct.Attack.Type -> String +get_effect_text attack = + ( + ( + case attack.precision of + Struct.Attack.Hit -> " hit for " + Struct.Attack.Graze -> " grazed for " + Struct.Attack.Miss -> " missed." + ) + ++ + ( + if (attack.precision == Struct.Attack.Miss) + then + "" + else + ( + ((toString attack.damage) ++ " damage") + ++ + ( + if (attack.critical) + then " (Critical Hit)." + else "." + ) + ) + ) + ) + +get_empty_attack_html : (Html.Html Struct.Event.Type) +get_empty_attack_html = + (Html.div + [ + (Html.Attributes.class "battlemap-message-attack-text") + ] + [] + ) + +get_attack_html : ( + Struct.Character.Type -> + Struct.Character.Type -> + Struct.Attack.Type -> + (Html.Html Struct.Event.Type) + ) +get_attack_html attacker defender attack = + let + attacker_name = (Struct.Character.get_name attacker) + defender_name = (Struct.Character.get_name defender) + in + (Html.div + [ + (Html.Attributes.class "battlemap-message-attack-text") + ] + [ + (Html.text + ( + case (attack.order, attack.parried) of + (Struct.Attack.Counter, True) -> + ( + defender_name + ++ " attempted to strike back, but " + ++ attacker_name + ++ " parried, and " + ++ (get_effect_text attack) + ) + + (Struct.Attack.Counter, _) -> + ( + defender_name + ++ " striked back, and " + ++ (get_effect_text attack) + ) + + (_, True) -> + ( + attacker_name + ++ " attempted a hit, but " + ++ defender_name + ++ " parried, and " + ++ (get_effect_text attack) + ) + + (_, _) -> + (attacker_name ++ " " ++ (get_effect_text attack)) + ) + ) + ] + ) + +get_attack_animation_class : ( + Struct.Attack.Type -> + Struct.Character.Type -> + String + ) +get_attack_animation_class attack char = + if (attack.critical) + then + "battlemap-animated-portrait-attack-critical" + else + "battlemap-animated-portrait-attacks" + +get_defense_animation_class : ( + Struct.Attack.Type -> + Struct.Character.Type -> + String + ) +get_defense_animation_class attack char = + if (attack.damage == 0) + then + if (attack.precision == Struct.Attack.Miss) + then + "battlemap-animated-portrait-dodges" + else + "battlemap-animated-portrait-undamaged" + else if ((Struct.Character.get_current_health char) > 0) + then + if (attack.precision == Struct.Attack.Graze) + then + "battlemap-animated-portrait-grazed-damage" + else + "battlemap-animated-portrait-damaged" + else + if (attack.precision == Struct.Attack.Graze) + then + "battlemap-animated-portrait-grazed-death" + else + "battlemap-animated-portrait-dies" + +get_attacker_card : ( + (Maybe Struct.Attack.Type) -> + Struct.Character.Type -> + (Html.Html Struct.Event.Type) + ) +get_attacker_card maybe_attack char = + (Html.div + (case maybe_attack of + Nothing -> + if ((Struct.Character.get_current_health char) > 0) + then + [ + (Html.Attributes.class "battlemap-animated-portrait") + ] + else + [ + (Html.Attributes.class "battlemap-animated-portrait-absent"), + (Html.Attributes.class "battlemap-animated-portrait") + ] + + (Just attack) -> + [ + (Html.Attributes.class + (case (attack.order, attack.parried) of + (Struct.Attack.Counter, True) -> + (get_attack_animation_class attack char) + + (Struct.Attack.Counter, _) -> + (get_defense_animation_class attack char) + + (_, True) -> + (get_defense_animation_class attack char) + + (_, _) -> + (get_attack_animation_class attack char) + ) + ), + (Html.Attributes.class "battlemap-animated-portrait") + ] + ) + [ + (View.Controlled.CharacterCard.get_minimal_html + (Struct.Character.get_player_ix char) + char + ) + ] + ) + +get_defender_card : ( + (Maybe Struct.Attack.Type) -> + Struct.Character.Type -> + (Html.Html Struct.Event.Type) + ) +get_defender_card maybe_attack char = + (Html.div + (case maybe_attack of + Nothing -> + if ((Struct.Character.get_current_health char) > 0) + then + [ + (Html.Attributes.class "battlemap-animated-portrait") + ] + else + [ + (Html.Attributes.class "battlemap-animated-portrait-absent"), + (Html.Attributes.class "battlemap-animated-portrait") + ] + + (Just attack) -> + [ + (Html.Attributes.class + (case (attack.order, attack.parried) of + (Struct.Attack.Counter, True) -> + (get_defense_animation_class attack char) + + (Struct.Attack.Counter, _) -> + (get_attack_animation_class attack char) + + (_, True) -> + (get_attack_animation_class attack char) + + (_, _) -> + (get_defense_animation_class attack char) + ) + ), + (Html.Attributes.class "battlemap-animated-portrait") + ] + ) + [ + (View.Controlled.CharacterCard.get_minimal_html -1 char) + ] + ) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_placeholder_html : ( + (Array.Array Struct.Character.Type) -> + Int -> + Int -> + (Maybe Struct.Attack.Type) -> + (Html.Html Struct.Event.Type) + ) +get_placeholder_html characters attacker_ix defender_ix maybe_attack = + case + ( + (Array.get attacker_ix characters), + (Array.get defender_ix characters) + ) + of + ((Just atkchar), (Just defchar)) -> + (Html.div + [ + (Html.Attributes.class "battlemap-message-board"), + (Html.Attributes.class "battlemap-message-attack") + ] + ( + [ + (get_attacker_card maybe_attack atkchar), + ( + case maybe_attack of + (Just attack) -> + (get_attack_html atkchar defchar attack) + + Nothing -> + (get_empty_attack_html) + ), + (get_defender_card maybe_attack defchar) + ] + ) + ) + + _ -> + (Html.div + [ + ] + [ + (Html.text "Error: Attack with unknown characters") + ] + ) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : ( + Struct.Model.Type -> + Int -> + Int -> + (Maybe Struct.Attack.Type) -> + (Html.Html Struct.Event.Type) + ) +get_html model attacker_ix defender_ix maybe_attack = + (get_placeholder_html model.characters attacker_ix defender_ix maybe_attack) diff --git a/src/map-editor/src/View/MessageBoard/Error.elm b/src/map-editor/src/View/MessageBoard/Error.elm new file mode 100644 index 0000000..642634a --- /dev/null +++ b/src/map-editor/src/View/MessageBoard/Error.elm @@ -0,0 +1,33 @@ +module View.MessageBoard.Error exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Html +import Html.Attributes + +-- Battlemap ------------------------------------------------------------------- +import Struct.Error +import Struct.Event +import Struct.Model + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : ( + Struct.Model.Type -> + Struct.Error.Type -> + (Html.Html Struct.Event.Type) + ) +get_html model error = + (Html.div + [ + (Html.Attributes.class "battlemap-message-board"), + (Html.Attributes.class "battlemap-error") + ] + [ + (Html.text (Struct.Error.to_string error)) + ] + ) diff --git a/src/map-editor/src/View/MessageBoard/Help.elm b/src/map-editor/src/View/MessageBoard/Help.elm new file mode 100644 index 0000000..15a33a5 --- /dev/null +++ b/src/map-editor/src/View/MessageBoard/Help.elm @@ -0,0 +1,37 @@ +module View.MessageBoard.Help exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Html +import Html.Attributes + +-- Battlemap ------------------------------------------------------------------- +import Struct.Event +import Struct.HelpRequest +import Struct.Model + +import View.MessageBoard.Help.Guide +import View.MessageBoard.Help.Rank + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : Struct.Model.Type -> (Html.Html Struct.Event.Type) +get_html model = + (Html.div + [ + (Html.Attributes.class "battlemap-message-board"), + (Html.Attributes.class "battlemap-message-board-help") + ] + ( + case model.help_request of + Struct.HelpRequest.None -> + (View.MessageBoard.Help.Guide.get_html_contents model) + + (Struct.HelpRequest.HelpOnRank rank) -> + (View.MessageBoard.Help.Rank.get_html_contents rank) + ) + ) diff --git a/src/map-editor/src/View/MessageBoard/Help/Guide.elm b/src/map-editor/src/View/MessageBoard/Help/Guide.elm new file mode 100644 index 0000000..a10b96e --- /dev/null +++ b/src/map-editor/src/View/MessageBoard/Help/Guide.elm @@ -0,0 +1,100 @@ +module View.MessageBoard.Help.Guide exposing (get_html_contents) + +-- Elm ------------------------------------------------------------------------- +import Html +import Html.Attributes + +-- Battlemap ------------------------------------------------------------------- +import Struct.CharacterTurn +import Struct.Event +import Struct.Model + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_header_html : (String -> (Html.Html Struct.Event.Type)) +get_header_html title = + (Html.h1 + [] + [ + (Html.div + [(Html.Attributes.class "battlemap-help-guide-icon")] + [] + ), + (Html.text title) + ] + ) + +get_selected_character_html_contents : (List (Html.Html Struct.Event.Type)) +get_selected_character_html_contents = + [ + (get_header_html "Controlling a Character"), + (Html.text + ( + "Click on a target tile to select a path or use the manual" + ++ " controls (on the left panel) to make your own. Click on the" + ++ " destination tile again to confirm (this can be reverted)." + ) + ) + ] + +get_moved_character_html_contents : (List (Html.Html Struct.Event.Type)) +get_moved_character_html_contents = + [ + (get_header_html "Selecting a Target"), + (Html.text + ( + "You can now choose a target in range. Dashed tiles indicate" + ++ " where your character will not be able to defend themselves" + ++ " against counter attacks." + ) + ) + ] + +get_chose_target_html_contents : (List (Html.Html Struct.Event.Type)) +get_chose_target_html_contents = + [ + (get_header_html "Finalizing the Character's Turn"), + (Html.text + ( + "If you are satisfied with your choices, you can end this" + ++ " character's turn and see the results unfold. Otherwise, click" + ++ " on the abort button to undo it all." + ) + ) + ] + +get_default_html_contents : (List (Html.Html Struct.Event.Type)) +get_default_html_contents = + [ + (get_header_html "Selecting a Character"), + (Html.text + ( + "Click once on a character to focus them. This will show you" + ++ " their stats, equipment, and other infos. If they are in" + ++ " your team and active (the pulsating characters)," + ++ " clicking on them again will let you take control." + ) + ) + ] + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html_contents : ( + Struct.Model.Type -> + (List (Html.Html Struct.Event.Type)) + ) +get_html_contents model = + case (Struct.CharacterTurn.get_state model.char_turn) of + Struct.CharacterTurn.SelectedCharacter -> + (get_selected_character_html_contents) + + Struct.CharacterTurn.MovedCharacter -> + (get_moved_character_html_contents) + + Struct.CharacterTurn.ChoseTarget -> + (get_chose_target_html_contents) + + _ -> + (get_default_html_contents) diff --git a/src/map-editor/src/View/MessageBoard/Help/Rank.elm b/src/map-editor/src/View/MessageBoard/Help/Rank.elm new file mode 100644 index 0000000..95477d3 --- /dev/null +++ b/src/map-editor/src/View/MessageBoard/Help/Rank.elm @@ -0,0 +1,97 @@ +module View.MessageBoard.Help.Rank exposing (get_html_contents) + +-- Elm ------------------------------------------------------------------------- +import Html +import Html.Attributes + +-- Battlemap ------------------------------------------------------------------- +import Struct.Character +import Struct.Event + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_guide_icon_html : (Html.Html Struct.Event.Type) +get_guide_icon_html = + (Html.div + [(Html.Attributes.class "battlemap-help-guide-icon")] + [] + ) + +get_header_with_icon_html : String -> String -> (Html.Html Struct.Event.Type) +get_header_with_icon_html title rank_name = + (Html.h1 + [] + [ + (get_guide_icon_html), + (Html.text (title ++ " - ")), + (Html.div + [ + (Html.Attributes.class + "battlemap-message-board-help-figure" + ), + (Html.Attributes.class + ("battlemap-character-card-" ++ rank_name ++ "-status") + ) + ] + [] + ) + ] + ) + +get_target_help_message : (List (Html.Html Struct.Event.Type)) +get_target_help_message = + [ + (get_header_with_icon_html "Protected Character" "target"), + (Html.text + ( + "Players that lose all of their Protected Characters are" + ++ " eliminated." + ) + ) + ] + +get_commander_help_message : (List (Html.Html Struct.Event.Type)) +get_commander_help_message = + [ + (get_header_with_icon_html "Critical Character" "commander"), + (Html.text + ( + "Players that lose any of their Critical Characters are" + ++ " eliminated." + ) + ) + ] + +get_optional_help_message : (List (Html.Html Struct.Event.Type)) +get_optional_help_message = + [ + (Html.h1 + [] + [ + (get_guide_icon_html), + (Html.text "Reinforcement Character") + ] + ), + (Html.text + ( + "Unless it is their very last character, losing a" + ++ " Reinforcement characters never causes a player to be" + ++ " eliminated." + ) + ) + ] + + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html_contents : ( + Struct.Character.Rank -> + (List (Html.Html Struct.Event.Type)) + ) +get_html_contents rank = + case rank of + Struct.Character.Target -> (get_target_help_message) + Struct.Character.Commander -> (get_commander_help_message) + Struct.Character.Optional -> (get_optional_help_message) diff --git a/src/map-editor/src/View/SubMenu.elm b/src/map-editor/src/View/SubMenu.elm new file mode 100644 index 0000000..8537452 --- /dev/null +++ b/src/map-editor/src/View/SubMenu.elm @@ -0,0 +1,85 @@ +module View.SubMenu exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Array + +import Html +import Html.Attributes +import Html.Lazy + +-- Battlemap ------------------------------------------------------------------- +import Struct.CharacterTurn +import Struct.Event +import Struct.Model +import Struct.UI + +import Util.Html + +import View.Controlled.CharacterCard + +import View.SubMenu.Characters +import View.SubMenu.Settings +import View.SubMenu.Status +import View.SubMenu.Timeline + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_inner_html : ( + Struct.Model.Type -> + Struct.UI.Tab -> + (Html.Html Struct.Event.Type) + ) +get_inner_html model tab = + case tab of + Struct.UI.StatusTab -> + (View.SubMenu.Status.get_html model) + + Struct.UI.CharactersTab -> + (Html.Lazy.lazy2 + (View.SubMenu.Characters.get_html) + model.characters + model.player_ix + ) + + Struct.UI.SettingsTab -> + (View.SubMenu.Settings.get_html model) + + Struct.UI.TimelineTab -> + (View.SubMenu.Timeline.get_html model) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : Struct.Model.Type -> (Html.Html Struct.Event.Type) +get_html model = + case (Struct.UI.try_getting_displayed_tab model.ui) of + (Just tab) -> + (Html.div + [(Html.Attributes.class "battlemap-sub-menu")] + [(get_inner_html model tab)] + ) + + Nothing -> + case (Struct.CharacterTurn.try_getting_target model.char_turn) of + (Just char_ref) -> + case (Array.get char_ref model.characters) of + (Just char) -> + (Html.div + [(Html.Attributes.class "battlemap-sub-menu")] + [ + (Html.text "Targeting:"), + (Html.Lazy.lazy3 + (View.Controlled.CharacterCard.get_summary_html) + model.char_turn + model.player_ix + char + ) + ] + ) + + Nothing -> + (Util.Html.nothing) + + Nothing -> + (Util.Html.nothing) diff --git a/src/map-editor/src/View/SubMenu/Characters.elm b/src/map-editor/src/View/SubMenu/Characters.elm new file mode 100644 index 0000000..be5bac4 --- /dev/null +++ b/src/map-editor/src/View/SubMenu/Characters.elm @@ -0,0 +1,69 @@ +module View.SubMenu.Characters exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Array + +import Html +import Html.Attributes +import Html.Events + +-- Battlemap ------------------------------------------------------------------- +import Struct.Character +import Struct.Event + +import View.Controlled.CharacterCard + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_character_element_html : ( + Int -> + Struct.Character.Type -> + (Html.Html Struct.Event.Type) + ) +get_character_element_html player_ix char = + (Html.div + [ + (Html.Attributes.class "battlemap-characters-element"), + ( + if (Struct.Character.is_alive char) + then + (Html.Attributes.class "clickable") + else + (Html.Attributes.class "") + ), + (Html.Events.onClick + (Struct.Event.LookingForCharacter (Struct.Character.get_index char)) + ), + ( + if (Struct.Character.is_enabled char) + then + (Html.Attributes.class "battlemap-characters-element-active") + else + (Html.Attributes.class "battlemap-characters-element-inactive") + ) + ] + [ + (View.Controlled.CharacterCard.get_minimal_html player_ix char) + ] + ) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : ( + (Array.Array Struct.Character.Type) -> + Int -> + (Html.Html Struct.Event.Type) + ) +get_html characters player_ix = + (Html.div + [ + (Html.Attributes.class "battlemap-tabmenu-content"), + (Html.Attributes.class "battlemap-tabmenu-characters-tab") + ] + (List.map + (get_character_element_html player_ix) + (Array.toList characters) + ) + ) diff --git a/src/map-editor/src/View/SubMenu/Settings.elm b/src/map-editor/src/View/SubMenu/Settings.elm new file mode 100644 index 0000000..22aa99a --- /dev/null +++ b/src/map-editor/src/View/SubMenu/Settings.elm @@ -0,0 +1,59 @@ +module View.SubMenu.Settings exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Html +import Html.Attributes +import Html.Events + +-- Battlemap ------------------------------------------------------------------- +import Struct.Event +import Struct.Model + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +scale_button : Float -> String -> (Html.Html Struct.Event.Type) +scale_button mod label = + (Html.button + [ + (Html.Events.onClick + (Struct.Event.ScaleChangeRequested mod) + ) + ] + [ (Html.text label) ] + ) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : Struct.Model.Type -> (Html.Html Struct.Event.Type) +get_html model = + (Html.div + [ + (Html.Attributes.class "battlemap-tabmenu-content"), + (Html.Attributes.class "battlemap-tabmenu-settings-tab") + ] + [ + (scale_button (0.75) "Zoom -"), + (scale_button 0 "Zoom Reset"), + (scale_button (1.15) "Zoom +"), + (Html.button + [ + (Html.Events.onClick Struct.Event.DebugTeamSwitchRequest) + ] + [ (Html.text "[DEBUG] Switch team") ] + ), + (Html.button + [ + (Html.Events.onClick Struct.Event.DebugLoadBattlemapRequest) + ] + [ (Html.text "[DEBUG] Load battlemap") ] + ), + (Html.button + [ + (Html.Events.onClick Struct.Event.DebugTestAnimation) + ] + [ (Html.text "[DEBUG] Test animations") ] + ) + ] + ) diff --git a/src/map-editor/src/View/SubMenu/Status.elm b/src/map-editor/src/View/SubMenu/Status.elm new file mode 100644 index 0000000..f67c85e --- /dev/null +++ b/src/map-editor/src/View/SubMenu/Status.elm @@ -0,0 +1,55 @@ +module View.SubMenu.Status exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Array + +import Html +import Html.Attributes +import Html.Lazy + +-- Struct.Battlemap ------------------------------------------------------------------- +import Struct.Event +import Struct.Location +import Struct.Model +import Struct.UI + +import View.SubMenu.Status.CharacterInfo +import View.SubMenu.Status.TileInfo +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : Struct.Model.Type -> (Html.Html Struct.Event.Type) +get_html model = + (Html.div + [ + (Html.Attributes.class "battlemap-footer-tabmenu-content"), + (Html.Attributes.class "battlemap-footer-tabmenu-content-status") + ] + [ + (case (Struct.UI.get_previous_action model.ui) of + (Just (Struct.UI.SelectedLocation loc)) -> + (View.SubMenu.Status.TileInfo.get_html + model + (Struct.Location.from_ref loc) + ) + + (Just (Struct.UI.SelectedCharacter target_char)) -> + case (Array.get target_char model.characters) of + (Just char) -> + (Html.Lazy.lazy2 + (View.SubMenu.Status.CharacterInfo.get_html) + model.player_ix + char + ) + + _ -> (Html.text "Error: Unknown character selected.") + + _ -> + (Html.text "Nothing is being focused.") + ) + ] + ) diff --git a/src/map-editor/src/View/SubMenu/Status/CharacterInfo.elm b/src/map-editor/src/View/SubMenu/Status/CharacterInfo.elm new file mode 100644 index 0000000..a927158 --- /dev/null +++ b/src/map-editor/src/View/SubMenu/Status/CharacterInfo.elm @@ -0,0 +1,34 @@ +module View.SubMenu.Status.CharacterInfo exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Html +import Html.Attributes + +-- Struct.Battlemap ------------------------------------------------------------------- +import Struct.Character +import Struct.Event + +import View.Controlled.CharacterCard + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : ( + Int -> + Struct.Character.Type -> + (Html.Html Struct.Event.Type) + ) +get_html player_ix char = + (Html.div + [ + (Html.Attributes.class "battlemap-tabmenu-character-info") + ] + [ + (Html.text ("Focusing:")), + (View.Controlled.CharacterCard.get_full_html player_ix char) + ] + ) diff --git a/src/map-editor/src/View/SubMenu/Status/TileInfo.elm b/src/map-editor/src/View/SubMenu/Status/TileInfo.elm new file mode 100644 index 0000000..a009bc3 --- /dev/null +++ b/src/map-editor/src/View/SubMenu/Status/TileInfo.elm @@ -0,0 +1,142 @@ +module View.SubMenu.Status.TileInfo exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Dict + +import Html +import Html.Attributes + +-- Struct.Battlemap ------------------------------------------------------------------- +import Constants.IO +import Constants.Movement + +import Struct.Battlemap +import Struct.Event +import Struct.Location +import Struct.Model +import Struct.Tile + +import Util.Html +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_icon : (Struct.Tile.Instance -> (Html.Html Struct.Event.Type)) +get_icon tile = + (Html.div + [ + (Html.Attributes.class "battlemap-tile-card-icon"), + (Html.Attributes.class + ( + "battlemap-tile-variant-" + ++ (toString (Struct.Tile.get_variant_id tile)) + ) + ), + (Html.Attributes.style + [ + ( + "background-image", + ( + "url(" + ++ Constants.IO.tile_assets_url + ++ (Struct.Tile.get_icon_id tile) + ++".svg)" + ) + ) + ] + ) + ] + [ + ] + ) + +get_name : ( + Struct.Model.Type -> + Struct.Tile.Instance -> + (Html.Html Struct.Event.Type) + ) +get_name model tile = + case (Dict.get (Struct.Tile.get_type_id tile) model.tiles) of + Nothing -> (Util.Html.nothing) + (Just tile_type) -> + (Html.div + [ + (Html.Attributes.class "battlemap-tile-card-name") + ] + [ + (Html.text (Struct.Tile.get_name tile_type)) + ] + ) + +get_cost : (Struct.Tile.Instance -> (Html.Html Struct.Event.Type)) +get_cost tile = + let + cost = (Struct.Tile.get_instance_cost tile) + text = + if (cost > Constants.Movement.max_points) + then + "Obstructed" + else + ("Cost: " ++ (toString cost)) + in + (Html.div + [ + (Html.Attributes.class "battlemap-tile-card-cost") + ] + [ + (Html.text text) + ] + ) + +get_location : (Struct.Tile.Instance -> (Html.Html Struct.Event.Type)) +get_location tile = + let + tile_location = (Struct.Tile.get_location tile) + in + (Html.div + [ + (Html.Attributes.class "battlemap-tile-card-location") + ] + [ + (Html.text + ( + "{x: " + ++ (toString tile_location.x) + ++ "; y: " + ++ (toString tile_location.y) + ++ "}" + ) + ) + ] + ) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : ( + Struct.Model.Type -> + Struct.Location.Type -> + (Html.Html Struct.Event.Type) + ) +get_html model loc = + case (Struct.Battlemap.try_getting_tile_at loc model.battlemap) of + (Just tile) -> + (Html.div + [ + (Html.Attributes.class "battlemap-tile-card") + ] + [ + (get_name model tile), + (Html.div + [ + (Html.Attributes.class "battlemap-tile-card-top") + ] + [ + (get_icon tile), + (get_location tile), + (get_cost tile) + ] + ) + ] + ) + + Nothing -> (Html.text "Error: Unknown tile location selected.") diff --git a/src/map-editor/src/View/ToolBox.elm b/src/map-editor/src/View/ToolBox.elm new file mode 100644 index 0000000..8a36fb8 --- /dev/null +++ b/src/map-editor/src/View/ToolBox.elm @@ -0,0 +1,133 @@ +module View.Controlled exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Html +import Html.Attributes +import Html.Events + +-- Struct.Battlemap ------------------------------------------------------------------- +import Struct.CharacterTurn +import Struct.Event +import Struct.Navigator + +import Util.Html + +import View.Controlled.CharacterCard +import View.Controlled.ManualControls + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +has_a_path : Struct.CharacterTurn.Type -> Bool +has_a_path char_turn = + case (Struct.CharacterTurn.try_getting_navigator char_turn) of + (Just nav) -> ((Struct.Navigator.get_path nav) /= []) + Nothing -> False + + +attack_button : Struct.CharacterTurn.Type -> (Html.Html Struct.Event.Type) +attack_button char_turn = + (Html.button + [ (Html.Events.onClick Struct.Event.AttackWithoutMovingRequest) ] + [ + (Html.text + ( + if (has_a_path char_turn) + then ("Go & Select Target") + else ("Select Target") + ) + ) + ] + ) + +abort_button : (Html.Html Struct.Event.Type) +abort_button = + (Html.button + [ (Html.Events.onClick Struct.Event.AbortTurnRequest) ] + [ (Html.text "Abort") ] + ) + +end_turn_button : String -> (Html.Html Struct.Event.Type) +end_turn_button suffix = + (Html.button + [ + (Html.Events.onClick Struct.Event.TurnEnded), + (Html.Attributes.class "battlemap-end-turn-button") + ] + [ (Html.text ("End Turn" ++ suffix)) ] + ) + +inventory_button : (Html.Html Struct.Event.Type) +inventory_button = + (Html.button + [ (Html.Events.onClick Struct.Event.WeaponSwitchRequest) ] + [ (Html.text "Switch Weapon") ] + ) + +get_available_actions : ( + Struct.CharacterTurn.Type -> + (List (Html.Html Struct.Event.Type)) + ) +get_available_actions char_turn = + case (Struct.CharacterTurn.get_state char_turn) of + Struct.CharacterTurn.SelectedCharacter -> + [ + (attack_button char_turn), + (inventory_button), + (end_turn_button " Doing Nothing"), + (abort_button) + ] + + Struct.CharacterTurn.MovedCharacter -> + [ + (end_turn_button " Without Attacking"), + (abort_button) + ] + + Struct.CharacterTurn.ChoseTarget -> + [ + (end_turn_button " By Attacking"), + (abort_button) + ] + + _ -> + [ + ] + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : Struct.CharacterTurn.Type -> Int -> (Html.Html Struct.Event.Type) +get_html char_turn player_ix = + case + (Struct.CharacterTurn.try_getting_active_character char_turn) + of + (Just char) -> + (Html.div + [(Html.Attributes.class "battlemap-controlled")] + [ + (View.Controlled.CharacterCard.get_summary_html + char_turn + player_ix + char + ), + ( + if + ( + (Struct.CharacterTurn.get_state char_turn) + == + Struct.CharacterTurn.SelectedCharacter + ) + then + (View.Controlled.ManualControls.get_html) + else + (Util.Html.nothing) + ), + (Html.div + [(Html.Attributes.class "battlemap-controlled-actions")] + (get_available_actions char_turn) + ) + ] + ) + + Nothing -> (Util.Html.nothing) diff --git a/src/map-editor/www/index.html b/src/map-editor/www/index.html new file mode 100644 index 0000000..2dcbefb --- /dev/null +++ b/src/map-editor/www/index.html @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + diff --git a/src/map-editor/www/style.css b/src/map-editor/www/style.css new file mode 100644 index 0000000..fee293f --- /dev/null +++ b/src/map-editor/www/style.css @@ -0,0 +1,356 @@ +/******************************************************************************/ +/** LAYOUT ********************************************************************/ +/******************************************************************************/ +.fullscreen-module {} + +.map-main-menu +{ + position: absolute; + top: 0; + left: 0; + right: 0; + height: 3em; + + display: flex; + + flex-direction: row; + flex-wrap: wrap; + + border: 3px solid #502D16; + border-top: none; + border-radius: 0 0 15px 15px; + + padding: 0.5em; + + background-color: #917C6F; + + margin: 0 1em 0 1em; +} + +.map-message-board +{ + position: absolute; + bottom: 0; + left: 0; + right: 0; + + height: 10em; + + border: 3px solid #502D16; + border-radius: 15px 15px 0 0; + border-bottom: none; + + padding: 0.5em; + margin: 0 1em 0 1em; + + background-color: #917C6F; + + display: flex; + flex-flow: row; + justify-content: space-between; +} + +.map-container-centerer +{ + position: absolute; + top: 4em; + left: 16em; + right: 21em; + bottom: 11em; + + display: flex; +} + +.map-container +{ + display: inline-block; + max-height: 100%; + max-width: 100%; + /* + * 4em: main-menu + margin. + * 11em: message-board + margin. + */ + /*margin: 0 1em 0 1em; */ + overflow: scroll; + + margin: auto; + resize: both; + + border: 3px solid #502D16; + border-radius: 15px; +} + +.map-toolbox +{ + position: absolute; + left: 0; + top: 4em; + width: 15em; + /* + * 4em: main-menu + margin. + * 11em: message-board + margin. + */ + height: calc(100% - 11em - 4em); + + display: flex; + flex-flow: column; + + justify-content: space-between; + + padding: 0.5em; + + border: 3px solid #502D16; + border-radius: 0 15px 15px 0; + border-left: none; + + background-color: #917C6F; +} + +.map-sub-menu +{ + position: absolute; + right: 0; + top: 4em; + width: 20em; + /* + * 4em: main-menu + margin. + * 11em: message-board + margin. + */ + height: calc(100% - 11em - 4em); + padding: 0.5em; + overflow: auto; + + border: 3px solid #502D16; + border-radius: 15px 0 0 15px; + border-right: none; + + background-color: #917C6F; +} + +/******************************************************************************/ +/** MESSAGE BOARD *************************************************************/ +/******************************************************************************/ +.map-error +{ + background-color: #550000; +} + +.map-message-board-help +{ + display: block; +} + +.map-message-board-help h1 +{ + margin: 0; + margin-bottom: 0.3em; + font-size: 1.5em; + text-align: center; +} + +.map-message-board-help-figure +{ + width: 1.5em; + height: 1.5em; + background-size: 100%; + display: inline-block; + vertical-align: middle; +} + +.map-help-guide-icon +{ + margin-right: 0.5em; + width: 1.5em; + height: 1.5em; + background-image: url("/asset/svg/help-icon.svg"); + background-size: 100%; + display: inline-block; + vertical-align: middle; +} + +/******************************************************************************/ +/** ??? ***********************************************************************/ +/******************************************************************************/ + +/** Tile Card *****************************************************************/ +.map-tile-card +{ + display: flex; + flex-flow: column; +} + +.map-tile-card-top +{ + margin-top: 0.5em; + position: relative; +} + +.map-character-portrait +{ + box-sizing: border-box; + border-radius: 5px; + background-size: 100% 100%; + width: 100px; + height: 100px; + overflow: hidden; +} + +.map-tile-card-icon +{ + box-sizing: border-box; + border-radius: 5px; + background-size: 300% 300%; + width: 80px; + height: 80px; +} + +.map-tile-card-icon +{ + top: 0; + left: 0; + margin: 0; + box-sizing: border-box; + box-shadow: + 1px 0px 2px #333, + -1px 0px 2px #333, + 0px 1px 2px #333, + 0px -1px 2px #333; +} + +.map-character-portrait-team-0 { background-color: rgba(57, 106, 177, 0.3); } +.map-character-portrait-team-1 { background-color: rgba(204, 37, 41, 0.3); } +.map-character-portrait-team-2 { background-color: rgba(62, 150, 81, 0.3); } +.map-character-portrait-team-3 { background-color: rgba(218, 124, 48, 0.3); } +.map-character-portrait-team-4 { background-color: rgba(83, 81, 84, 0.3); } +.map-character-portrait-team-5 { background-color: rgba(107, 76, 154, 0.3); } +.map-character-portrait-team-6 { background-color: rgba(127, 167, 169, 0.3); } +.map-character-portrait-team-7 { background-color: rgba(231, 167, 169, 0.3); } + +.map-tile-card-top +{ + margin:0.3em; +} + +.map-tile-card-name, +.map-tile-card-cost, +.map-tile-card-location +{ + display:flex; + justify-content:center; + align-items:center; + border-radius: 5px; + background-color: #6C5D53; + width: 100%; +} + +.map-gauge +{ + position: relative; + border-radius: 5px; + border: 2px solid #6C5D53; + text-align: center; + height: 2em; +} + +.map-gauge-text +{ + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + z-index: 1; + + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.map-gauge-bar +{ + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + z-index: 0; + + border-radius: 5px; + z-index: 0; + transition: width 3s ease-in-out; +} + +.map-tile-card-cost +{ + position: absolute; + left: 100px; + top: 0; + margin-left: 0.5em; + width: calc(100% - 100px - 0.5em); +} + +.map-tile-card-location +{ + position: absolute; + left: 100px; + top: calc(1.5em + 1em); + margin-left: 0.5em; + width: calc(100% - 100px - 0.5em); +} + +/******************************************************************************/ +/** MAIN MENU *****************************************************************/ +/******************************************************************************/ +.map-main-menu +{ + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; +} + +.map-main-menu button +{ + flex: 1; + + text-transform: uppercase; +} + +/******************************************************************************/ +/** SUB-MENU ******************************************************************/ +/******************************************************************************/ + +/******************************************************************************/ +/** Main View Elements ********************************************************/ +/******************************************************************************/ +.map-actual +{ + display: inline-block; + transform-origin: top left; + + /*** Otherwise, it won't display correctly without 'transform: scale' ***/ + position: relative; + background-color: #917C6F; +} + +.map-tiled +{ + height: 32px; + width: 32px; + /** Fixes odd behavior of table cell being resized. **/ + /* min-width: 32px; */ + /* max-width: 32px; */ +} + +.map-tile-variant-0 {background-position: 0 0;} +.map-tile-variant-1 {background-position: 100% 0;} +.map-tile-variant-2 {background-position: 200% 0;} +.map-tile-variant-3 {background-position: 0 100%;} +.map-tile-variant-4 {background-position: 100% 100%;} +.map-tile-variant-5 {background-position: 200% 100%;} +.map-tile-variant-6 {background-position: 0 200%;} +.map-tile-variant-7 {background-position: 100% 200%;} +.map-tile-variant-8 {background-position: 200% 200%;} + +.map-tile-icon {z-index: 0; position: absolute; background-size: 300%;} -- cgit v1.2.3-70-g09d2