| summaryrefslogtreecommitdiff | 
diff options
| author | nsensfel <SpamShield0@noot-noot.org> | 2018-09-10 18:04:34 +0200 | 
|---|---|---|
| committer | nsensfel <SpamShield0@noot-noot.org> | 2018-09-10 18:04:34 +0200 | 
| commit | 4089e04b953ce2799d839d841278446d7f0b4c32 (patch) | |
| tree | e1877866c559544a97a4557cc99c025184f122c1 /src/roster-editor | |
| parent | 04e4ce4137fe3ffb0ccc6dc8635db3e202517945 (diff) | |
character -> roster-editor
Diffstat (limited to 'src/roster-editor')
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> | 


