summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/roster-editor')
-rw-r--r--src/roster-editor/Makefile36
-rw-r--r--src/roster-editor/elm-package.json19
-rw-r--r--src/roster-editor/src/Comm/AddArmor.elm24
-rw-r--r--src/roster-editor/src/Comm/AddChar.elm28
-rw-r--r--src/roster-editor/src/Comm/AddWeapon.elm24
-rw-r--r--src/roster-editor/src/Comm/LoadRoster.elm42
-rw-r--r--src/roster-editor/src/Comm/Send.elm71
-rw-r--r--src/roster-editor/src/Constants/IO.elm.m410
-rw-r--r--src/roster-editor/src/Constants/Movement.elm10
-rw-r--r--src/roster-editor/src/Constants/UI.elm16
-rw-r--r--src/roster-editor/src/ElmModule/Init.elm28
-rw-r--r--src/roster-editor/src/ElmModule/Subscriptions.elm17
-rw-r--r--src/roster-editor/src/ElmModule/Update.elm114
-rw-r--r--src/roster-editor/src/ElmModule/View.elm40
-rw-r--r--src/roster-editor/src/Main.elm23
-rw-r--r--src/roster-editor/src/Struct/Armor.elm70
-rw-r--r--src/roster-editor/src/Struct/Attributes.elm173
-rw-r--r--src/roster-editor/src/Struct/Character.elm299
-rw-r--r--src/roster-editor/src/Struct/DamageType.elm55
-rw-r--r--src/roster-editor/src/Struct/Error.elm45
-rw-r--r--src/roster-editor/src/Struct/Event.elm30
-rw-r--r--src/roster-editor/src/Struct/HelpRequest.elm13
-rw-r--r--src/roster-editor/src/Struct/Model.elm149
-rw-r--r--src/roster-editor/src/Struct/Omnimods.elm180
-rw-r--r--src/roster-editor/src/Struct/ServerReply.elm27
-rw-r--r--src/roster-editor/src/Struct/Statistics.elm210
-rw-r--r--src/roster-editor/src/Struct/UI.elm52
-rw-r--r--src/roster-editor/src/Struct/Weapon.elm99
-rw-r--r--src/roster-editor/src/Struct/WeaponSet.elm39
-rw-r--r--src/roster-editor/src/Update/DisplayCharacterInfo.elm53
-rw-r--r--src/roster-editor/src/Update/GoToMainMenu.elm24
-rw-r--r--src/roster-editor/src/Update/HandleServerReply.elm174
-rw-r--r--src/roster-editor/src/Update/SelectCharacter.elm298
-rw-r--r--src/roster-editor/src/Update/SelectTab.elm32
-rw-r--r--src/roster-editor/src/Update/SendLoadRosterRequest.elm26
-rw-r--r--src/roster-editor/src/Update/SetRequestedHelp.elm22
-rw-r--r--src/roster-editor/src/View/Character.elm230
-rw-r--r--src/roster-editor/src/View/CharacterIcon.elm218
-rw-r--r--src/roster-editor/src/View/Controlled.elm158
-rw-r--r--src/roster-editor/src/View/Controlled/CharacterCard.elm540
-rw-r--r--src/roster-editor/src/View/Controlled/ManualControls.elm60
-rw-r--r--src/roster-editor/src/View/Controlled/Targets.elm69
-rw-r--r--src/roster-editor/src/View/CurrentTab.elm40
-rw-r--r--src/roster-editor/src/View/Gauge.elm76
-rw-r--r--src/roster-editor/src/View/MainMenu.elm46
-rw-r--r--src/roster-editor/src/View/MessageBoard.elm30
-rw-r--r--src/roster-editor/src/View/MessageBoard/Animator.elm57
-rw-r--r--src/roster-editor/src/View/MessageBoard/Animator/Attack.elm297
-rw-r--r--src/roster-editor/src/View/MessageBoard/Error.elm33
-rw-r--r--src/roster-editor/src/View/MessageBoard/Help.elm37
-rw-r--r--src/roster-editor/src/View/MessageBoard/Help/Guide.elm119
-rw-r--r--src/roster-editor/src/View/MessageBoard/Help/Rank.elm97
-rw-r--r--src/roster-editor/src/View/SubMenu.elm85
-rw-r--r--src/roster-editor/src/View/SubMenu/Characters.elm69
-rw-r--r--src/roster-editor/src/View/SubMenu/Settings.elm59
-rw-r--r--src/roster-editor/src/View/SubMenu/Status.elm55
-rw-r--r--src/roster-editor/src/View/SubMenu/Status/CharacterInfo.elm34
-rw-r--r--src/roster-editor/src/View/SubMenu/Status/TileInfo.elm181
-rw-r--r--src/roster-editor/src/View/SubMenu/Timeline.elm95
-rw-r--r--src/roster-editor/src/View/SubMenu/Timeline/Attack.elm164
-rw-r--r--src/roster-editor/src/View/SubMenu/Timeline/Movement.elm62
-rw-r--r--src/roster-editor/src/View/SubMenu/Timeline/PlayerDefeat.elm38
-rw-r--r--src/roster-editor/src/View/SubMenu/Timeline/PlayerTurnStart.elm38
-rw-r--r--src/roster-editor/src/View/SubMenu/Timeline/PlayerVictory.elm38
-rw-r--r--src/roster-editor/src/View/SubMenu/Timeline/WeaponSwitch.elm58
-rw-r--r--src/roster-editor/www/index.html32
66 files changed, 5687 insertions, 0 deletions
diff --git a/src/roster-editor/Makefile b/src/roster-editor/Makefile
new file mode 100644
index 0000000..3b58a08
--- /dev/null
+++ b/src/roster-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/roster-editor/elm-package.json b/src/roster-editor/elm-package.json
new file mode 100644
index 0000000..d62239e
--- /dev/null
+++ b/src/roster-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",
+ "../shared/elm"
+ ],
+ "exposed-modules": [],
+ "dependencies": {
+ "NoRedInk/elm-decode-pipeline": "3.0.0 <= v < 4.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/roster-editor/src/Comm/AddArmor.elm b/src/roster-editor/src/Comm/AddArmor.elm
new file mode 100644
index 0000000..480b823
--- /dev/null
+++ b/src/roster-editor/src/Comm/AddArmor.elm
@@ -0,0 +1,24 @@
+module Comm.AddArmor exposing (decode)
+
+-- Elm -------------------------------------------------------------------------
+import Json.Decode
+
+-- Map -------------------------------------------------------------------
+import Struct.Armor
+import Struct.ServerReply
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+internal_decoder : Struct.Armor.Type -> Struct.ServerReply.Type
+internal_decoder ar = (Struct.ServerReply.AddArmor ar)
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+decode : (Json.Decode.Decoder Struct.ServerReply.Type)
+decode = (Json.Decode.map (internal_decoder) (Struct.Armor.decoder))
diff --git a/src/roster-editor/src/Comm/AddChar.elm b/src/roster-editor/src/Comm/AddChar.elm
new file mode 100644
index 0000000..32227a8
--- /dev/null
+++ b/src/roster-editor/src/Comm/AddChar.elm
@@ -0,0 +1,28 @@
+module Comm.AddChar exposing (decode)
+
+-- Elm -------------------------------------------------------------------------
+import Json.Decode
+
+-- Map -------------------------------------------------------------------
+import Struct.Character
+import Struct.ServerReply
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+internal_decoder : (
+ (Struct.Character.Type, Int, Int, Int) ->
+ Struct.ServerReply.Type
+ )
+internal_decoder char_and_refs = (Struct.ServerReply.AddCharacter char_and_refs)
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+decode : (Json.Decode.Decoder Struct.ServerReply.Type)
+decode = (Json.Decode.map (internal_decoder) (Struct.Character.decoder))
diff --git a/src/roster-editor/src/Comm/AddWeapon.elm b/src/roster-editor/src/Comm/AddWeapon.elm
new file mode 100644
index 0000000..7061dea
--- /dev/null
+++ b/src/roster-editor/src/Comm/AddWeapon.elm
@@ -0,0 +1,24 @@
+module Comm.AddWeapon exposing (decode)
+
+-- Elm -------------------------------------------------------------------------
+import Json.Decode
+
+-- Map -------------------------------------------------------------------
+import Struct.Weapon
+import Struct.ServerReply
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+internal_decoder : Struct.Weapon.Type -> Struct.ServerReply.Type
+internal_decoder wp = (Struct.ServerReply.AddWeapon wp)
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+decode : (Json.Decode.Decoder Struct.ServerReply.Type)
+decode = (Json.Decode.map (internal_decoder) (Struct.Weapon.decoder))
diff --git a/src/roster-editor/src/Comm/LoadRoster.elm b/src/roster-editor/src/Comm/LoadRoster.elm
new file mode 100644
index 0000000..524605f
--- /dev/null
+++ b/src/roster-editor/src/Comm/LoadRoster.elm
@@ -0,0 +1,42 @@
+module Comm.LoadRoster exposing (try)
+
+-- Elm -------------------------------------------------------------------------
+import Json.Encode
+
+-- Roster Editor ---------------------------------------------------------------
+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)),
+ ("rid", (Json.Encode.string model.roster_id))
+ ]
+ )
+ )
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+try : Struct.Model.Type -> (Maybe (Cmd Struct.Event.Type))
+try model =
+ (Comm.Send.try_sending
+ model
+ Constants.IO.roster_loading_handler
+ try_encoding
+ )
diff --git a/src/roster-editor/src/Comm/Send.elm b/src/roster-editor/src/Comm/Send.elm
new file mode 100644
index 0000000..ec9e359
--- /dev/null
+++ b/src/roster-editor/src/Comm/Send.elm
@@ -0,0 +1,71 @@
+module Comm.Send exposing (try_sending)
+
+-- Elm -------------------------------------------------------------------------
+import Http
+
+import Json.Decode
+import Json.Encode
+
+--- Roster Editor --------------------------------------------------------------
+import Comm.AddArmor
+import Comm.AddChar
+import Comm.AddWeapon
+
+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_armor" -> (Comm.AddArmor.decode)
+ "add_char" -> (Comm.AddChar.decode)
+ "add_weapon" -> (Comm.AddWeapon.decode)
+ "disconnected" -> (Json.Decode.succeed Struct.ServerReply.Disconnected)
+ "okay" -> (Json.Decode.succeed Struct.ServerReply.Okay)
+
+ 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/roster-editor/src/Constants/IO.elm.m4 b/src/roster-editor/src/Constants/IO.elm.m4
new file mode 100644
index 0000000..c78c717
--- /dev/null
+++ b/src/roster-editor/src/Constants/IO.elm.m4
@@ -0,0 +1,10 @@
+module Constants.IO exposing (..)
+
+base_url : String
+base_url = "__CONF_SERVER_URL"
+
+roster_handler_url : String
+roster_handler_url = (base_url ++ "/handler/roster")
+
+roster_loading_handler : String
+roster_loading_handler = (map_handler_url ++ "/rst_load")
diff --git a/src/roster-editor/src/Constants/Movement.elm b/src/roster-editor/src/Constants/Movement.elm
new file mode 100644
index 0000000..a2a5c1e
--- /dev/null
+++ b/src/roster-editor/src/Constants/Movement.elm
@@ -0,0 +1,10 @@
+module Constants.Movement exposing (..)
+
+max_points : Int
+max_points = 200
+
+cost_when_occupied_tile : Int
+cost_when_occupied_tile = 201
+
+cost_when_out_of_bounds : Int
+cost_when_out_of_bounds = 255
diff --git a/src/roster-editor/src/Constants/UI.elm b/src/roster-editor/src/Constants/UI.elm
new file mode 100644
index 0000000..6a0b948
--- /dev/null
+++ b/src/roster-editor/src/Constants/UI.elm
@@ -0,0 +1,16 @@
+module Constants.UI exposing (..)
+
+tile_size : Int
+tile_size = 32
+
+local_variants_per_tile : Int
+local_variants_per_tile = 16
+
+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/roster-editor/src/ElmModule/Init.elm b/src/roster-editor/src/ElmModule/Init.elm
new file mode 100644
index 0000000..4fccd82
--- /dev/null
+++ b/src/roster-editor/src/ElmModule/Init.elm
@@ -0,0 +1,28 @@
+module ElmModule.Init exposing (init)
+
+-- Elm -------------------------------------------------------------------------
+
+-- Map -------------------------------------------------------------------
+import Comm.LoadBattle
+
+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.LoadBattle.try model) of
+ (Just cmd) -> cmd
+ Nothing -> Cmd.none
+ )
+ )
diff --git a/src/roster-editor/src/ElmModule/Subscriptions.elm b/src/roster-editor/src/ElmModule/Subscriptions.elm
new file mode 100644
index 0000000..198833a
--- /dev/null
+++ b/src/roster-editor/src/ElmModule/Subscriptions.elm
@@ -0,0 +1,17 @@
+module ElmModule.Subscriptions exposing (..)
+
+-- Elm -------------------------------------------------------------------------
+
+-- Roster Editor ---------------------------------------------------------------
+import Struct.Model
+import Struct.Event
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+subscriptions : Struct.Model.Type -> (Sub Struct.Event.Type)
+subscriptions model = Sub.none
diff --git a/src/roster-editor/src/ElmModule/Update.elm b/src/roster-editor/src/ElmModule/Update.elm
new file mode 100644
index 0000000..f9d7d38
--- /dev/null
+++ b/src/roster-editor/src/ElmModule/Update.elm
@@ -0,0 +1,114 @@
+module ElmModule.Update exposing (update)
+
+-- Elm -------------------------------------------------------------------------
+
+-- Battle ----------------------------------------------------------------------
+import Struct.Event
+import Struct.Model
+
+import Update.AbortTurn
+import Update.AttackWithoutMoving
+import Update.ChangeScale
+import Update.DisplayCharacterInfo
+import Update.EndTurn
+import Update.GoToMainMenu
+import Update.HandleAnimationEnded
+import Update.HandleServerReply
+import Update.LookForCharacter
+import Update.RequestDirection
+import Update.SelectCharacter
+import Update.SelectCharacterOrTile
+import Update.SelectTab
+import Update.SelectTile
+import Update.SendLoadBattleRequest
+import Update.SetRequestedHelp
+import Update.SwitchTeam
+import Update.SwitchWeapon
+import Update.TestAnimation
+import Update.UndoAction
+
+--------------------------------------------------------------------------------
+-- 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.AttackWithoutMovingRequest ->
+ (Update.AttackWithoutMoving.apply_to new_model)
+
+ Struct.Event.AnimationEnded ->
+ (Update.HandleAnimationEnded.apply_to model)
+
+ (Struct.Event.DirectionRequested d) ->
+ (Update.RequestDirection.apply_to new_model d)
+
+ (Struct.Event.TileSelected loc) ->
+ (Update.SelectTile.apply_to new_model loc)
+
+ (Struct.Event.CharacterOrTileSelected loc) ->
+ (Update.SelectCharacterOrTile.apply_to new_model loc)
+
+ (Struct.Event.CharacterSelected char_id) ->
+ (Update.SelectCharacter.apply_to new_model char_id)
+
+ (Struct.Event.CharacterInfoRequested char_id) ->
+ (Update.DisplayCharacterInfo.apply_to new_model char_id)
+
+ (Struct.Event.LookingForCharacter char_id) ->
+ (Update.LookForCharacter.apply_to new_model char_id)
+
+ Struct.Event.TurnEnded ->
+ (Update.EndTurn.apply_to new_model)
+
+ (Struct.Event.ScaleChangeRequested mod) ->
+ (Update.ChangeScale.apply_to new_model mod)
+
+ (Struct.Event.TabSelected tab) ->
+ (Update.SelectTab.apply_to new_model tab)
+
+ Struct.Event.DebugTeamSwitchRequest ->
+ (Update.SwitchTeam.apply_to new_model)
+
+ Struct.Event.DebugTestAnimation ->
+ (Update.TestAnimation.apply_to new_model)
+
+ (Struct.Event.DebugLoadBattleRequest) ->
+ (Update.SendLoadBattleRequest.apply_to new_model)
+
+ (Struct.Event.ServerReplied result) ->
+ (Update.HandleServerReply.apply_to model result)
+
+ Struct.Event.WeaponSwitchRequest ->
+ (Update.SwitchWeapon.apply_to new_model)
+
+ Struct.Event.AbortTurnRequest ->
+ (Update.AbortTurn.apply_to new_model)
+
+ Struct.Event.UndoActionRequest ->
+ (Update.UndoAction.apply_to new_model)
+
+ (Struct.Event.RequestedHelp help_request) ->
+ (Update.SetRequestedHelp.apply_to new_model help_request)
+
+ Struct.Event.GoToMainMenu ->
+ (Update.GoToMainMenu.apply_to new_model)
diff --git a/src/roster-editor/src/ElmModule/View.elm b/src/roster-editor/src/ElmModule/View.elm
new file mode 100644
index 0000000..3f643f5
--- /dev/null
+++ b/src/roster-editor/src/ElmModule/View.elm
@@ -0,0 +1,40 @@
+module ElmModule.View exposing (view)
+
+-- Elm -------------------------------------------------------------------------
+import Html
+import Html.Lazy
+import Html.Attributes
+
+-- Map -------------------------------------------------------------------
+import Constants.UI
+
+import Struct.Event
+import Struct.Model
+
+import View.MessageBoard
+import View.MainMenu
+import View.CharacterSelection
+import View.PortraitSelection
+import View.WeaponSelection
+import View.
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+view : Struct.Model.Type -> (Html.Html Struct.Event.Type)
+view model =
+ (Html.div
+ [
+ (Html.Attributes.class "fullscreen-module")
+ ]
+ [
+ (View.MainMenu.get_html),
+ (View.CurrentTab.get_html model),
+ (View.Controlled.get_html model),
+ (View.MessageBoard.get_html model)
+ ]
+ )
diff --git a/src/roster-editor/src/Main.elm b/src/roster-editor/src/Main.elm
new file mode 100644
index 0000000..8140041
--- /dev/null
+++ b/src/roster-editor/src/Main.elm
@@ -0,0 +1,23 @@
+-- Elm ------------------------------------------------------------------------
+import Html
+
+-- Map -------------------------------------------------------------------
+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/roster-editor/src/Struct/Armor.elm b/src/roster-editor/src/Struct/Armor.elm
new file mode 100644
index 0000000..659f2c3
--- /dev/null
+++ b/src/roster-editor/src/Struct/Armor.elm
@@ -0,0 +1,70 @@
+module Struct.Armor exposing
+ (
+ Type,
+ Ref,
+ new,
+ get_id,
+ get_name,
+ get_image_id,
+ get_omnimods,
+ decoder,
+ none
+ )
+
+-- Elm -------------------------------------------------------------------------
+import Json.Decode
+import Json.Decode.Pipeline
+
+-- Battle ----------------------------------------------------------------------
+import Struct.Omnimods
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type alias Type =
+ {
+ id : Int,
+ name : String,
+ omnimods : Struct.Omnimods.Type
+ }
+
+type alias Ref = Int
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+new : Int -> String -> Struct.Omnimods.Type -> Type
+new id name omnimods =
+ {
+ id = id,
+ name = name,
+ omnimods = omnimods
+ }
+
+get_id : Type -> Ref
+get_id ar = ar.id
+
+get_name : Type -> String
+get_name ar = ar.name
+
+get_image_id : Type -> String
+get_image_id ar = (toString ar.id)
+
+get_omnimods : Type -> Struct.Omnimods.Type
+get_omnimods ar = ar.omnimods
+
+decoder : (Json.Decode.Decoder Type)
+decoder =
+ (Json.Decode.Pipeline.decode
+ Type
+ |> (Json.Decode.Pipeline.required "id" Json.Decode.int)
+ |> (Json.Decode.Pipeline.required "nam" Json.Decode.string)
+ |> (Json.Decode.Pipeline.required "omni" Struct.Omnimods.decoder)
+ )
+
+none : Type
+none = (new 0 "None" (Struct.Omnimods.new [] [] [] []))
diff --git a/src/roster-editor/src/Struct/Attributes.elm b/src/roster-editor/src/Struct/Attributes.elm
new file mode 100644
index 0000000..ce871dd
--- /dev/null
+++ b/src/roster-editor/src/Struct/Attributes.elm
@@ -0,0 +1,173 @@
+module Struct.Attributes exposing
+ (
+ Type,
+ Category(..),
+ get_constitution,
+ get_dexterity,
+ get_intelligence,
+ get_mind,
+ get_speed,
+ get_strength,
+ mod_constitution,
+ mod_dexterity,
+ mod_intelligence,
+ mod_mind,
+ mod_speed,
+ mod_strength,
+ mod,
+ get,
+ new,
+ decode_category,
+ default
+ )
+
+-- Elm -------------------------------------------------------------------------
+
+-- Battle ----------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type Category =
+ Constitution
+ | Dexterity
+ | Intelligence
+ | Mind
+ | Speed
+ | Strength
+
+type alias Type =
+ {
+ constitution : Int,
+ dexterity : Int,
+ intelligence : Int,
+ mind : Int,
+ speed : Int,
+ strength : Int
+ }
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_within_range : Int -> Int -> Int -> Int
+get_within_range vmin vmax v = (min vmax (max vmin v))
+
+get_within_att_range : Int -> Int
+get_within_att_range v = (get_within_range 0 100 v)
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_constitution : Type -> Int
+get_constitution t = t.constitution
+
+get_dexterity : Type -> Int
+get_dexterity t = t.dexterity
+
+get_intelligence : Type -> Int
+get_intelligence t = t.intelligence
+
+get_mind : Type -> Int
+get_mind t = t.mind
+
+get_speed : Type -> Int
+get_speed t = t.speed
+
+get_strength : Type -> Int
+get_strength t = t.strength
+
+mod_constitution : Int -> Type -> Type
+mod_constitution i t =
+ {t |
+ constitution = (get_within_att_range (i + t.constitution))
+ }
+
+mod_dexterity : Int -> Type -> Type
+mod_dexterity i t =
+ {t |
+ dexterity = (get_within_att_range (i + t.dexterity))
+ }
+
+mod_intelligence : Int -> Type -> Type
+mod_intelligence i t =
+ {t |
+ intelligence = (get_within_att_range (i + t.intelligence))
+ }
+
+mod_mind : Int -> Type -> Type
+mod_mind i t =
+ {t |
+ mind = (get_within_att_range (i + t.mind))
+ }
+
+mod_speed : Int -> Type -> Type
+mod_speed i t =
+ {t |
+ speed = (get_within_att_range (i + t.speed))
+ }
+
+mod_strength : Int -> Type -> Type
+mod_strength i t =
+ {t |
+ strength = (get_within_att_range (i + t.strength))
+ }
+
+mod : Category -> Int -> Type -> Type
+mod cat i t =
+ case cat of
+ Constitution -> (mod_constitution i t)
+ Dexterity -> (mod_dexterity i t)
+ Intelligence -> (mod_intelligence i t)
+ Mind -> (mod_mind i t)
+ Speed -> (mod_speed i t)
+ Strength -> (mod_strength i t)
+
+get : Category -> Type -> Int
+get cat t =
+ case cat of
+ Constitution -> (get_constitution t)
+ Dexterity -> (get_dexterity t)
+ Intelligence -> (get_intelligence t)
+ Mind -> (get_mind t)
+ Speed -> (get_speed t)
+ Strength -> (get_strength t)
+
+new : (
+ Int -> -- constitution
+ Int -> -- dexterity
+ Int -> -- intelligence
+ Int -> -- mind
+ Int -> -- speed
+ Int -> -- strength
+ Type
+ )
+new con dex int min spe str =
+ {
+ constitution = con,
+ dexterity = dex,
+ intelligence = int,
+ mind = min,
+ speed = spe,
+ strength = str
+ }
+
+default : Type
+default =
+ {
+ constitution = 50,
+ dexterity = 50,
+ intelligence = 50,
+ mind = 50,
+ speed = 50,
+ strength = 50
+ }
+
+decode_category : String -> Category
+decode_category str =
+ case str of
+ "con" -> Constitution
+ "dex" -> Dexterity
+ "int" -> Intelligence
+ "min" -> Mind
+ "spe" -> Speed
+ _ -> Strength
diff --git a/src/roster-editor/src/Struct/Character.elm b/src/roster-editor/src/Struct/Character.elm
new file mode 100644
index 0000000..b837962
--- /dev/null
+++ b/src/roster-editor/src/Struct/Character.elm
@@ -0,0 +1,299 @@
+module Struct.Character exposing
+ (
+ Type,
+ Rank(..),
+ get_index,
+ get_player_ix,
+ get_name,
+ get_rank,
+ get_icon_id,
+ get_portrait_id,
+ get_armor,
+ get_armor_variation,
+ get_current_health,
+ get_current_omnimods,
+ get_sane_current_health,
+ set_current_health,
+ get_location,
+ set_location,
+ get_attributes,
+ get_statistics,
+ is_enabled,
+ is_defeated,
+ is_alive,
+ set_enabled,
+ set_defeated,
+ get_weapons,
+ set_weapons,
+ decoder,
+ refresh_omnimods,
+ fill_missing_equipment_and_omnimods
+ )
+
+-- Elm -------------------------------------------------------------------------
+import Json.Decode
+import Json.Decode.Pipeline
+
+-- Map -------------------------------------------------------------------
+import Struct.Armor
+import Struct.Attributes
+import Struct.Location
+import Struct.Omnimods
+import Struct.Statistics
+import Struct.Weapon
+import Struct.WeaponSet
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type alias PartiallyDecoded =
+ {
+ ix : Int,
+ nam : String,
+ rnk : String,
+ ico : String,
+ prt : String,
+ lc : Struct.Location.Type,
+ hea : Int,
+ pla : Int,
+ ena : Bool,
+ dea : Bool,
+ awp : Int,
+ swp : Int,
+ ar : Int,
+ omni : Struct.Omnimods.Type
+ }
+
+type Rank =
+ Optional
+ | Target
+ | Commander
+
+type alias Type =
+ {
+ ix : Int,
+ name : String,
+ rank : Rank,
+ icon : String,
+ portrait : String,
+ location : Struct.Location.Type,
+ health : Int,
+ player_ix : Int,
+ enabled : Bool,
+ defeated : Bool,
+ attributes : Struct.Attributes.Type,
+ statistics : Struct.Statistics.Type,
+ weapons : Struct.WeaponSet.Type,
+ armor : Struct.Armor.Type,
+ current_omnimods : Struct.Omnimods.Type,
+ permanent_omnimods : Struct.Omnimods.Type
+ }
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+str_to_rank : String -> Rank
+str_to_rank str =
+ case str of
+ "t" -> Target
+ "c" -> Commander
+ _ -> Optional
+
+finish_decoding : PartiallyDecoded -> (Type, Int, Int, Int)
+finish_decoding add_char =
+ let
+ weapon_set = (Struct.WeaponSet.new Struct.Weapon.none Struct.Weapon.none)
+ armor = Struct.Armor.none
+ default_attributes = (Struct.Attributes.default)
+ almost_char =
+ {
+ ix = add_char.ix,
+ name = add_char.nam,
+ rank = (str_to_rank add_char.rnk),
+ icon = add_char.ico,
+ portrait = add_char.prt,
+ location = add_char.lc,
+ health = add_char.hea,
+ attributes = default_attributes,
+ statistics = (Struct.Statistics.new_raw default_attributes),
+ player_ix = add_char.pla,
+ enabled = add_char.ena,
+ defeated = add_char.dea,
+ weapons = weapon_set,
+ armor = armor,
+ current_omnimods = (Struct.Omnimods.new [] [] [] []),
+ permanent_omnimods = add_char.omni
+ }
+ in
+ (almost_char, add_char.awp, add_char.swp, add_char.ar)
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_index : Type -> Int
+get_index c = c.ix
+
+get_name : Type -> String
+get_name c = c.name
+
+get_rank : Type -> Rank
+get_rank c = c.rank
+
+get_player_ix : Type -> Int
+get_player_ix c = c.player_ix
+
+get_icon_id : Type -> String
+get_icon_id c = c.icon
+
+get_portrait_id : Type -> String
+get_portrait_id c = c.portrait
+
+get_current_health : Type -> Int
+get_current_health c = c.health
+
+get_current_omnimods : Type -> Struct.Omnimods.Type
+get_current_omnimods c = c.current_omnimods
+
+get_sane_current_health : Type -> Int
+get_sane_current_health c = (max 0 c.health)
+
+set_current_health : Int -> Type -> Type
+set_current_health health c = {c | health = health}
+
+get_location : Type -> Struct.Location.Type
+get_location t = t.location
+
+set_location : Struct.Location.Type -> Type -> Type
+set_location location char = {char | location = location}
+
+get_attributes : Type -> Struct.Attributes.Type
+get_attributes char = char.attributes
+
+get_statistics : Type -> Struct.Statistics.Type
+get_statistics char = char.statistics
+
+is_alive : Type -> Bool
+is_alive char = ((char.health > 0) && (not char.defeated))
+
+is_enabled : Type -> Bool
+is_enabled char = char.enabled
+
+is_defeated : Type -> Bool
+is_defeated char = char.defeated
+
+set_enabled : Bool -> Type -> Type
+set_enabled enabled char = {char | enabled = enabled}
+
+set_defeated : Bool -> Type -> Type
+set_defeated defeated char = {char | defeated = defeated}
+
+get_weapons : Type -> Struct.WeaponSet.Type
+get_weapons char = char.weapons
+
+get_armor : Type -> Struct.Armor.Type
+get_armor char = char.armor
+
+get_armor_variation : Type -> String
+get_armor_variation char =
+ case char.portrait of
+ -- Currently hardcoded to match crows from characters.css
+ "11" -> "1"
+ "4" -> "1"
+ _ -> "0"
+
+set_weapons : Struct.WeaponSet.Type -> Type -> Type
+set_weapons weapons char =
+ {char |
+ weapons = weapons
+ }
+
+decoder : (Json.Decode.Decoder (Type, Int, Int, Int))
+decoder =
+ (Json.Decode.map
+ (finish_decoding)
+ (Json.Decode.Pipeline.decode
+ PartiallyDecoded
+ |> (Json.Decode.Pipeline.required "ix" Json.Decode.int)
+ |> (Json.Decode.Pipeline.required "nam" Json.Decode.string)
+ |> (Json.Decode.Pipeline.required "rnk" Json.Decode.string)
+ |> (Json.Decode.Pipeline.required "ico" Json.Decode.string)
+ |> (Json.Decode.Pipeline.required "prt" Json.Decode.string)
+ |> (Json.Decode.Pipeline.required "lc" Struct.Location.decoder)
+ |> (Json.Decode.Pipeline.required "hea" Json.Decode.int)
+ |> (Json.Decode.Pipeline.required "pla" Json.Decode.int)
+ |> (Json.Decode.Pipeline.required "ena" Json.Decode.bool)
+ |> (Json.Decode.Pipeline.required "dea" Json.Decode.bool)
+ |> (Json.Decode.Pipeline.required "awp" Json.Decode.int)
+ |> (Json.Decode.Pipeline.required "swp" Json.Decode.int)
+ |> (Json.Decode.Pipeline.required "ar" Json.Decode.int)
+ |> (Json.Decode.Pipeline.required "pomni" Struct.Omnimods.decoder)
+ )
+ )
+
+refresh_omnimods : (
+ (Struct.Location.Type -> Struct.Omnimods.Type) ->
+ Type ->
+ Type
+ )
+refresh_omnimods tile_omnimods_fun char =
+ let
+ previous_max_health = (Struct.Statistics.get_max_health char.statistics)
+ current_omnimods =
+ (Struct.Omnimods.merge
+ (Struct.Weapon.get_omnimods
+ (Struct.WeaponSet.get_active_weapon char.weapons)
+ )
+ (Struct.Omnimods.merge
+ (tile_omnimods_fun char.location)
+ char.permanent_omnimods
+ )
+ )
+ current_attributes =
+ (Struct.Omnimods.apply_to_attributes
+ current_omnimods
+ (Struct.Attributes.default)
+ )
+ current_statistics =
+ (Struct.Omnimods.apply_to_statistics
+ current_omnimods
+ (Struct.Statistics.new_raw current_attributes)
+ )
+ new_max_health = (Struct.Statistics.get_max_health current_statistics)
+ in
+ {char |
+ attributes = current_attributes,
+ statistics = current_statistics,
+ current_omnimods = current_omnimods,
+ health =
+ (clamp
+ 1
+ new_max_health
+ (round
+ (
+ ((toFloat char.health) / (toFloat previous_max_health))
+ * (toFloat new_max_health)
+ )
+ )
+ )
+ }
+
+fill_missing_equipment_and_omnimods : (
+ (Struct.Location.Type -> Struct.Omnimods.Type) ->
+ Struct.Weapon.Type ->
+ Struct.Weapon.Type ->
+ Struct.Armor.Type ->
+ Type ->
+ Type
+ )
+fill_missing_equipment_and_omnimods tile_omnimods_fun awp swp ar char =
+ (set_current_health
+ -- We just changed the omnimods, but already had the right health value
+ char.health
+ (refresh_omnimods
+ (tile_omnimods_fun)
+ {char |
+ weapons = (Struct.WeaponSet.new awp swp),
+ armor = ar
+ }
+ )
+ )
diff --git a/src/roster-editor/src/Struct/DamageType.elm b/src/roster-editor/src/Struct/DamageType.elm
new file mode 100644
index 0000000..b7bced7
--- /dev/null
+++ b/src/roster-editor/src/Struct/DamageType.elm
@@ -0,0 +1,55 @@
+module Struct.DamageType exposing
+ (
+ Type(..),
+ encode,
+ decode,
+ to_string
+ )
+
+-- Elm -------------------------------------------------------------------------
+
+-- Map -------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type Type =
+ Base
+ | Slash
+ | Blunt
+ | Pierce
+ | None
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+decode : String -> Type
+decode str =
+ case str of
+ "bse" -> Base
+ "slh" -> Slash
+ "pie" -> Pierce
+ "blu" -> Blunt
+ _ -> None
+
+encode : Type -> String
+encode t =
+ case t of
+ Base -> "bse"
+ Slash -> "slh"
+ Pierce -> "pie"
+ Blunt -> "blu"
+ None -> "non"
+
+to_string : Type -> String
+to_string t =
+ case t of
+ Base -> "Base"
+ Slash -> "Slash"
+ Pierce -> "Piercing"
+ Blunt -> "Bludgeoning"
+ None -> "ERROR"
diff --git a/src/roster-editor/src/Struct/Error.elm b/src/roster-editor/src/Struct/Error.elm
new file mode 100644
index 0000000..5f40c09
--- /dev/null
+++ b/src/roster-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/roster-editor/src/Struct/Event.elm b/src/roster-editor/src/Struct/Event.elm
new file mode 100644
index 0000000..e95d029
--- /dev/null
+++ b/src/roster-editor/src/Struct/Event.elm
@@ -0,0 +1,30 @@
+module Struct.Event exposing (Type(..), attempted)
+
+-- Elm -------------------------------------------------------------------------
+import Http
+
+-- Roster Editor ---------------------------------------------------------------
+import Struct.Error
+import Struct.ServerReply
+import Struct.HelpRequest
+import Struct.UI
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type Type =
+ None
+ | CharacterSelected Int
+ | Failed Struct.Error.Type
+ | GoToMainMenu
+ | RequestedHelp Struct.HelpRequest.Type
+ | ServerReplied (Result Http.Error (List Struct.ServerReply.Type))
+ | TabSelected Struct.UI.Tab
+ | TileSelected Struct.Location.Ref
+
+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/roster-editor/src/Struct/HelpRequest.elm b/src/roster-editor/src/Struct/HelpRequest.elm
new file mode 100644
index 0000000..a0693e2
--- /dev/null
+++ b/src/roster-editor/src/Struct/HelpRequest.elm
@@ -0,0 +1,13 @@
+module Struct.HelpRequest exposing (Type(..))
+
+-- Elm -------------------------------------------------------------------------
+
+-- Map -------------------------------------------------------------------
+import Struct.Character
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type Type =
+ None
+ | HelpOnRank Struct.Character.Rank
diff --git a/src/roster-editor/src/Struct/Model.elm b/src/roster-editor/src/Struct/Model.elm
new file mode 100644
index 0000000..3e7fc01
--- /dev/null
+++ b/src/roster-editor/src/Struct/Model.elm
@@ -0,0 +1,149 @@
+module Struct.Model exposing
+ (
+ Type,
+ new,
+ add_character,
+ update_character,
+ update_character_fun,
+ add_weapon,
+ add_armor,
+ invalidate,
+ clear_error
+ )
+
+-- Elm -------------------------------------------------------------------------
+import Array
+
+import Dict
+
+-- Shared ----------------------------------------------------------------------
+import Struct.Flags
+
+-- Roster Editor ---------------------------------------------------------------
+import Struct.Armor
+import Struct.Character
+import Struct.CharacterTurn
+import Struct.Error
+import Struct.HelpRequest
+import Struct.Omnimods
+import Struct.UI
+import Struct.Weapon
+
+import Util.Array
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type alias Type =
+ {
+ flags: Struct.Flags.Type,
+ help_request: Struct.HelpRequest.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),
+ error: (Maybe Struct.Error.Type),
+ player_id: String,
+ roster_id: String,
+ session_token: String,
+ ui: Struct.UI.Type
+ }
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+new : Struct.Flags.Type -> Type
+new flags =
+ let
+ maybe_roster_id = (Struct.Flags.maybe_get_param "id" flags)
+ model =
+ {
+ flags = flags,
+ help_request = Struct.HelpRequest.None,
+ characters = (Array.empty),
+ weapons = (Dict.empty),
+ armors = (Dict.empty),
+ error = Nothing,
+ roster_id = "",
+ player_id =
+ (
+ if (flags.user_id == "")
+ then "0"
+ else flags.user_id
+ ),
+ session_token = flags.token,
+ ui = (Struct.UI.default)
+ }
+ in
+ case maybe_roster_id of
+ Nothing ->
+ (invalidate
+ (Struct.Error.new
+ Struct.Error.Failure
+ "Could not find roster id."
+ )
+ model
+ )
+
+ (Just id) -> {model | roster_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
+ )
+ }
+
+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/roster-editor/src/Struct/Omnimods.elm b/src/roster-editor/src/Struct/Omnimods.elm
new file mode 100644
index 0000000..5876454
--- /dev/null
+++ b/src/roster-editor/src/Struct/Omnimods.elm
@@ -0,0 +1,180 @@
+module Struct.Omnimods exposing
+ (
+ Type,
+ new,
+ merge,
+ apply_to_attributes,
+ apply_to_statistics,
+ get_attack_damage,
+ get_damage_sum,
+ get_attributes_mods,
+ get_statistics_mods,
+ get_attack_mods,
+ get_defense_mods,
+ decoder
+ )
+
+-- Elm -------------------------------------------------------------------------
+import Dict
+
+import Json.Decode
+import Json.Decode.Pipeline
+
+-- Map -------------------------------------------------------------------
+import Struct.Attributes
+import Struct.Statistics
+import Struct.DamageType
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type alias Type =
+ {
+ attributes : (Dict.Dict String Int),
+ statistics : (Dict.Dict String Int),
+ attack : (Dict.Dict String Int),
+ defense : (Dict.Dict String Int)
+ }
+
+type alias GenericMod =
+ {
+ t : String,
+ v : Int
+ }
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+generic_mods_decoder : (Json.Decode.Decoder (Dict.Dict String Int))
+generic_mods_decoder =
+ (Json.Decode.map
+ (Dict.fromList)
+ (Json.Decode.list
+ (Json.Decode.map
+ (\gm -> (gm.t, gm.v))
+ (Json.Decode.Pipeline.decode
+ GenericMod
+ |> (Json.Decode.Pipeline.required "t" Json.Decode.string)
+ |> (Json.Decode.Pipeline.required "v" Json.Decode.int)
+ )
+ )
+ )
+ )
+
+merge_mods : (
+ (Dict.Dict String Int) ->
+ (Dict.Dict String Int) ->
+ (Dict.Dict String Int)
+ )
+merge_mods a_mods b_mods =
+ (Dict.merge
+ (Dict.insert)
+ (\t -> \v_a -> \v_b -> \r -> (Dict.insert t (v_a + v_b) r))
+ (Dict.insert)
+ a_mods
+ b_mods
+ (Dict.empty)
+ )
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+decoder : (Json.Decode.Decoder Type)
+decoder =
+ (Json.Decode.Pipeline.decode
+ Type
+ |> (Json.Decode.Pipeline.required "attm" generic_mods_decoder)
+ |> (Json.Decode.Pipeline.required "stam" generic_mods_decoder)
+ |> (Json.Decode.Pipeline.required "atkm" generic_mods_decoder)
+ |> (Json.Decode.Pipeline.required "defm" generic_mods_decoder)
+ )
+
+new : (
+ (List (String, Int)) ->
+ (List (String, Int)) ->
+ (List (String, Int)) ->
+ (List (String, Int)) ->
+ Type
+ )
+new attribute_mods statistic_mods attack_mods defense_mods =
+ {
+ attributes = (Dict.fromList attribute_mods),
+ statistics = (Dict.fromList statistic_mods),
+ attack = (Dict.fromList attack_mods),
+ defense = (Dict.fromList defense_mods)
+ }
+
+merge : Type -> Type -> Type
+merge omni_a omni_b =
+ {
+ attributes = (merge_mods omni_a.attributes omni_b.attributes),
+ statistics = (merge_mods omni_a.statistics omni_b.statistics),
+ attack = (merge_mods omni_a.attack omni_b.attack),
+ defense = (merge_mods omni_a.defense omni_b.defense)
+ }
+
+apply_to_attributes : Type -> Struct.Attributes.Type -> Struct.Attributes.Type
+apply_to_attributes omnimods attributes =
+ (Dict.foldl
+ ((Struct.Attributes.decode_category) >> (Struct.Attributes.mod))
+ attributes
+ omnimods.attributes
+ )
+
+apply_to_statistics : Type -> Struct.Statistics.Type -> Struct.Statistics.Type
+apply_to_statistics omnimods statistics =
+ (Dict.foldl
+ ((Struct.Statistics.decode_category) >> (Struct.Statistics.mod))
+ statistics
+ omnimods.statistics
+ )
+
+get_damage_sum : Type -> Int
+get_damage_sum omni =
+ (Dict.foldl (\t -> \v -> \result -> (result + v)) 0 omni.attack)
+
+get_attack_damage : Float -> Type -> Type -> Int
+get_attack_damage dmg_modifier atk_omni def_omni =
+ let
+ base_def =
+ (
+ case
+ (Dict.get
+ (Struct.DamageType.encode Struct.DamageType.Base)
+ def_omni.defense
+ )
+ of
+ (Just v) -> v
+ Nothing -> 0
+ )
+ in
+ (Dict.foldl
+ (\t -> \v -> \result ->
+ let
+ actual_atk =
+ (max
+ 0
+ (
+ (ceiling ((toFloat v) * dmg_modifier))
+ - base_def
+ )
+ )
+ in
+ case (Dict.get t def_omni.defense) of
+ (Just def_v) -> (result + (max 0 (actual_atk - def_v)))
+ Nothing -> (result + actual_atk)
+ )
+ 0
+ atk_omni.attack
+ )
+
+get_attributes_mods : Type -> (List (String, Int))
+get_attributes_mods omnimods = (Dict.toList omnimods.attributes)
+
+get_statistics_mods : Type -> (List (String, Int))
+get_statistics_mods omnimods = (Dict.toList omnimods.statistics)
+
+get_attack_mods : Type -> (List (String, Int))
+get_attack_mods omnimods = (Dict.toList omnimods.attack)
+
+get_defense_mods : Type -> (List (String, Int))
+get_defense_mods omnimods = (Dict.toList omnimods.defense)
diff --git a/src/roster-editor/src/Struct/ServerReply.elm b/src/roster-editor/src/Struct/ServerReply.elm
new file mode 100644
index 0000000..50968f6
--- /dev/null
+++ b/src/roster-editor/src/Struct/ServerReply.elm
@@ -0,0 +1,27 @@
+module Struct.ServerReply exposing (Type(..))
+
+-- Elm -------------------------------------------------------------------------
+
+-- Character -------------------------------------------------------------------
+import Struct.Armor
+import Struct.Character
+import Struct.Weapon
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+type Type =
+ Okay
+ | Disconnected
+ | AddArmor Struct.Armor.Type
+ | AddWeapon Struct.Weapon.Type
+ | AddCharacter (Struct.Character.Type, Int, Int, Int)
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
diff --git a/src/roster-editor/src/Struct/Statistics.elm b/src/roster-editor/src/Struct/Statistics.elm
new file mode 100644
index 0000000..f676648
--- /dev/null
+++ b/src/roster-editor/src/Struct/Statistics.elm
@@ -0,0 +1,210 @@
+module Struct.Statistics exposing
+ (
+ Type,
+ Category(..),
+ get_movement_points,
+ get_max_health,
+ get_dodges,
+ get_parries,
+ get_accuracy,
+ get_double_hits,
+ get_critical_hits,
+ get_damage_modifier,
+ decode_category,
+ mod,
+ new_raw
+ )
+
+-- Elm -------------------------------------------------------------------------
+import List
+
+-- Battle ----------------------------------------------------------------------
+import Struct.Attributes
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type Category =
+ MovementPoints
+ | MaxHealth
+ | Dodges
+ | Parries
+ | Accuracy
+ | DoubleHits
+ | CriticalHits
+
+type alias Type =
+ {
+ movement_points : Int,
+ max_health : Int,
+ dodges : Int,
+ parries : Int,
+ accuracy : Int,
+ double_hits : Int,
+ critical_hits : Int,
+ damage_modifier : Float
+ }
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+average : (List Int) -> Float
+average l = ((toFloat (List.sum l)) / (toFloat (List.length l)))
+
+float_to_int : Float -> Int
+float_to_int f =
+ (ceiling f)
+
+gentle_squared_growth : Int -> Int
+gentle_squared_growth v = (float_to_int (((toFloat v)^1.8)/20.0))
+
+gentle_squared_growth_f : Float -> Int
+gentle_squared_growth_f v = (float_to_int ((v^1.8)/20.0))
+
+sudden_squared_growth : Int -> Int
+sudden_squared_growth v = (float_to_int (((toFloat v)^2.5)/1000.0))
+
+sudden_squared_growth_f : Float -> Int
+sudden_squared_growth_f v = (float_to_int ((v^2.5)/1000.0))
+
+sudden_exp_growth : Int -> Int
+sudden_exp_growth v = (float_to_int (4.0^((toFloat v)/25.0)))
+
+sudden_exp_growth_f : Float -> Int
+sudden_exp_growth_f f = (float_to_int (4.0^(f/25.0)))
+
+damage_base_mod : Float -> Float
+damage_base_mod str = ((((str + 10) * 4)^1.5)/3000.0)
+
+make_movement_points_safe : Int -> Int
+make_movement_points_safe val = (clamp 0 200 val)
+
+make_max_health_safe : Int -> Int
+make_max_health_safe val = (max 1 val)
+
+make_dodges_safe : Int -> Int
+make_dodges_safe val = (clamp 0 100 val)
+
+make_parries_safe : Int -> Int
+make_parries_safe val = (clamp 0 75 val)
+
+make_accuracy_safe : Int -> Int
+make_accuracy_safe val = (clamp 0 100 val)
+
+make_double_hits_safe : Int -> Int
+make_double_hits_safe val = (clamp 0 100 val)
+
+make_critical_hits_safe : Int -> Int
+make_critical_hits_safe val = (clamp 0 100 val)
+
+mod_movement_points : Int -> Type -> Type
+mod_movement_points v t =
+ {t |
+ movement_points = (make_movement_points_safe (t.movement_points + v))
+ }
+
+mod_max_health : Int -> Type -> Type
+mod_max_health v t =
+ {t |
+ max_health = (make_max_health_safe (t.max_health + v))
+ }
+
+mod_dodges : Int -> Type -> Type
+mod_dodges v t = {t | dodges = (make_dodges_safe (t.dodges + v))}
+
+mod_parries : Int -> Type -> Type
+mod_parries v t = {t | parries = (make_parries_safe (t.parries + v))}
+
+mod_accuracy : Int -> Type -> Type
+mod_accuracy v t = {t | accuracy = (make_accuracy_safe (t.accuracy + v))}
+
+mod_double_hits : Int -> Type -> Type
+mod_double_hits v t =
+ {t |
+ double_hits = (make_double_hits_safe (t.double_hits + v))
+ }
+
+mod_critical_hits : Int -> Type -> Type
+mod_critical_hits v t =
+ {t |
+ critical_hits = (make_critical_hits_safe (t.critical_hits + v))
+ }
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_movement_points : Type -> Int
+get_movement_points t = t.movement_points
+
+get_max_health : Type -> Int
+get_max_health t = t.max_health
+
+get_dodges : Type -> Int
+get_dodges t = t.dodges
+
+get_parries : Type -> Int
+get_parries t = t.parries
+
+get_accuracy : Type -> Int
+get_accuracy t = t.accuracy
+
+get_double_hits : Type -> Int
+get_double_hits t = t.double_hits
+
+get_critical_hits : Type -> Int
+get_critical_hits t = t.critical_hits
+
+get_damage_modifier : Type -> Float
+get_damage_modifier t = t.damage_modifier
+
+mod : Category -> Int -> Type -> Type
+mod cat v t =
+ case cat of
+ MaxHealth -> (mod_max_health v t)
+ MovementPoints -> (mod_movement_points v t)
+ Dodges -> (mod_dodges v t)
+ Parries -> (mod_parries v t)
+ Accuracy -> (mod_accuracy v t)
+ DoubleHits -> (mod_double_hits v t)
+ CriticalHits -> (mod_critical_hits v t)
+
+new_raw : (Struct.Attributes.Type -> Type)
+new_raw att =
+ let
+ constitution = (Struct.Attributes.get_constitution att)
+ dexterity = (Struct.Attributes.get_dexterity att)
+ intelligence = (Struct.Attributes.get_intelligence att)
+ mind = (Struct.Attributes.get_mind att)
+ speed = (Struct.Attributes.get_speed att)
+ strength = (Struct.Attributes.get_strength att)
+ in
+ {
+ movement_points =
+ (gentle_squared_growth_f
+ (average [mind, constitution, constitution, speed, speed, speed])
+ ),
+ max_health =
+ (gentle_squared_growth_f
+ (average [constitution, constitution, constitution, mind])
+ ),
+ dodges = (sudden_exp_growth_f (average [dexterity, mind, speed])),
+ parries =
+ (sudden_exp_growth_f
+ (average [dexterity, intelligence, speed, strength])
+ ),
+ accuracy = (sudden_squared_growth dexterity),
+ double_hits = (sudden_squared_growth_f (average [mind, speed])),
+ critical_hits = (sudden_squared_growth intelligence),
+ damage_modifier = (damage_base_mod (toFloat strength))
+ }
+
+decode_category : String -> Category
+decode_category str =
+ case str of
+ "mheal" -> MaxHealth
+ "mpts" -> MovementPoints
+ "dodg" -> Dodges
+ "pary" -> Parries
+ "accu" -> Accuracy
+ "dhit" -> DoubleHits
+ _ -> CriticalHits
diff --git a/src/roster-editor/src/Struct/UI.elm b/src/roster-editor/src/Struct/UI.elm
new file mode 100644
index 0000000..2831bc0
--- /dev/null
+++ b/src/roster-editor/src/Struct/UI.elm
@@ -0,0 +1,52 @@
+module Struct.UI exposing
+ (
+ Type,
+ Tab(..),
+ default,
+ -- Tab
+ get_displayed_tab,
+ set_displayed_tab,
+ reset_displayed_tab
+ )
+
+-- Elm -------------------------------------------------------------------------
+
+-- Roster Editor ---------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type Tab =
+ CharacterSelectionTab
+ | PortraitSelectionTab
+-- | AccessorySelectionTab
+ | WeaponSelectionTab
+ | GlyphManagementTab
+
+type alias Type =
+ {
+ displayed_tab : Tab
+ }
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+default : Type
+default =
+ {
+ displayed_tab = CharacterSelectionTab,
+ }
+
+-- Tab -------------------------------------------------------------------------
+get_displayed_tab : Type -> Tab
+get_displayed_tab ui = ui.displayed_tab
+
+set_displayed_tab : Tab -> Type -> Type
+set_displayed_tab tab ui = {ui | displayed_tab = tab}
+
+reset_displayed_tab : Type -> Type
+reset_displayed_tab ui = {ui | displayed_tab = CharacterSelectionTab}
diff --git a/src/roster-editor/src/Struct/Weapon.elm b/src/roster-editor/src/Struct/Weapon.elm
new file mode 100644
index 0000000..2035fe4
--- /dev/null
+++ b/src/roster-editor/src/Struct/Weapon.elm
@@ -0,0 +1,99 @@
+module Struct.Weapon exposing
+ (
+ Type,
+ Ref,
+ new,
+ get_id,
+ get_name,
+ get_attack_range,
+ get_defense_range,
+ get_omnimods,
+ get_damage_sum,
+ decoder,
+ none
+ )
+
+-- Elm -------------------------------------------------------------------------
+import Json.Decode
+import Json.Decode.Pipeline
+
+-- Map -------------------------------------------------------------------
+import Struct.Omnimods
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type alias PartiallyDecoded =
+ {
+ id : Int,
+ nam : String,
+ rmi : Int,
+ rma : Int,
+ omni : String
+ }
+
+type alias Type =
+ {
+ id : Int,
+ name : String,
+ def_range : Int,
+ atk_range : Int,
+ omnimods : Struct.Omnimods.Type,
+ damage_sum : Int
+ }
+
+type alias Ref = Int
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+new : Int -> String -> Int -> Int -> Struct.Omnimods.Type -> Type
+new id name range_min range_max omnimods =
+ {
+ id = id,
+ name = name,
+ def_range = range_min,
+ atk_range = range_max,
+ omnimods = omnimods,
+ damage_sum = (Struct.Omnimods.get_damage_sum omnimods)
+ }
+
+get_id : Type -> Int
+get_id wp = wp.id
+
+get_name : Type -> String
+get_name wp = wp.name
+
+get_attack_range : Type -> Int
+get_attack_range wp = wp.atk_range
+
+get_defense_range : Type -> Int
+get_defense_range wp = wp.def_range
+
+get_omnimods : Type -> Struct.Omnimods.Type
+get_omnimods wp = wp.omnimods
+
+get_damage_sum : Type -> Int
+get_damage_sum wp = wp.damage_sum
+
+decoder : (Json.Decode.Decoder Type)
+decoder =
+ (Json.Decode.map
+ (\e -> {e | damage_sum = (Struct.Omnimods.get_damage_sum e.omnimods)})
+ (Json.Decode.Pipeline.decode
+ Type
+ |> (Json.Decode.Pipeline.required "id" Json.Decode.int)
+ |> (Json.Decode.Pipeline.required "nam" Json.Decode.string)
+ |> (Json.Decode.Pipeline.required "rmi" Json.Decode.int)
+ |> (Json.Decode.Pipeline.required "rma" Json.Decode.int)
+ |> (Json.Decode.Pipeline.required "omni" Struct.Omnimods.decoder)
+ |> (Json.Decode.Pipeline.hardcoded 0)
+ )
+ )
+
+none : Type
+none = (new 0 "None" 0 0 (Struct.Omnimods.new [] [] [] []))
diff --git a/src/roster-editor/src/Struct/WeaponSet.elm b/src/roster-editor/src/Struct/WeaponSet.elm
new file mode 100644
index 0000000..de96daf
--- /dev/null
+++ b/src/roster-editor/src/Struct/WeaponSet.elm
@@ -0,0 +1,39 @@
+module Struct.WeaponSet exposing
+ (
+ Type,
+ new,
+ get_active_weapon,
+ get_secondary_weapon,
+ switch_weapons
+ )
+
+-- Map -------------------------------------------------------------------
+import Struct.Weapon
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type alias Type =
+ {
+ active : Struct.Weapon.Type,
+ secondary : Struct.Weapon.Type
+ }
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+new : Struct.Weapon.Type -> Struct.Weapon.Type -> Type
+new wp0 wp1 = { active = wp0, secondary = wp1 }
+
+get_active_weapon : Type -> Struct.Weapon.Type
+get_active_weapon set = set.active
+
+get_secondary_weapon : Type -> Struct.Weapon.Type
+get_secondary_weapon set = set.secondary
+
+switch_weapons : Type -> Type
+switch_weapons set = {set | active = set.secondary, secondary = set.active}
diff --git a/src/roster-editor/src/Update/DisplayCharacterInfo.elm b/src/roster-editor/src/Update/DisplayCharacterInfo.elm
new file mode 100644
index 0000000..e482e2f
--- /dev/null
+++ b/src/roster-editor/src/Update/DisplayCharacterInfo.elm
@@ -0,0 +1,53 @@
+module Update.DisplayCharacterInfo exposing (apply_to)
+-- Elm -------------------------------------------------------------------------
+import Array
+import Task
+
+-- Map -------------------------------------------------------------------
+import Action.Scroll
+
+import Struct.Character
+import Struct.Event
+import Struct.Model
+import Struct.UI
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+scroll_to_char : Struct.Model.Type -> Int -> (Cmd Struct.Event.Type)
+scroll_to_char model char_ix =
+ case (Array.get char_ix model.characters) of
+ (Just char) ->
+ (Task.attempt
+ (Struct.Event.attempted)
+ (Action.Scroll.to
+ (Struct.Character.get_location char)
+ model.ui
+ )
+ )
+
+ Nothing ->
+ Cmd.none
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+apply_to : (
+ Struct.Model.Type ->
+ Int ->
+ (Struct.Model.Type, (Cmd Struct.Event.Type))
+ )
+apply_to model target_ref =
+ (
+ {model |
+ ui =
+ (Struct.UI.set_displayed_tab
+ Struct.UI.StatusTab
+ (Struct.UI.set_previous_action
+ (Just (Struct.UI.SelectedCharacter target_ref))
+ model.ui
+ )
+ )
+ },
+ (scroll_to_char model target_ref)
+ )
diff --git a/src/roster-editor/src/Update/GoToMainMenu.elm b/src/roster-editor/src/Update/GoToMainMenu.elm
new file mode 100644
index 0000000..f2ec989
--- /dev/null
+++ b/src/roster-editor/src/Update/GoToMainMenu.elm
@@ -0,0 +1,24 @@
+module Update.GoToMainMenu exposing (apply_to)
+-- Elm -------------------------------------------------------------------------
+
+-- Battle ----------------------------------------------------------------------
+import Action.Ports
+
+import Constants.IO
+
+import Struct.Model
+import Struct.Event
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+apply_to : Struct.Model.Type -> (Struct.Model.Type, (Cmd Struct.Event.Type))
+apply_to model =
+ (
+ model,
+ (Action.Ports.go_to (Constants.IO.base_url ++"/main-menu/"))
+ )
diff --git a/src/roster-editor/src/Update/HandleServerReply.elm b/src/roster-editor/src/Update/HandleServerReply.elm
new file mode 100644
index 0000000..22261da
--- /dev/null
+++ b/src/roster-editor/src/Update/HandleServerReply.elm
@@ -0,0 +1,174 @@
+module Update.HandleServerReply exposing (apply_to)
+
+-- Elm -------------------------------------------------------------------------
+import Array
+
+import Delay
+
+import Dict
+
+import Http
+
+import Time
+
+-- Shared ----------------------------------------------------------------------
+import Action.Ports
+
+import Struct.Flags
+
+-- Roster Editor ---------------------------------------------------------------
+import Constants.IO
+
+import Struct.Armor
+import Struct.Character
+import Struct.Error
+import Struct.Event
+import Struct.Model
+import Struct.ServerReply
+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
+
+-----------
+
+disconnected : (
+ (Struct.Model.Type, (List (Cmd Struct.Event.Type))) ->
+ (Struct.Model.Type, (List (Cmd Struct.Event.Type)))
+ )
+disconnected current_state =
+ let (model, cmds) = current_state in
+ (
+ model,
+ [
+ (Action.Ports.go_to
+ (
+ Constants.IO.base_url
+ ++ "/login/?action=disconnect&goto="
+ ++
+ (Http.encodeUri
+ (
+ "/roster-editor/?"
+ ++ (Struct.Flags.get_params_as_url model.flags)
+ )
+ )
+ )
+ )
+ ]
+ )
+
+add_armor : (
+ Struct.Armor.Type ->
+ (Struct.Model.Type, (List (Cmd Struct.Event.Type))) ->
+ (Struct.Model.Type, (List (Cmd Struct.Event.Type)))
+ )
+add_armor ar current_state =
+ let (model, cmds) = current_state in
+ ((Struct.Model.add_armor ar model), cmds)
+
+add_weapon : (
+ Struct.Weapon.Type ->
+ (Struct.Model.Type, (List (Cmd Struct.Event.Type))) ->
+ (Struct.Model.Type, (List (Cmd Struct.Event.Type)))
+ )
+add_weapon wp current_state =
+ let (model, cmds) = current_state in
+ ((Struct.Model.add_weapon wp model), cmds)
+
+add_character : (
+ (Struct.Character.Type, Int, Int, Int) ->
+ (Struct.Model.Type, (List (Cmd Struct.Event.Type))) ->
+ (Struct.Model.Type, (List (Cmd Struct.Event.Type)))
+ )
+add_character char_and_refs current_state =
+ let
+ (model, cmds) = current_state
+ (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_and_omnimods
+ (Struct.Model.tile_omnimods_fun model)
+ awp
+ swp
+ ar
+ char
+ )
+ model
+ ),
+ cmds
+ )
+
+apply_command : (
+ Struct.ServerReply.Type ->
+ (Struct.Model.Type, (List (Cmd Struct.Event.Type))) ->
+ (Struct.Model.Type, (List (Cmd Struct.Event.Type)))
+ )
+apply_command command current_state =
+ case command of
+ Struct.ServerReply.Disconnected -> (disconnected current_state)
+
+ (Struct.ServerReply.AddWeapon wp) ->
+ (add_weapon wp current_state)
+
+ (Struct.ServerReply.AddArmor ar) ->
+ (add_armor ar current_state)
+
+ (Struct.ServerReply.AddCharacter char) ->
+ (add_character char 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, elm_commands) =
+ (List.foldl (apply_command) (model, [Cmd.none]) commands)
+ in
+ (
+ new_model,
+ (
+ case elm_commands of
+ [] -> Cmd.none
+ [cmd] -> cmd
+ _ -> (Cmd.batch elm_commands)
+ )
+ )
diff --git a/src/roster-editor/src/Update/SelectCharacter.elm b/src/roster-editor/src/Update/SelectCharacter.elm
new file mode 100644
index 0000000..169046c
--- /dev/null
+++ b/src/roster-editor/src/Update/SelectCharacter.elm
@@ -0,0 +1,298 @@
+module Update.SelectCharacter exposing (apply_to)
+
+-- Elm -------------------------------------------------------------------------
+import Array
+
+import Task
+
+-- Map -------------------------------------------------------------------
+import Action.Scroll
+
+import Struct.Map
+import Struct.Character
+import Struct.CharacterTurn
+import Struct.Error
+import Struct.Event
+import Struct.Location
+import Struct.Model
+import Struct.Navigator
+import Struct.Statistics
+import Struct.UI
+import Struct.Weapon
+import Struct.WeaponSet
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_character_navigator : (
+ Struct.Model.Type ->
+ Struct.Character.Type ->
+ Struct.Navigator.Type
+ )
+get_character_navigator model char =
+ let
+ weapon =
+ (Struct.WeaponSet.get_active_weapon
+ (Struct.Character.get_weapons char)
+ )
+ in
+ (Struct.Navigator.new
+ (Struct.Character.get_location char)
+ (Struct.Statistics.get_movement_points
+ (Struct.Character.get_statistics char)
+ )
+ (Struct.Weapon.get_defense_range weapon)
+ (Struct.Weapon.get_attack_range weapon)
+ (Struct.Map.get_movement_cost_function
+ model.map
+ (Struct.Character.get_location char)
+ (Array.toList model.characters)
+ )
+ )
+
+attack_character : (
+ Struct.Model.Type ->
+ Int ->
+ Struct.Character.Type ->
+ Struct.Model.Type
+ )
+attack_character model target_char_id target_char =
+ {model |
+ char_turn =
+ (Struct.CharacterTurn.set_target
+ (Just target_char_id)
+ model.char_turn
+ ),
+ ui =
+ (Struct.UI.reset_displayed_nav
+ (Struct.UI.reset_displayed_tab
+ (Struct.UI.set_previous_action Nothing model.ui)
+ )
+ )
+ }
+
+ctrl_or_focus_character : (
+ Struct.Model.Type ->
+ Int ->
+ Struct.Character.Type ->
+ Struct.Model.Type
+ )
+ctrl_or_focus_character model target_char_id target_char =
+ if (Struct.Character.is_enabled target_char)
+ then
+ let
+ nav =
+ (case (Struct.UI.try_getting_displayed_nav model.ui) of
+ (Just dnav) -> dnav
+ Nothing ->
+ (get_character_navigator model target_char)
+ )
+ in
+ {model |
+ char_turn =
+ (Struct.CharacterTurn.set_navigator
+ nav
+ (Struct.CharacterTurn.set_active_character
+ target_char
+ model.char_turn
+ )
+ ),
+ ui =
+ (Struct.UI.reset_displayed_nav
+ (Struct.UI.reset_displayed_tab
+ (Struct.UI.set_previous_action Nothing model.ui)
+ )
+ )
+ }
+ else
+ {model |
+ ui =
+ (Struct.UI.set_previous_action
+ (Just (Struct.UI.SelectedCharacter target_char_id))
+ (Struct.UI.set_displayed_nav
+ (get_character_navigator model target_char)
+ model.ui
+ )
+ )
+ }
+
+can_target_character : (
+ Struct.Model.Type ->
+ Struct.Character.Type ->
+ Bool
+ )
+can_target_character model target =
+ (
+ (Struct.CharacterTurn.can_select_target model.char_turn)
+ && (Struct.Character.is_alive target)
+ &&
+ (
+ case
+ (Struct.CharacterTurn.try_getting_navigator
+ model.char_turn
+ )
+ of
+ (Just nav) ->
+ case
+ (Struct.Navigator.try_getting_path_to
+ (Struct.Location.get_ref
+ (Struct.Character.get_location target)
+ )
+ nav
+ )
+ of
+ (Just _) -> True
+ _ -> False
+
+ _ ->
+ False
+ )
+ )
+
+second_click_on : (
+ Struct.Model.Type ->
+ Int ->
+ (Struct.Model.Type, (Cmd Struct.Event.Type))
+ )
+second_click_on model target_char_id =
+ case (Array.get target_char_id model.characters) of
+ (Just target_char) ->
+ case
+ (
+ (Struct.CharacterTurn.try_getting_active_character
+ model.char_turn
+ ),
+ (Struct.CharacterTurn.try_getting_target model.char_turn)
+ )
+ of
+ ((Just _), (Just char_turn_target_id)) ->
+ if (char_turn_target_id == target_char_id)
+ then
+ (
+ model,
+ Cmd.none
+ )
+ else
+ (
+ (ctrl_or_focus_character model target_char_id target_char),
+ (Task.attempt
+ (Struct.Event.attempted)
+ (Action.Scroll.to
+ (Struct.Character.get_location target_char)
+ model.ui
+ )
+ )
+ )
+
+ ((Just _), Nothing) ->
+ if (can_target_character model target_char)
+ then
+ (
+ (attack_character
+ model
+ target_char_id
+ target_char
+ ),
+ Cmd.none
+ )
+ else
+ (
+ (ctrl_or_focus_character model target_char_id target_char),
+ (Task.attempt
+ (Struct.Event.attempted)
+ (Action.Scroll.to
+ (Struct.Character.get_location target_char)
+ model.ui
+ )
+ )
+ )
+
+ (_, _) ->
+ (
+ (ctrl_or_focus_character model target_char_id target_char),
+ (Task.attempt
+ (Struct.Event.attempted)
+ (Action.Scroll.to
+ (Struct.Character.get_location target_char)
+ model.ui
+ )
+ )
+ )
+
+ Nothing ->
+ (
+ (Struct.Model.invalidate
+ (Struct.Error.new
+ Struct.Error.Programming
+ "SelectCharacter: Unknown char selected."
+ )
+ model
+ ),
+ Cmd.none
+ )
+
+first_click_on : (
+ Struct.Model.Type ->
+ Int ->
+ (Struct.Model.Type, (Cmd Struct.Event.Type))
+ )
+first_click_on model target_char_id =
+ if
+ (
+ (Struct.CharacterTurn.try_getting_target model.char_turn)
+ ==
+ (Just target_char_id)
+ )
+ then
+ (model, Cmd.none)
+ else
+ case (Array.get target_char_id model.characters) of
+ (Just target_char) ->
+ (
+ {model |
+ ui =
+ (Struct.UI.set_previous_action
+ (Just (Struct.UI.SelectedCharacter target_char_id))
+ (Struct.UI.set_displayed_tab
+ Struct.UI.StatusTab
+ (Struct.UI.set_displayed_nav
+ (get_character_navigator model target_char)
+ model.ui
+ )
+ )
+ )
+ },
+ Cmd.none
+ )
+
+ Nothing ->
+ (
+ (Struct.Model.invalidate
+ (Struct.Error.new
+ Struct.Error.Programming
+ "SelectCharacter: Unknown char selected."
+ )
+ model
+ ),
+ Cmd.none
+ )
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+apply_to : (
+ Struct.Model.Type ->
+ Int ->
+ (Struct.Model.Type, (Cmd Struct.Event.Type))
+ )
+apply_to model target_char_id =
+ if
+ (
+ (Struct.UI.get_previous_action model.ui)
+ ==
+ (Just (Struct.UI.SelectedCharacter target_char_id))
+ )
+ then
+ (second_click_on model target_char_id)
+ else
+ (first_click_on model target_char_id)
diff --git a/src/roster-editor/src/Update/SelectTab.elm b/src/roster-editor/src/Update/SelectTab.elm
new file mode 100644
index 0000000..d15a463
--- /dev/null
+++ b/src/roster-editor/src/Update/SelectTab.elm
@@ -0,0 +1,32 @@
+module Update.SelectTab exposing (apply_to)
+-- Elm -------------------------------------------------------------------------
+
+-- Map -------------------------------------------------------------------
+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/roster-editor/src/Update/SendLoadRosterRequest.elm b/src/roster-editor/src/Update/SendLoadRosterRequest.elm
new file mode 100644
index 0000000..2bbe9da
--- /dev/null
+++ b/src/roster-editor/src/Update/SendLoadRosterRequest.elm
@@ -0,0 +1,26 @@
+module Update.SendLoadRosterRequest exposing (apply_to)
+-- Elm -------------------------------------------------------------------------
+
+-- Roster Editor ---------------------------------------------------------------
+import Comm.LoadRoster
+
+import Struct.Event
+import Struct.Model
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+apply_to : Struct.Model.Type -> (Struct.Model.Type, (Cmd Struct.Event.Type))
+apply_to model =
+ (
+ model,
+ (case (Comm.LoadRoster.try model) of
+ (Just cmd) -> cmd
+ Nothing -> Cmd.none
+ )
+ )
+
diff --git a/src/roster-editor/src/Update/SetRequestedHelp.elm b/src/roster-editor/src/Update/SetRequestedHelp.elm
new file mode 100644
index 0000000..dfc58db
--- /dev/null
+++ b/src/roster-editor/src/Update/SetRequestedHelp.elm
@@ -0,0 +1,22 @@
+module Update.SetRequestedHelp exposing (apply_to)
+-- Elm -------------------------------------------------------------------------
+
+-- Map -------------------------------------------------------------------
+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/roster-editor/src/View/Character.elm b/src/roster-editor/src/View/Character.elm
new file mode 100644
index 0000000..d33feb1
--- /dev/null
+++ b/src/roster-editor/src/View/Character.elm
@@ -0,0 +1,230 @@
+module View.Character exposing
+ (
+ get_portrait_html,
+ get_icon_html
+ )
+
+-- Elm -------------------------------------------------------------------------
+import Html
+import Html.Attributes
+import Html.Events
+
+-- Map ------------------------------------------------------------------
+import Constants.UI
+
+import Util.Html
+
+import Struct.Armor
+import Struct.Character
+import Struct.CharacterTurn
+import Struct.Event
+import Struct.Model
+import Struct.UI
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+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 "battle-character-icon-enabled")
+ else
+ (Html.Attributes.class "battle-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 "battle-character-ally")
+ else
+ (Html.Attributes.class "battle-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 "battle-character-selected")
+ else
+ if
+ (
+ (Struct.CharacterTurn.try_getting_target model.char_turn)
+ ==
+ (Just (Struct.Character.get_index char))
+ )
+ then
+ (Html.Attributes.class "battle-character-targeted")
+ else
+ (Html.Attributes.class "")
+
+get_icon_body_html : Struct.Character.Type -> (Html.Html Struct.Event.Type)
+get_icon_body_html char =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-character-icon-body"),
+ (Html.Attributes.class
+ (
+ "asset-character-team-body-"
+ ++ (toString (Struct.Character.get_player_ix char))
+ )
+ )
+ ]
+ [
+ ]
+ )
+
+get_icon_head_html : Struct.Character.Type -> (Html.Html Struct.Event.Type)
+get_icon_head_html char =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-character-icon-head"),
+ (Html.Attributes.class
+ ("asset-character-icon-" ++ (Struct.Character.get_icon_id char))
+ )
+ ]
+ [
+ ]
+ )
+
+get_icon_actual_html : (
+ Struct.Model.Type ->
+ Struct.Character.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_icon_actual_html model char =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-tiled"),
+ (Html.Attributes.class "battle-character-icon"),
+ (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_icon_body_html char),
+ (get_icon_head_html char)
+ ]
+ )
+
+get_portrait_body_html : Struct.Character.Type -> (Html.Html Struct.Event.Type)
+get_portrait_body_html char =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-character-portrait-body"),
+ (Html.Attributes.class
+ (
+ "asset-character-portrait-"
+ ++ (Struct.Character.get_portrait_id char)
+ )
+ )
+ ]
+ [
+ ]
+ )
+
+get_portrait_armor_html : Struct.Character.Type -> (Html.Html Struct.Event.Type)
+get_portrait_armor_html char =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-character-portrait-armor"),
+ (Html.Attributes.class
+ (
+ "asset-armor-"
+ ++
+ (Struct.Armor.get_image_id (Struct.Character.get_armor char))
+ )
+ ),
+ (Html.Attributes.class
+ (
+ "asset-armor-variation-"
+ ++ (Struct.Character.get_armor_variation char)
+ )
+ )
+ ]
+ [
+ ]
+ )
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_portrait_html : (
+ Int ->
+ Struct.Character.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_portrait_html viewer_ix char =
+ (Html.div
+ [
+ (Html.Attributes.class
+ (
+ if ((Struct.Character.get_player_ix char) == viewer_ix)
+ then
+ "battle-character-ally"
+ else
+ "battle-character-enemy"
+ )
+ ),
+ (Html.Attributes.class "battle-character-portrait"),
+ (Html.Attributes.class
+ (
+ "battle-character-portrait-team-"
+ ++
+ (toString (Struct.Character.get_player_ix char))
+ )
+ ),
+ (Html.Events.onClick
+ (Struct.Event.LookingForCharacter (Struct.Character.get_index char))
+ )
+ ]
+ [
+ (get_portrait_body_html char),
+ (get_portrait_armor_html char)
+ ]
+ )
+
+get_icon_html : (
+ Struct.Model.Type ->
+ Struct.Character.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_icon_html model char =
+ if (Struct.Character.is_alive char)
+ then
+ (get_icon_actual_html model char)
+ else
+ (Util.Html.nothing)
diff --git a/src/roster-editor/src/View/CharacterIcon.elm b/src/roster-editor/src/View/CharacterIcon.elm
new file mode 100644
index 0000000..aaf7cb2
--- /dev/null
+++ b/src/roster-editor/src/View/CharacterIcon.elm
@@ -0,0 +1,218 @@
+module View.Map.Character exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Html
+import Html.Attributes
+import Html.Events
+
+-- Map ------------------------------------------------------------------
+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 "battle-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
+ "battle-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 "battle-character-icon-enabled")
+ else
+ (Html.Attributes.class "battle-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 "battle-character-ally")
+ else
+ (Html.Attributes.class "battle-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 "battle-character-selected")
+ else
+ if
+ (
+ (Struct.CharacterTurn.try_getting_target model.char_turn)
+ ==
+ (Just (Struct.Character.get_index char))
+ )
+ then
+ (Html.Attributes.class "battle-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 "battle-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 "battle-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 "battle-character-icon-banner"),
+ (Html.Attributes.class "asset-character-icon-commander-banner")
+ ]
+ [
+ ]
+ )
+
+ Struct.Character.Target ->
+ (Html.div
+ [
+ (Html.Attributes.class "battle-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 "battle-tiled"),
+ (Html.Attributes.class "battle-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/roster-editor/src/View/Controlled.elm b/src/roster-editor/src/View/Controlled.elm
new file mode 100644
index 0000000..d0c33a5
--- /dev/null
+++ b/src/roster-editor/src/View/Controlled.elm
@@ -0,0 +1,158 @@
+module View.Controlled exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Html
+import Html.Attributes
+import Html.Events
+
+-- Struct.Map -------------------------------------------------------------------
+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") ]
+ )
+
+undo_button : (Html.Html Struct.Event.Type)
+undo_button =
+ (Html.button
+ [ (Html.Events.onClick Struct.Event.UndoActionRequest) ]
+ [ (Html.text "Undo") ]
+ )
+
+end_turn_button : String -> (Html.Html Struct.Event.Type)
+end_turn_button suffix =
+ (Html.button
+ [
+ (Html.Events.onClick Struct.Event.TurnEnded),
+ (Html.Attributes.class "battle-end-turn-button")
+ ]
+ [ (Html.text ("End Turn" ++ suffix)) ]
+ )
+
+inventory_button : Bool -> (Html.Html Struct.Event.Type)
+inventory_button go_prefix =
+ (Html.button
+ [ (Html.Events.onClick Struct.Event.WeaponSwitchRequest) ]
+ [
+ (Html.text
+ (
+ if (go_prefix)
+ then ("Go & Switch Weapon")
+ else ("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 (has_a_path char_turn)),
+ (end_turn_button " Doing Nothing"),
+ (abort_button)
+ ]
+
+ Struct.CharacterTurn.MovedCharacter ->
+ [
+ (inventory_button False),
+ (end_turn_button " by Moving"),
+ (undo_button),
+ (abort_button)
+ ]
+
+ Struct.CharacterTurn.ChoseTarget ->
+ [
+ (end_turn_button " by Attacking"),
+ (undo_button),
+ (abort_button)
+ ]
+
+ Struct.CharacterTurn.SwitchedWeapons ->
+ [
+ (end_turn_button " by Switching Weapons"),
+ (undo_button),
+ (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 "battle-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 "battle-controlled-actions")]
+ (get_available_actions char_turn)
+ )
+ ]
+ )
+
+ Nothing -> (Util.Html.nothing)
diff --git a/src/roster-editor/src/View/Controlled/CharacterCard.elm b/src/roster-editor/src/View/Controlled/CharacterCard.elm
new file mode 100644
index 0000000..ac56cbb
--- /dev/null
+++ b/src/roster-editor/src/View/Controlled/CharacterCard.elm
@@ -0,0 +1,540 @@
+module View.Controlled.CharacterCard exposing
+ (
+ get_minimal_html,
+ get_summary_html,
+ get_full_html
+ )
+
+-- Elm -------------------------------------------------------------------------
+import List
+
+import Html
+import Html.Attributes
+import Html.Events
+
+-- Battle ----------------------------------------------------------------------
+import Struct.Armor
+import Struct.Character
+import Struct.CharacterTurn
+import Struct.Event
+import Struct.HelpRequest
+import Struct.Navigator
+import Struct.Omnimods
+import Struct.Statistics
+import Struct.Weapon
+import Struct.WeaponSet
+
+import Util.Html
+
+import View.Character
+import View.Gauge
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_name : (
+ Struct.Character.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_name char =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-info-card-name"),
+ (Html.Attributes.class "battle-info-card-text-field"),
+ (Html.Attributes.class "battle-character-card-name")
+ ]
+ [
+ (Html.text (Struct.Character.get_name char))
+ ]
+ )
+
+get_health_bar : (
+ Struct.Character.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_health_bar char =
+ let
+ current = (Struct.Character.get_sane_current_health char)
+ max =
+ (Struct.Statistics.get_max_health
+ (Struct.Character.get_statistics char)
+ )
+ in
+ (View.Gauge.get_html
+ ("HP: " ++ (toString current) ++ "/" ++ (toString max))
+ (100.0 * ((toFloat current)/(toFloat max)))
+ [(Html.Attributes.class "battle-character-card-health")]
+ []
+ []
+ )
+
+get_rank_status : (
+ Struct.Character.Rank ->
+ (Html.Html Struct.Event.Type)
+ )
+get_rank_status rank =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-character-card-status"),
+ (Html.Attributes.class "clickable"),
+ (Html.Events.onClick
+ (Struct.Event.RequestedHelp (Struct.HelpRequest.HelpOnRank rank))
+ ),
+ (Html.Attributes.class
+ (
+ case rank of
+ Struct.Character.Commander ->
+ "battle-character-card-commander-status"
+
+ Struct.Character.Target ->
+ "battle-character-card-target-status"
+
+ Struct.Character.Optional -> ""
+ )
+ )
+ ]
+ [
+ ]
+ )
+
+get_statuses : (
+ Struct.Character.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_statuses char =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-character-card-statuses")
+ ]
+ [
+ (
+ case (Struct.Character.get_rank char) of
+ Struct.Character.Optional -> (Util.Html.nothing)
+ other -> (get_rank_status other)
+ )
+ ]
+ )
+
+get_active_movement_bar : (
+ (Maybe Struct.Navigator.Type) ->
+ Struct.Character.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_active_movement_bar maybe_navigator char =
+ let
+ max =
+ (Struct.Statistics.get_movement_points
+ (Struct.Character.get_statistics char)
+ )
+ current =
+ case maybe_navigator of
+ (Just navigator) ->
+ (Struct.Navigator.get_remaining_points navigator)
+
+ Nothing ->
+ max
+ in
+ (View.Gauge.get_html
+ ("MP: " ++ (toString current) ++ "/" ++ (toString max))
+ (100.0 * ((toFloat current)/(toFloat max)))
+ [(Html.Attributes.class "battle-character-card-movement")]
+ []
+ []
+ )
+
+get_inactive_movement_bar : (
+ Struct.Character.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_inactive_movement_bar char =
+ let
+ max =
+ (Struct.Statistics.get_movement_points
+ (Struct.Character.get_statistics char)
+ )
+ in
+ (View.Gauge.get_html
+ (
+ "MP: "
+ ++
+ (toString
+ (Struct.Statistics.get_movement_points
+ (Struct.Character.get_statistics char)
+ )
+ )
+ )
+ 100.0
+ [(Html.Attributes.class "battle-character-card-movement")]
+ []
+ []
+ )
+
+get_movement_bar : (
+ Struct.CharacterTurn.Type ->
+ Struct.Character.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_movement_bar char_turn char =
+ case (Struct.CharacterTurn.try_getting_active_character char_turn) of
+ (Just active_char) ->
+ if
+ (
+ (Struct.Character.get_index active_char)
+ ==
+ (Struct.Character.get_index char)
+ )
+ then
+ (get_active_movement_bar
+ (Struct.CharacterTurn.try_getting_navigator char_turn)
+ active_char
+ )
+ else
+ (get_inactive_movement_bar char)
+
+ Nothing ->
+ (get_inactive_movement_bar char)
+
+get_weapon_field_header : (
+ Float ->
+ Struct.Weapon.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_weapon_field_header damage_multiplier weapon =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-character-card-header")
+ ]
+ [
+ (Html.div
+ [
+ ]
+ [
+ (Html.text (Struct.Weapon.get_name weapon))
+ ]
+ ),
+ (Html.div
+ [
+ ]
+ [
+ (Html.text
+ (
+ "~"
+ ++
+ (toString
+ (ceiling
+ (
+ (toFloat (Struct.Weapon.get_damage_sum weapon))
+ * damage_multiplier
+ )
+ )
+ )
+ ++ " dmg @ ["
+ ++ (toString (Struct.Weapon.get_defense_range weapon))
+ ++ ", "
+ ++ (toString (Struct.Weapon.get_attack_range weapon))
+ ++ "]"
+ )
+ )
+ ]
+ )
+ ]
+ )
+
+get_mod_html : (String, Int) -> (Html.Html Struct.Event.Type)
+get_mod_html mod =
+ let
+ (category, value) = mod
+ in
+ (Html.div
+ [
+ (Html.Attributes.class "battle-info-card-mod")
+ ]
+ [
+ (Html.text
+ (category ++ ": " ++ (toString value))
+ )
+ ]
+ )
+
+get_multiplied_mod_html : Float -> (String, Int) -> (Html.Html Struct.Event.Type)
+get_multiplied_mod_html multiplier mod =
+ let
+ (category, value) = mod
+ in
+ (Html.div
+ [
+ (Html.Attributes.class "battle-character-card-mod")
+ ]
+ [
+ (Html.text
+ (
+ category
+ ++ ": "
+ ++ (toString (ceiling ((toFloat value) * multiplier)))
+ )
+ )
+ ]
+ )
+
+get_weapon_details : (
+ Struct.Omnimods.Type ->
+ Float ->
+ Struct.Weapon.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_weapon_details omnimods damage_multiplier weapon =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-character-card-weapon")
+ ]
+ [
+ (get_weapon_field_header damage_multiplier weapon),
+ (Html.div
+ [
+ (Html.Attributes.class "battle-info-card-omnimods-listing")
+ ]
+ (List.map
+ (get_multiplied_mod_html damage_multiplier)
+ (Struct.Omnimods.get_attack_mods omnimods)
+ )
+ )
+ ]
+ )
+
+get_weapon_summary : (
+ Float ->
+ Struct.Weapon.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_weapon_summary damage_multiplier weapon =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-character-card-weapon-summary")
+ ]
+ [
+ (get_weapon_field_header damage_multiplier weapon)
+ ]
+ )
+
+get_armor_details : (
+ Struct.Omnimods.Type ->
+ Struct.Armor.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_armor_details omnimods armor =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-character-card-armor")
+ ]
+ [
+ (Html.div
+ [
+ (Html.Attributes.class "battle-character-card-armor-name")
+ ]
+ [
+ (Html.text (Struct.Armor.get_name armor))
+ ]
+ ),
+ (Html.div
+ [
+ (Html.Attributes.class "battle-info-card-omnimods-listing")
+ ]
+ (List.map
+ (get_mod_html)
+ (Struct.Omnimods.get_defense_mods omnimods)
+ )
+ )
+ ]
+ )
+
+stat_name : String -> (Html.Html Struct.Event.Type)
+stat_name name =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-character-card-stat-name")
+ ]
+ [
+ (Html.text name)
+ ]
+ )
+
+stat_val : Int -> Bool -> (Html.Html Struct.Event.Type)
+stat_val val perc =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-character-card-stat-val")
+ ]
+ [
+ (Html.text
+ (
+ (toString val)
+ ++
+ (
+ if perc
+ then
+ "%"
+ else
+ ""
+ )
+ )
+ )
+ ]
+ )
+
+get_relevant_stats : (
+ Struct.Statistics.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_relevant_stats stats =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-character-card-stats")
+ ]
+ [
+ (stat_name "Dodge"),
+ (stat_val (Struct.Statistics.get_dodges stats) True),
+ (stat_name "Parry"),
+ (stat_val (Struct.Statistics.get_parries stats) True),
+ (stat_name "Accu."),
+ (stat_val (Struct.Statistics.get_accuracy stats) False),
+ (stat_name "2xHit"),
+ (stat_val (Struct.Statistics.get_double_hits stats) True),
+ (stat_name "Crit."),
+ (stat_val (Struct.Statistics.get_critical_hits stats) True)
+ ]
+ )
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_minimal_html : (
+ Int ->
+ Struct.Character.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_minimal_html player_ix char =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-info-card"),
+ (Html.Attributes.class "battle-info-card-minimal"),
+ (Html.Attributes.class "battle-character-card"),
+ (Html.Attributes.class "battle-character-card-minimal")
+ ]
+ [
+ (get_name char),
+ (Html.div
+ [
+ (Html.Attributes.class "battle-info-card-top"),
+ (Html.Attributes.class "battle-character-card-top")
+ ]
+ [
+ (Html.div
+ [
+ (Html.Attributes.class "battle-info-card-picture")
+ ]
+ [
+ (View.Character.get_portrait_html player_ix char)
+ ]
+ ),
+ (get_health_bar char),
+ (get_inactive_movement_bar char),
+ (get_statuses char)
+ ]
+ )
+ ]
+ )
+
+get_summary_html : (
+ Struct.CharacterTurn.Type ->
+ Int ->
+ Struct.Character.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_summary_html char_turn player_ix char =
+ let
+ weapon_set = (Struct.Character.get_weapons char)
+ main_weapon = (Struct.WeaponSet.get_active_weapon weapon_set)
+ char_statistics = (Struct.Character.get_statistics char)
+ damage_modifier = (Struct.Statistics.get_damage_modifier char_statistics)
+ secondary_weapon = (Struct.WeaponSet.get_secondary_weapon weapon_set)
+ omnimods = (Struct.Character.get_current_omnimods char)
+ in
+ (Html.div
+ [
+ (Html.Attributes.class "battle-character-card")
+ ]
+ [
+ (get_name char),
+ (Html.div
+ [
+ (Html.Attributes.class "battle-info-card-top"),
+ (Html.Attributes.class "battle-character-card-top")
+ ]
+ [
+ (Html.div
+ [
+ (Html.Attributes.class "battle-info-card-picture")
+ ]
+ [
+ (View.Character.get_portrait_html player_ix char)
+ ]
+ ),
+ (get_health_bar char),
+ (get_movement_bar char_turn char),
+ (get_statuses char)
+ ]
+ ),
+ (get_weapon_details omnimods damage_modifier main_weapon),
+ (get_armor_details omnimods (Struct.Character.get_armor char)),
+ (get_relevant_stats char_statistics),
+ (get_weapon_summary damage_modifier secondary_weapon)
+ ]
+ )
+
+get_full_html : (
+ Int ->
+ Struct.Character.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_full_html player_ix char =
+ let
+ weapon_set = (Struct.Character.get_weapons char)
+ main_weapon = (Struct.WeaponSet.get_active_weapon weapon_set)
+ char_statistics = (Struct.Character.get_statistics char)
+ damage_modifier = (Struct.Statistics.get_damage_modifier char_statistics)
+ secondary_weapon = (Struct.WeaponSet.get_secondary_weapon weapon_set)
+ armor = (Struct.Character.get_armor char)
+ omnimods = (Struct.Character.get_current_omnimods char)
+ in
+ (Html.div
+ [
+ (Html.Attributes.class "battle-info-card"),
+ (Html.Attributes.class "battle-character-card")
+ ]
+ [
+ (get_name char),
+ (Html.div
+ [
+ (Html.Attributes.class "battle-info-card-top"),
+ (Html.Attributes.class "battle-character-card-top")
+ ]
+ [
+ (Html.div
+ [
+ (Html.Attributes.class "battle-info-card-picture")
+ ]
+ [
+ (View.Character.get_portrait_html player_ix char)
+ ]
+ ),
+ (get_health_bar char),
+ (get_inactive_movement_bar char),
+ (get_statuses char)
+ ]
+ ),
+ (get_weapon_details omnimods damage_modifier main_weapon),
+ (get_armor_details omnimods armor),
+ (get_relevant_stats char_statistics),
+ (get_weapon_summary damage_modifier secondary_weapon)
+ ]
+ )
diff --git a/src/roster-editor/src/View/Controlled/ManualControls.elm b/src/roster-editor/src/View/Controlled/ManualControls.elm
new file mode 100644
index 0000000..1dceafb
--- /dev/null
+++ b/src/roster-editor/src/View/Controlled/ManualControls.elm
@@ -0,0 +1,60 @@
+module View.Controlled.ManualControls exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Html
+import Html.Attributes
+import Html.Events
+
+-- Map -------------------------------------------------------------------
+import Struct.Direction
+import Struct.Event
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+direction_button : (
+ Struct.Direction.Type ->
+ String ->
+ (Html.Html Struct.Event.Type)
+ )
+direction_button dir label =
+ (Html.div
+ [
+ (Html.Attributes.class ("battle-manual-controls-" ++ label)),
+ (Html.Attributes.class "clickable"),
+ (Html.Events.onClick
+ (Struct.Event.DirectionRequested dir)
+ )
+ ]
+ []
+ )
+
+go_button : (Html.Html Struct.Event.Type)
+go_button =
+ (Html.button
+ [
+ (Html.Attributes.class "battle-manual-controls-go"),
+ (Html.Events.onClick Struct.Event.AttackWithoutMovingRequest)
+ ]
+ [
+ (Html.text "Go")
+ ]
+ )
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_html : (Html.Html Struct.Event.Type)
+get_html =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-manual-controls")
+ ]
+ [
+ (direction_button Struct.Direction.Left "left"),
+ (direction_button Struct.Direction.Down "down"),
+ (direction_button Struct.Direction.Up "up"),
+ (direction_button Struct.Direction.Right "right"),
+ (go_button)
+ ]
+ )
diff --git a/src/roster-editor/src/View/Controlled/Targets.elm b/src/roster-editor/src/View/Controlled/Targets.elm
new file mode 100644
index 0000000..eee5a54
--- /dev/null
+++ b/src/roster-editor/src/View/Controlled/Targets.elm
@@ -0,0 +1,69 @@
+module View.SideBar.Targets exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Dict
+
+import Html
+import Html.Attributes
+
+-- Map -------------------------------------------------------------------
+import Struct.Character
+import Struct.Event
+import Struct.Model
+import Struct.Statistics
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+get_target_info_html : (
+ Struct.Model.Type ->
+ Struct.Character.Ref ->
+ (Html.Html Struct.Event.Type)
+ )
+get_target_info_html model char_ref =
+ case (Dict.get char_ref model.characters) of
+ Nothing -> (Html.text "Error: Unknown character selected.")
+ (Just char) ->
+ (Html.text
+ (
+ "Attacking "
+ ++ char.name
+ ++ " (player "
+ ++ (toString (Struct.Character.get_player_ix char))
+ ++ "): "
+ ++
+ (toString
+ (Struct.Statistics.get_movement_points
+ (Struct.Character.get_statistics char)
+ )
+ )
+ ++ " movement points; "
+ ++ "???"
+ ++ " attack range. Health: "
+ ++ (toString (Struct.Character.get_sane_current_health char))
+ ++ "/"
+ ++
+ (toString
+ (Struct.Statistics.get_max_health
+ (Struct.Character.get_statistics char)
+ )
+ )
+ )
+ )
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_html : (
+ Struct.Model.Type ->
+ Struct.Character.Ref ->
+ (Html.Html Struct.Event.Type)
+ )
+get_html model target_ref =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-side-bar-targets")
+ ]
+ [(get_target_info_html model target_ref)]
+ )
diff --git a/src/roster-editor/src/View/CurrentTab.elm b/src/roster-editor/src/View/CurrentTab.elm
new file mode 100644
index 0000000..8a062a9
--- /dev/null
+++ b/src/roster-editor/src/View/CurrentTab.elm
@@ -0,0 +1,40 @@
+module View.CurrentTab exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Html
+
+-- Roster Editor ---------------------------------------------------------------
+import Struct.Event
+import Struct.Model
+import Struct.UI
+
+import View.CharacterSelection
+import View.PortraitSelection
+import View.WeaponSelection
+import View.ArmorSelection
+import View.GlyphManagement
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_html : Struct.Model.Type -> (Html.Html Struct.Event.Type)
+get_html model =
+ case (Struct.UI.get_displayed_tab model.ui) of
+ Struct.UI.CharacterSelectionTab ->
+ (View.CharacterSelection.get_html model)
+
+ Struct.UI.PortraitSelectionTab ->
+ (View.PortraitSelection.get_html model)
+
+ Struct.UI.WeaponSelectionTab ->
+ (View.WeaponSelection.get_html model)
+
+ Struct.UI.ArmorSelectionTab ->
+ (View.ArmorSelection.get_html model)
+
+ Struct.UI.GlyphManagementTab ->
+ (View.GlyphManagement.get_html model)
diff --git a/src/roster-editor/src/View/Gauge.elm b/src/roster-editor/src/View/Gauge.elm
new file mode 100644
index 0000000..cf89f3a
--- /dev/null
+++ b/src/roster-editor/src/View/Gauge.elm
@@ -0,0 +1,76 @@
+module View.Gauge exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Html
+import Html.Attributes
+
+-- Map -------------------------------------------------------------------
+import Struct.Event
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_text_div: (
+ String ->
+ List (Html.Attribute Struct.Event.Type) ->
+ (Html.Html Struct.Event.Type)
+ )
+get_text_div text extra_txt_attr =
+ (Html.div
+ (
+ [(Html.Attributes.class "battle-gauge-text")]
+ ++ extra_txt_attr
+ )
+ [
+ (Html.text text)
+ ]
+ )
+
+get_bar_div: (
+ Float ->
+ List (Html.Attribute Struct.Event.Type) ->
+ (Html.Html Struct.Event.Type)
+ )
+get_bar_div percent extra_bar_attr =
+ (Html.div
+ (
+ [
+ (Html.Attributes.style
+ [
+ ("width", ((toString percent) ++ "%"))
+ ]
+ ),
+ (Html.Attributes.class
+ "battle-gauge-bar"
+ )
+ ]
+ ++
+ extra_bar_attr
+ )
+ [
+ ]
+ )
+
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_html : (
+ String ->
+ Float ->
+ List (Html.Attribute Struct.Event.Type) ->
+ List (Html.Attribute Struct.Event.Type) ->
+ List (Html.Attribute Struct.Event.Type) ->
+ (Html.Html Struct.Event.Type)
+ )
+get_html text percent extra_div_attr extra_bar_attr extra_txt_attr =
+ (Html.div
+ (
+ [(Html.Attributes.class "battle-gauge")]
+ ++ extra_div_attr
+ )
+ [
+ (get_text_div text extra_txt_attr),
+ (get_bar_div percent extra_bar_attr)
+ ]
+ )
diff --git a/src/roster-editor/src/View/MainMenu.elm b/src/roster-editor/src/View/MainMenu.elm
new file mode 100644
index 0000000..96bf539
--- /dev/null
+++ b/src/roster-editor/src/View/MainMenu.elm
@@ -0,0 +1,46 @@
+module View.MainMenu exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Html
+import Html.Attributes
+import Html.Events
+
+-- Map -------------------------------------------------------------------
+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)) ]
+ )
+
+get_main_menu_button_html : (Html.Html Struct.Event.Type)
+get_main_menu_button_html =
+ (Html.button
+ [ (Html.Events.onClick Struct.Event.GoToMainMenu) ]
+ [ (Html.text "Main Menu") ]
+ )
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_html : (Html.Html Struct.Event.Type)
+get_html =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-main-menu")
+ ]
+ (
+ (get_main_menu_button_html)
+ ::
+ (List.map
+ (get_menu_button_html)
+ (Struct.UI.get_all_tabs)
+ )
+ )
+ )
diff --git a/src/roster-editor/src/View/MessageBoard.elm b/src/roster-editor/src/View/MessageBoard.elm
new file mode 100644
index 0000000..736f938
--- /dev/null
+++ b/src/roster-editor/src/View/MessageBoard.elm
@@ -0,0 +1,30 @@
+module View.MessageBoard exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Html
+
+-- Struct.Map -------------------------------------------------------------------
+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/roster-editor/src/View/MessageBoard/Animator.elm b/src/roster-editor/src/View/MessageBoard/Animator.elm
new file mode 100644
index 0000000..49bb83a
--- /dev/null
+++ b/src/roster-editor/src/View/MessageBoard/Animator.elm
@@ -0,0 +1,57 @@
+module View.MessageBoard.Animator exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Html
+
+-- Map -------------------------------------------------------------------
+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/roster-editor/src/View/MessageBoard/Animator/Attack.elm b/src/roster-editor/src/View/MessageBoard/Animator/Attack.elm
new file mode 100644
index 0000000..437a76d
--- /dev/null
+++ b/src/roster-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
+
+-- Map -------------------------------------------------------------------
+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 "battle-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 "battle-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
+ "battle-animated-portrait-attack-critical"
+ else
+ "battle-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
+ "battle-animated-portrait-dodges"
+ else
+ "battle-animated-portrait-undamaged"
+ else if ((Struct.Character.get_current_health char) > 0)
+ then
+ if (attack.precision == Struct.Attack.Graze)
+ then
+ "battle-animated-portrait-grazed-damage"
+ else
+ "battle-animated-portrait-damaged"
+ else
+ if (attack.precision == Struct.Attack.Graze)
+ then
+ "battle-animated-portrait-grazed-death"
+ else
+ "battle-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 "battle-animated-portrait")
+ ]
+ else
+ [
+ (Html.Attributes.class "battle-animated-portrait-absent"),
+ (Html.Attributes.class "battle-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 "battle-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 "battle-animated-portrait")
+ ]
+ else
+ [
+ (Html.Attributes.class "battle-animated-portrait-absent"),
+ (Html.Attributes.class "battle-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 "battle-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 "battle-message-board"),
+ (Html.Attributes.class "battle-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/roster-editor/src/View/MessageBoard/Error.elm b/src/roster-editor/src/View/MessageBoard/Error.elm
new file mode 100644
index 0000000..797d89f
--- /dev/null
+++ b/src/roster-editor/src/View/MessageBoard/Error.elm
@@ -0,0 +1,33 @@
+module View.MessageBoard.Error exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Html
+import Html.Attributes
+
+-- Map -------------------------------------------------------------------
+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 "battle-message-board"),
+ (Html.Attributes.class "battle-error")
+ ]
+ [
+ (Html.text (Struct.Error.to_string error))
+ ]
+ )
diff --git a/src/roster-editor/src/View/MessageBoard/Help.elm b/src/roster-editor/src/View/MessageBoard/Help.elm
new file mode 100644
index 0000000..6c20bbc
--- /dev/null
+++ b/src/roster-editor/src/View/MessageBoard/Help.elm
@@ -0,0 +1,37 @@
+module View.MessageBoard.Help exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Html
+import Html.Attributes
+
+-- Map -------------------------------------------------------------------
+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 "battle-message-board"),
+ (Html.Attributes.class "battle-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/roster-editor/src/View/MessageBoard/Help/Guide.elm b/src/roster-editor/src/View/MessageBoard/Help/Guide.elm
new file mode 100644
index 0000000..7268c12
--- /dev/null
+++ b/src/roster-editor/src/View/MessageBoard/Help/Guide.elm
@@ -0,0 +1,119 @@
+module View.MessageBoard.Help.Guide exposing (get_html_contents)
+
+-- Elm -------------------------------------------------------------------------
+import Html
+import Html.Attributes
+
+-- Map -------------------------------------------------------------------
+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 "battle-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 an Action"),
+ (Html.text
+ (
+ """You can now choose an action for this character. Either attack
+ a target in range by clicking twice on it, or switch weapons by using the menu
+ on the left. Dashes indicate tiles this character will be unable to defend
+ from. Crossed shields indicate the equivalent for the current selection."""
+ )
+ )
+ ]
+
+get_chose_target_html_contents : (List (Html.Html Struct.Event.Type))
+get_chose_target_html_contents =
+ [
+ (get_header_html "End the Turn by an Attack"),
+ (Html.text
+ (
+ """A target for the attack has been selected. If you are satisfied
+with your choices, you can end this character's turn and see the results unfold.
+Otherwise, click on the "Undo" button to change the action, or the "Abort"
+button to start this turn over."""
+ )
+ )
+ ]
+
+get_switched_weapons_html_contents : (List (Html.Html Struct.Event.Type))
+get_switched_weapons_html_contents =
+ [
+ (get_header_html "End the Turn by Switching Weapons"),
+ (Html.text
+ (
+ """The character will switch weapons. If you are satisfied
+with your choices, you can end this character's turn and see the results unfold.
+Otherwise, click on the "Undo" button to change the action, or the "Abort"
+button to start this turn over."""
+ )
+ )
+ ]
+
+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)
+
+ Struct.CharacterTurn.SwitchedWeapons ->
+ (get_switched_weapons_html_contents)
+
+ _ ->
+ (get_default_html_contents)
diff --git a/src/roster-editor/src/View/MessageBoard/Help/Rank.elm b/src/roster-editor/src/View/MessageBoard/Help/Rank.elm
new file mode 100644
index 0000000..4a01e75
--- /dev/null
+++ b/src/roster-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
+
+-- Map -------------------------------------------------------------------
+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 "battle-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
+ "battle-message-board-help-figure"
+ ),
+ (Html.Attributes.class
+ ("battle-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/roster-editor/src/View/SubMenu.elm b/src/roster-editor/src/View/SubMenu.elm
new file mode 100644
index 0000000..e661b9c
--- /dev/null
+++ b/src/roster-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
+
+-- Map -------------------------------------------------------------------
+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 "battle-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 "battle-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/roster-editor/src/View/SubMenu/Characters.elm b/src/roster-editor/src/View/SubMenu/Characters.elm
new file mode 100644
index 0000000..396dbee
--- /dev/null
+++ b/src/roster-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
+
+-- Map -------------------------------------------------------------------
+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 "battle-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 "battle-characters-element-active")
+ else
+ (Html.Attributes.class "battle-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 "battle-tabmenu-content"),
+ (Html.Attributes.class "battle-tabmenu-characters-tab")
+ ]
+ (List.map
+ (get_character_element_html player_ix)
+ (Array.toList characters)
+ )
+ )
diff --git a/src/roster-editor/src/View/SubMenu/Settings.elm b/src/roster-editor/src/View/SubMenu/Settings.elm
new file mode 100644
index 0000000..e0ad4d7
--- /dev/null
+++ b/src/roster-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
+
+-- Map -------------------------------------------------------------------
+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 "battle-tabmenu-content"),
+ (Html.Attributes.class "battle-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.DebugLoadBattleRequest)
+ ]
+ [ (Html.text "[DEBUG] Load map") ]
+ ),
+ (Html.button
+ [
+ (Html.Events.onClick Struct.Event.DebugTestAnimation)
+ ]
+ [ (Html.text "[DEBUG] Test animations") ]
+ )
+ ]
+ )
diff --git a/src/roster-editor/src/View/SubMenu/Status.elm b/src/roster-editor/src/View/SubMenu/Status.elm
new file mode 100644
index 0000000..485704e
--- /dev/null
+++ b/src/roster-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.Map -------------------------------------------------------------------
+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 "battle-footer-tabmenu-content"),
+ (Html.Attributes.class "battle-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/roster-editor/src/View/SubMenu/Status/CharacterInfo.elm b/src/roster-editor/src/View/SubMenu/Status/CharacterInfo.elm
new file mode 100644
index 0000000..814ce5f
--- /dev/null
+++ b/src/roster-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.Map -------------------------------------------------------------------
+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 "battle-tabmenu-character-info")
+ ]
+ [
+ (Html.text ("Focusing:")),
+ (View.Controlled.CharacterCard.get_full_html player_ix char)
+ ]
+ )
diff --git a/src/roster-editor/src/View/SubMenu/Status/TileInfo.elm b/src/roster-editor/src/View/SubMenu/Status/TileInfo.elm
new file mode 100644
index 0000000..cace444
--- /dev/null
+++ b/src/roster-editor/src/View/SubMenu/Status/TileInfo.elm
@@ -0,0 +1,181 @@
+module View.SubMenu.Status.TileInfo exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Dict
+
+import Html
+import Html.Attributes
+
+-- Battle ----------------------------------------------------------------------
+import Constants.Movement
+
+import Struct.Map
+import Struct.Event
+import Struct.Location
+import Struct.Omnimods
+import Struct.Model
+import Struct.Tile
+
+import Util.Html
+
+import View.Map.Tile
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_icon : (Struct.Tile.Instance -> (Html.Html Struct.Event.Type))
+get_icon tile =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-tile-card-icon"),
+ (Html.Attributes.class "battle-info-card-picture"),
+ (Html.Attributes.class
+ (
+ "battle-tile-variant-"
+ ++ (toString (Struct.Tile.get_local_variant_ix tile))
+ )
+ )
+ ]
+ (View.Map.Tile.get_content_html tile)
+ )
+
+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 "battle-info-card-name"),
+ (Html.Attributes.class "battle-info-card-text-field"),
+ (Html.Attributes.class "battle-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 "battle-info-card-text-field"),
+ (Html.Attributes.class "battle-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 "battle-info-card-text-field"),
+ (Html.Attributes.class "battle-tile-card-location")
+ ]
+ [
+ (Html.text
+ (
+ "{x: "
+ ++ (toString tile_location.x)
+ ++ "; y: "
+ ++ (toString tile_location.y)
+ ++ "}"
+ )
+ )
+ ]
+ )
+
+get_mod_html : (String, Int) -> (Html.Html Struct.Event.Type)
+get_mod_html mod =
+ let
+ (category, value) = mod
+ in
+ (Html.div
+ [
+ (Html.Attributes.class "battle-info-card-mod")
+ ]
+ [
+ (Html.text
+ (category ++ ": " ++ (toString value))
+ )
+ ]
+ )
+
+get_omnimods_listing : (List (String, Int)) -> (Html.Html Struct.Event.Type)
+get_omnimods_listing mod_list =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-info-card-omnimods-listing")
+ ]
+ (List.map (get_mod_html) mod_list)
+ )
+
+get_omnimods : Struct.Omnimods.Type -> (Html.Html Struct.Event.Type)
+get_omnimods omnimods =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-info-card-omnimods")
+ ]
+ [
+ (Html.text "Attribute Modifiers"),
+ (get_omnimods_listing (Struct.Omnimods.get_attributes_mods omnimods)),
+ (Html.text "Statistics Modifiers"),
+ (get_omnimods_listing (Struct.Omnimods.get_statistics_mods omnimods)),
+ (Html.text "Attack Modifiers"),
+ (get_omnimods_listing (Struct.Omnimods.get_attack_mods omnimods)),
+ (Html.text "Defense Modifiers"),
+ (get_omnimods_listing (Struct.Omnimods.get_defense_mods omnimods))
+ ]
+ )
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_html : (
+ Struct.Model.Type ->
+ Struct.Location.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_html model loc =
+ case (Struct.Map.try_getting_tile_at loc model.map) of
+ (Just tile) ->
+ (Html.div
+ [
+ (Html.Attributes.class "battle-info-card"),
+ (Html.Attributes.class "battle-tile-card")
+ ]
+ [
+ (get_name model tile),
+ (Html.div
+ [
+ (Html.Attributes.class "battle-info-card-top"),
+ (Html.Attributes.class "battle-tile-card-top")
+ ]
+ [
+ (get_icon tile),
+ (get_location tile),
+ (get_cost tile)
+ ]
+ ),
+ (get_omnimods ((Struct.Model.tile_omnimods_fun model) loc))
+ ]
+ )
+
+ Nothing -> (Html.text "Error: Unknown tile location selected.")
diff --git a/src/roster-editor/src/View/SubMenu/Timeline.elm b/src/roster-editor/src/View/SubMenu/Timeline.elm
new file mode 100644
index 0000000..7fb1813
--- /dev/null
+++ b/src/roster-editor/src/View/SubMenu/Timeline.elm
@@ -0,0 +1,95 @@
+module View.SubMenu.Timeline exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Array
+
+import Html
+import Html.Attributes
+--import Html.Events
+import Html.Lazy
+
+-- Map -------------------------------------------------------------------
+import Struct.Character
+import Struct.Event
+import Struct.TurnResult
+import Struct.Model
+
+import View.SubMenu.Timeline.Attack
+import View.SubMenu.Timeline.Movement
+import View.SubMenu.Timeline.WeaponSwitch
+import View.SubMenu.Timeline.PlayerVictory
+import View.SubMenu.Timeline.PlayerDefeat
+import View.SubMenu.Timeline.PlayerTurnStart
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_turn_result_html : (
+ (Array.Array Struct.Character.Type) ->
+ Int ->
+ Struct.TurnResult.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_turn_result_html characters player_ix turn_result =
+ case turn_result of
+ (Struct.TurnResult.Moved movement) ->
+ (View.SubMenu.Timeline.Movement.get_html
+ characters
+ player_ix
+ movement
+ )
+
+ (Struct.TurnResult.Attacked attack) ->
+ (View.SubMenu.Timeline.Attack.get_html
+ characters
+ player_ix
+ attack
+ )
+
+ (Struct.TurnResult.SwitchedWeapon weapon_switch) ->
+ (View.SubMenu.Timeline.WeaponSwitch.get_html
+ characters
+ player_ix
+ weapon_switch
+ )
+
+ (Struct.TurnResult.PlayerWon pvict) ->
+ (View.SubMenu.Timeline.PlayerVictory.get_html pvict)
+
+ (Struct.TurnResult.PlayerLost pdefeat) ->
+ (View.SubMenu.Timeline.PlayerDefeat.get_html pdefeat)
+
+ (Struct.TurnResult.PlayerTurnStarted pturns) ->
+ (View.SubMenu.Timeline.PlayerTurnStart.get_html pturns)
+
+true_get_html : (
+ (Array.Array Struct.Character.Type) ->
+ Int ->
+ (Array.Array Struct.TurnResult.Type) ->
+ (Html.Html Struct.Event.Type)
+ )
+true_get_html characters player_ix turn_results =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-tabmenu-content"),
+ (Html.Attributes.class "battle-tabmenu-timeline-tab")
+ ]
+ (Array.toList
+ (Array.map
+ (get_turn_result_html characters player_ix)
+ turn_results
+ )
+ )
+ )
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_html : Struct.Model.Type -> (Html.Html Struct.Event.Type)
+get_html model =
+ (Html.Lazy.lazy3
+ (true_get_html)
+ model.characters
+ model.player_ix
+ model.timeline
+ )
diff --git a/src/roster-editor/src/View/SubMenu/Timeline/Attack.elm b/src/roster-editor/src/View/SubMenu/Timeline/Attack.elm
new file mode 100644
index 0000000..682540d
--- /dev/null
+++ b/src/roster-editor/src/View/SubMenu/Timeline/Attack.elm
@@ -0,0 +1,164 @@
+module View.SubMenu.Timeline.Attack exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Array
+
+import Html
+import Html.Attributes
+--import Html.Events
+
+-- Map -------------------------------------------------------------------
+import Struct.Attack
+import Struct.Event
+import Struct.TurnResult
+import Struct.Character
+
+import View.Character
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_title_html : (
+ Struct.Character.Type ->
+ Struct.Character.Type ->
+ (Html.Html Struct.Event.Type)
+ )
+get_title_html attacker defender =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-timeline-attack-title")
+ ]
+ [
+ (Html.text
+ (
+ (Struct.Character.get_name attacker)
+ ++ " attacked "
+ ++ (Struct.Character.get_name defender)
+ ++ "!"
+ )
+ )
+ ]
+ )
+
+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_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.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))
+ )
+ )
+ ]
+ )
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_html : (
+ (Array.Array Struct.Character.Type) ->
+ Int ->
+ Struct.TurnResult.Attack ->
+ (Html.Html Struct.Event.Type)
+ )
+get_html characters player_ix attack =
+ case
+ (
+ (Array.get attack.attacker_index characters),
+ (Array.get attack.defender_index characters)
+ )
+ of
+ ((Just atkchar), (Just defchar)) ->
+ (Html.div
+ [
+ (Html.Attributes.class "battle-timeline-element"),
+ (Html.Attributes.class "battle-timeline-attack")
+ ]
+ (
+ [
+ (View.Character.get_portrait_html player_ix atkchar),
+ (View.Character.get_portrait_html player_ix defchar),
+ (get_title_html atkchar defchar)
+ ]
+ ++
+ (List.map
+ (get_attack_html atkchar defchar)
+ attack.sequence
+ )
+ )
+ )
+
+ _ ->
+ (Html.div
+ [
+ (Html.Attributes.class "battle-timeline-element"),
+ (Html.Attributes.class "battle-timeline-attack")
+ ]
+ [
+ (Html.text "Error: Attack with unknown characters")
+ ]
+ )
diff --git a/src/roster-editor/src/View/SubMenu/Timeline/Movement.elm b/src/roster-editor/src/View/SubMenu/Timeline/Movement.elm
new file mode 100644
index 0000000..0746f1f
--- /dev/null
+++ b/src/roster-editor/src/View/SubMenu/Timeline/Movement.elm
@@ -0,0 +1,62 @@
+module View.SubMenu.Timeline.Movement exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Array
+
+import Html
+import Html.Attributes
+--import Html.Events
+
+-- Map -------------------------------------------------------------------
+import Struct.Event
+import Struct.TurnResult
+import Struct.Character
+
+import View.Character
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_html : (
+ (Array.Array Struct.Character.Type) ->
+ Int ->
+ Struct.TurnResult.Movement ->
+ (Html.Html Struct.Event.Type)
+ )
+get_html characters player_ix movement =
+ case (Array.get movement.character_index characters) of
+ (Just char) ->
+ (Html.div
+ [
+ (Html.Attributes.class "battle-timeline-element"),
+ (Html.Attributes.class "battle-timeline-movement")
+ ]
+ [
+ (View.Character.get_portrait_html player_ix char),
+ (Html.text
+ (
+ (Struct.Character.get_name char)
+ ++ " moved to ("
+ ++ (toString movement.destination.x)
+ ++ ", "
+ ++ (toString movement.destination.y)
+ ++ ")."
+ )
+ )
+ ]
+ )
+
+ _ ->
+ (Html.div
+ [
+ (Html.Attributes.class "battle-timeline-element"),
+ (Html.Attributes.class "battle-timeline-movement")
+ ]
+ [
+ (Html.text "Error: Moving with unknown character")
+ ]
+ )
diff --git a/src/roster-editor/src/View/SubMenu/Timeline/PlayerDefeat.elm b/src/roster-editor/src/View/SubMenu/Timeline/PlayerDefeat.elm
new file mode 100644
index 0000000..db5e023
--- /dev/null
+++ b/src/roster-editor/src/View/SubMenu/Timeline/PlayerDefeat.elm
@@ -0,0 +1,38 @@
+module View.SubMenu.Timeline.PlayerDefeat exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Html
+import Html.Attributes
+--import Html.Events
+
+-- Map -------------------------------------------------------------------
+import Struct.Event
+import Struct.TurnResult
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_html : (
+ Struct.TurnResult.PlayerDefeat ->
+ (Html.Html Struct.Event.Type)
+ )
+get_html pdefeat =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-timeline-element"),
+ (Html.Attributes.class "battle-timeline-player-defeat")
+ ]
+ [
+ (Html.text
+ (
+ "Player "
+ ++ (toString pdefeat.player_index)
+ ++ " has been eliminated."
+ )
+ )
+ ]
+ )
diff --git a/src/roster-editor/src/View/SubMenu/Timeline/PlayerTurnStart.elm b/src/roster-editor/src/View/SubMenu/Timeline/PlayerTurnStart.elm
new file mode 100644
index 0000000..a6486fa
--- /dev/null
+++ b/src/roster-editor/src/View/SubMenu/Timeline/PlayerTurnStart.elm
@@ -0,0 +1,38 @@
+module View.SubMenu.Timeline.PlayerTurnStart exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Html
+import Html.Attributes
+--import Html.Events
+
+-- Map -------------------------------------------------------------------
+import Struct.Event
+import Struct.TurnResult
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_html : (
+ Struct.TurnResult.PlayerTurnStart ->
+ (Html.Html Struct.Event.Type)
+ )
+get_html pturns =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-timeline-element"),
+ (Html.Attributes.class "battle-timeline-turn-start")
+ ]
+ [
+ (Html.text
+ (
+ "Player "
+ ++ (toString pturns.player_index)
+ ++ "'s turn has started."
+ )
+ )
+ ]
+ )
diff --git a/src/roster-editor/src/View/SubMenu/Timeline/PlayerVictory.elm b/src/roster-editor/src/View/SubMenu/Timeline/PlayerVictory.elm
new file mode 100644
index 0000000..4d47f62
--- /dev/null
+++ b/src/roster-editor/src/View/SubMenu/Timeline/PlayerVictory.elm
@@ -0,0 +1,38 @@
+module View.SubMenu.Timeline.PlayerVictory exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Html
+import Html.Attributes
+--import Html.Events
+
+-- Map -------------------------------------------------------------------
+import Struct.Event
+import Struct.TurnResult
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_html : (
+ Struct.TurnResult.PlayerVictory ->
+ (Html.Html Struct.Event.Type)
+ )
+get_html pvict =
+ (Html.div
+ [
+ (Html.Attributes.class "battle-timeline-element"),
+ (Html.Attributes.class "battle-timeline-player-victory")
+ ]
+ [
+ (Html.text
+ (
+ "Player "
+ ++ (toString pvict.player_index)
+ ++ " has won the map."
+ )
+ )
+ ]
+ )
diff --git a/src/roster-editor/src/View/SubMenu/Timeline/WeaponSwitch.elm b/src/roster-editor/src/View/SubMenu/Timeline/WeaponSwitch.elm
new file mode 100644
index 0000000..499e0c3
--- /dev/null
+++ b/src/roster-editor/src/View/SubMenu/Timeline/WeaponSwitch.elm
@@ -0,0 +1,58 @@
+module View.SubMenu.Timeline.WeaponSwitch exposing (get_html)
+
+-- Elm -------------------------------------------------------------------------
+import Array
+
+import Html
+import Html.Attributes
+--import Html.Events
+
+-- Map -------------------------------------------------------------------
+import Struct.Event
+import Struct.TurnResult
+import Struct.Character
+
+import View.Character
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_html : (
+ (Array.Array Struct.Character.Type) ->
+ Int ->
+ Struct.TurnResult.WeaponSwitch ->
+ (Html.Html Struct.Event.Type)
+ )
+get_html characters player_ix weapon_switch =
+ case (Array.get weapon_switch.character_index characters) of
+ (Just char) ->
+ (Html.div
+ [
+ (Html.Attributes.class "battle-timeline-element"),
+ (Html.Attributes.class "battle-timeline-weapon-switch")
+ ]
+ [
+ (View.Character.get_portrait_html player_ix char),
+ (Html.text
+ (
+ (Struct.Character.get_name char)
+ ++ " switched weapons."
+ )
+ )
+ ]
+ )
+
+ _ ->
+ (Html.div
+ [
+ (Html.Attributes.class "battle-timeline-element"),
+ (Html.Attributes.class "battle-timeline-weapon-switch")
+ ]
+ [
+ (Html.text "Error: Unknown character switched weapons")
+ ]
+ )
diff --git a/src/roster-editor/www/index.html b/src/roster-editor/www/index.html
new file mode 100644
index 0000000..a2a6034
--- /dev/null
+++ b/src/roster-editor/www/index.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/global.css">
+ <link rel="stylesheet" type="text/css" href="../css/roster-editor.css">
+ <link rel="stylesheet" type="text/css" href="../asset/characters.css">
+ <link rel="stylesheet" type="text/css" href="../asset/armors.css">
+ <link rel="icon" type="image/x-icon" href="/favicon.ico">
+ </head>
+ <body>
+ <script src="script/main.js"></script>
+ <script src="../global/script/session.js"></script>
+ <script src="../global/script/urlparams.js"></script>
+ <script src="../global/script/navigation.js"></script>
+ <script>
+ tacticians_online.session.load();
+
+ tacticians_online.app =
+ Elm.Main.fullscreen
+ (
+ {
+ user_id: tacticians_online.session.get_user_id(),
+ token: tacticians_online.session.get_token(),
+ url_params: tacticians_online.urlparams.get_parameters()
+ }
+ );
+
+ tacticians_online.session.attach_to(tacticians_online.app);
+ tacticians_online.navigation.attach_to(tacticians_online.app);
+ </script>
+ </body>
+</html>