summaryrefslogtreecommitdiff |
diff options
author | nsensfel <SpamShield0@noot-noot.org> | 2018-08-24 17:36:33 +0200 |
---|---|---|
committer | nsensfel <SpamShield0@noot-noot.org> | 2018-08-24 17:36:33 +0200 |
commit | b3fd9613c298e1af44f025d9d95021eec8c72a59 (patch) | |
tree | 4e00b8d3c2f3a56747a3520a3ec260c5e3302861 | |
parent | 3713d6089adccd96385b0d079bb72587d2122848 (diff) |
Starting to work on the character editor.
63 files changed, 5502 insertions, 0 deletions
diff --git a/src/character/Makefile b/src/character/Makefile new file mode 100644 index 0000000..3b58a08 --- /dev/null +++ b/src/character/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/character/elm-package.json b/src/character/elm-package.json new file mode 100644 index 0000000..5f6573f --- /dev/null +++ b/src/character/elm-package.json @@ -0,0 +1,18 @@ +{ + "version": "1.0.0", + "summary": "helpful summary of your project, less than 80 characters", + "repository": "https://github.com/nsensfel/tacticians-client.git", + "license": "Apache 2.0", + "source-directories": [ + "src" + ], + "exposed-modules": [], + "dependencies": { + "NoRedInk/elm-decode-pipeline": "3.0.0 <= v < 4.0.0", + "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/character/src/Comm/AddArmor.elm b/src/character/src/Comm/AddArmor.elm new file mode 100644 index 0000000..480b823 --- /dev/null +++ b/src/character/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/character/src/Comm/AddChar.elm b/src/character/src/Comm/AddChar.elm new file mode 100644 index 0000000..32227a8 --- /dev/null +++ b/src/character/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/character/src/Comm/AddWeapon.elm b/src/character/src/Comm/AddWeapon.elm new file mode 100644 index 0000000..7061dea --- /dev/null +++ b/src/character/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/character/src/Comm/LoadRoster.elm b/src/character/src/Comm/LoadRoster.elm new file mode 100644 index 0000000..4058b6d --- /dev/null +++ b/src/character/src/Comm/LoadRoster.elm @@ -0,0 +1,41 @@ +module Comm.LoadRoster exposing (try) + +-- Elm ------------------------------------------------------------------------- +import Json.Encode + +-- Map ------------------------------------------------------------------- +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)) + ] + ) + ) + +-------------------------------------------------------------------------------- +-- 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/character/src/Comm/Send.elm b/src/character/src/Comm/Send.elm new file mode 100644 index 0000000..98e3ba4 --- /dev/null +++ b/src/character/src/Comm/Send.elm @@ -0,0 +1,76 @@ +module Comm.Send exposing (try_sending) + +-- Elm ------------------------------------------------------------------------- +import Http + +import Json.Decode +import Json.Encode + +-- Map ------------------------------------------------------------------- +import Comm.AddArmor +import Comm.AddChar +import Comm.AddTile +import Comm.AddWeapon +import Comm.SetMap +import Comm.SetTimeline +import Comm.TurnResults + +import Struct.Event +import Struct.ServerReply +import Struct.Model + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +internal_decoder : String -> (Json.Decode.Decoder Struct.ServerReply.Type) +internal_decoder reply_type = + case reply_type of + "add_tile" -> (Comm.AddTile.decode) + "add_armor" -> (Comm.AddArmor.decode) + "add_char" -> (Comm.AddChar.decode) + "add_weapon" -> (Comm.AddWeapon.decode) + "set_map" -> (Comm.SetMap.decode) + "turn_results" -> (Comm.TurnResults.decode) + "set_timeline" -> (Comm.SetTimeline.decode) + other -> + (Json.Decode.fail + ( + "Unknown server command \"" + ++ other + ++ "\"" + ) + ) + +decode : (Json.Decode.Decoder Struct.ServerReply.Type) +decode = + (Json.Decode.field "msg" Json.Decode.string) + |> (Json.Decode.andThen (internal_decoder)) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +try_sending : ( + Struct.Model.Type -> + String -> + (Struct.Model.Type -> (Maybe Json.Encode.Value)) -> + (Maybe (Cmd Struct.Event.Type)) + ) +try_sending model recipient try_encoding_fun = + case (try_encoding_fun model) of + (Just serial) -> + (Just + (Http.send + Struct.Event.ServerReplied + (Http.post + recipient + (Http.jsonBody serial) + (Json.Decode.list (decode)) + ) + ) + ) + + Nothing -> Nothing diff --git a/src/character/src/Constants/IO.elm.m4 b/src/character/src/Constants/IO.elm.m4 new file mode 100644 index 0000000..c0f4a9f --- /dev/null +++ b/src/character/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 = (roster_handler_url ++ "/chr_load") diff --git a/src/character/src/ElmModule/Init.elm b/src/character/src/ElmModule/Init.elm new file mode 100644 index 0000000..4fccd82 --- /dev/null +++ b/src/character/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/character/src/ElmModule/Subscriptions.elm b/src/character/src/ElmModule/Subscriptions.elm new file mode 100644 index 0000000..fe276f4 --- /dev/null +++ b/src/character/src/ElmModule/Subscriptions.elm @@ -0,0 +1,17 @@ +module ElmModule.Subscriptions exposing (..) + +-- Elm ------------------------------------------------------------------------- + +-- Map ------------------------------------------------------------------- +import Struct.Model +import Struct.Event + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +subscriptions : Struct.Model.Type -> (Sub Struct.Event.Type) +subscriptions model = Sub.none diff --git a/src/character/src/ElmModule/Update.elm b/src/character/src/ElmModule/Update.elm new file mode 100644 index 0000000..eafac01 --- /dev/null +++ b/src/character/src/ElmModule/Update.elm @@ -0,0 +1,106 @@ +module ElmModule.Update exposing (update) + +-- Elm ------------------------------------------------------------------------- + +-- Map ------------------------------------------------------------------- +import Struct.Event +import Struct.Model + +import Update.AbortTurn +import Update.AttackWithoutMoving +import Update.ChangeScale +import Update.DisplayCharacterInfo +import Update.EndTurn +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 + +-------------------------------------------------------------------------------- +-- 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.RequestedHelp help_request) -> + (Update.SetRequestedHelp.apply_to new_model help_request) diff --git a/src/character/src/ElmModule/View.elm b/src/character/src/ElmModule/View.elm new file mode 100644 index 0000000..069b0bf --- /dev/null +++ b/src/character/src/ElmModule/View.elm @@ -0,0 +1,57 @@ +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.Map +import View.Controlled +import View.MessageBoard +import View.MainMenu +import View.SubMenu + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +view : Struct.Model.Type -> (Html.Html Struct.Event.Type) +view model = + (Html.div + [ + (Html.Attributes.class "fullscreen-module") + ] + [ + (View.MainMenu.get_html), + (Html.Lazy.lazy2 + (View.Controlled.get_html) + model.char_turn + model.player_ix + ), + (Html.div + [ + (Html.Attributes.class "battle-container-centerer") + ] + [ + (Html.div + [ + (Html.Attributes.class "battle-container"), + (Html.Attributes.id Constants.UI.viewer_html_id) + ] + [(View.Map.get_html model)] + ) + ] + ), + (View.SubMenu.get_html model), + (View.MessageBoard.get_html model) + ] + ) diff --git a/src/character/src/Main.elm b/src/character/src/Main.elm new file mode 100644 index 0000000..8140041 --- /dev/null +++ b/src/character/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/character/src/Struct/Armor.elm b/src/character/src/Struct/Armor.elm new file mode 100644 index 0000000..04a0428 --- /dev/null +++ b/src/character/src/Struct/Armor.elm @@ -0,0 +1,177 @@ +module Struct.Armor exposing + ( + Type, + Ref, + Category(..), + new, + get_id, + get_name, + get_category, + get_resistance_to, + get_image_id, + decoder, + none, + apply_to_attributes + ) + +-- Elm ------------------------------------------------------------------------- +import Json.Decode +import Json.Decode.Pipeline + +-- Map ------------------------------------------------------------------- +import Struct.Attributes +import Struct.Weapon + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type alias PartiallyDecoded = + { + id : Int, + nam : String, + ct : String, + cf : Float + } + +type alias Type = + { + id : Int, + name : String, + category : Category, + coef : Float + } + +type alias Ref = Int + +type Category = + Kinetic + | Leather + | Chain + | Plate + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +finish_decoding : PartiallyDecoded -> Type +finish_decoding add_armor = + { + id = add_armor.id, + name = add_armor.nam, + category = + ( + case add_armor.ct of + "k" -> Kinetic + "c" -> Chain + "p" -> Plate + _ -> Leather + ), + coef = add_armor.cf + } + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +new : Int -> String -> Category -> Float -> Type +new id name category coef = + { + id = id, + name = name, + category = category, + coef = coef + } + +get_id : Type -> Ref +get_id ar = ar.id + +get_name : Type -> String +get_name ar = ar.name + +get_category : Type -> String +get_category ar = ar.name + +get_image_id : Type -> String +get_image_id ar = (toString ar.id) + +get_resistance_to : Struct.Weapon.DamageType -> Type -> Int +get_resistance_to dmg_type ar = + (ceiling + ( + ar.coef + * + ( + case (dmg_type, ar.category) of + (Struct.Weapon.Slash, Kinetic) -> 0.0 + (Struct.Weapon.Slash, Leather) -> 20.0 + (Struct.Weapon.Slash, Chain) -> 30.0 + (Struct.Weapon.Slash, Plate) -> 30.0 + (Struct.Weapon.Blunt, Kinetic) -> 30.0 + (Struct.Weapon.Blunt, Leather) -> 20.0 + (Struct.Weapon.Blunt, Chain) -> 20.0 + (Struct.Weapon.Blunt, Plate) -> 20.0 + (Struct.Weapon.Pierce, Kinetic) -> 20.0 + (Struct.Weapon.Pierce, Leather) -> 20.0 + (Struct.Weapon.Pierce, Chain) -> 20.0 + (Struct.Weapon.Pierce, Plate) -> 30.0 + ) + ) + ) + +apply_to_attributes : Type -> Struct.Attributes.Type -> Struct.Attributes.Type +apply_to_attributes ar atts = + let + impact = (-1 * (ceiling (20.0 * ar.coef))) + half_impact = (-1 * (ceiling (10.0 * ar.coef))) + in + case ar.category of + Kinetic -> (Struct.Attributes.mod_mind impact atts) + Leather -> + (Struct.Attributes.mod_constitution + half_impact + (Struct.Attributes.mod_dexterity + half_impact + atts + ) + ) + + Chain -> + (Struct.Attributes.mod_constitution + half_impact + (Struct.Attributes.mod_dexterity + half_impact + (Struct.Attributes.mod_speed impact atts) + ) + ) + + Plate -> + (Struct.Attributes.mod_constitution + half_impact + (Struct.Attributes.mod_dexterity + half_impact + (Struct.Attributes.mod_speed + impact + (Struct.Attributes.mod_strength impact atts) + ) + ) + ) + +decoder : (Json.Decode.Decoder Type) +decoder = + (Json.Decode.map + (finish_decoding) + (Json.Decode.Pipeline.decode + PartiallyDecoded + |> (Json.Decode.Pipeline.required "id" Json.Decode.int) + |> (Json.Decode.Pipeline.required "nam" Json.Decode.string) + |> (Json.Decode.Pipeline.required "ct" Json.Decode.string) + |> (Json.Decode.Pipeline.required "cf" Json.Decode.float) + ) + ) + +none : Type +none = + (new + 0 + "None" + Leather + 0.0 + ) diff --git a/src/character/src/Struct/Attributes.elm b/src/character/src/Struct/Attributes.elm new file mode 100644 index 0000000..50b4ad4 --- /dev/null +++ b/src/character/src/Struct/Attributes.elm @@ -0,0 +1,134 @@ +module Struct.Attributes exposing + ( + Type, + get_constitution, + get_dexterity, + get_intelligence, + get_mind, + get_speed, + get_strength, + mod_constitution, + mod_dexterity, + mod_intelligence, + mod_mind, + mod_speed, + mod_strength, + new, + decoder + ) + +-- Elm ------------------------------------------------------------------------- +import Json.Decode +import Json.Decode.Pipeline + +-- Map ------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +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)) + } + +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 + } + +decoder : (Json.Decode.Decoder Type) +decoder = + (Json.Decode.Pipeline.decode + Type + |> (Json.Decode.Pipeline.required "con" Json.Decode.int) + |> (Json.Decode.Pipeline.required "dex" Json.Decode.int) + |> (Json.Decode.Pipeline.required "int" Json.Decode.int) + |> (Json.Decode.Pipeline.required "min" Json.Decode.int) + |> (Json.Decode.Pipeline.required "spe" Json.Decode.int) + |> (Json.Decode.Pipeline.required "str" Json.Decode.int) + ) diff --git a/src/character/src/Struct/Character.elm b/src/character/src/Struct/Character.elm new file mode 100644 index 0000000..f854b44 --- /dev/null +++ b/src/character/src/Struct/Character.elm @@ -0,0 +1,238 @@ +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_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, + fill_missing_equipment + ) + +-- Elm ------------------------------------------------------------------------- +import Json.Decode +import Json.Decode.Pipeline + +-- Map ------------------------------------------------------------------- +import Struct.Armor +import Struct.Attributes +import Struct.Location +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, + att : Struct.Attributes.Type, + awp : Int, + swp : Int, + ar : Int + } + +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 + } + +-------------------------------------------------------------------------------- +-- 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 + 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 = add_char.att, + statistics = (Struct.Statistics.new add_char.att weapon_set armor), + player_ix = add_char.pla, + enabled = add_char.ena, + defeated = add_char.dea, + weapons = weapon_set, + armor = armor + } + 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_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, + statistics = (Struct.Statistics.new char.attributes weapons char.armor) + } + +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 "att" (Struct.Attributes.decoder)) + |> (Json.Decode.Pipeline.required "awp" Json.Decode.int) + |> (Json.Decode.Pipeline.required "swp" Json.Decode.int) + |> (Json.Decode.Pipeline.required "ar" Json.Decode.int) + ) + ) + +fill_missing_equipment : ( + Struct.Weapon.Type -> + Struct.Weapon.Type -> + Struct.Armor.Type -> + Type -> + Type + ) +fill_missing_equipment awp swp ar char = + let + weapon_set = (Struct.WeaponSet.new awp swp) + in + {char | + statistics = (Struct.Statistics.new char.attributes weapon_set ar), + weapons = weapon_set, + armor = ar + } diff --git a/src/character/src/Struct/Error.elm b/src/character/src/Struct/Error.elm new file mode 100644 index 0000000..5f40c09 --- /dev/null +++ b/src/character/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/character/src/Struct/Event.elm b/src/character/src/Struct/Event.elm new file mode 100644 index 0000000..dedb606 --- /dev/null +++ b/src/character/src/Struct/Event.elm @@ -0,0 +1,44 @@ +module Struct.Event exposing (Type(..), attempted) + +-- Elm ------------------------------------------------------------------------- +import Http + +-- Map ------------------------------------------------------------------- +import Struct.Direction +import Struct.Error +import Struct.Location +import Struct.ServerReply +import Struct.HelpRequest +import Struct.UI + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type Type = + AbortTurnRequest + | AnimationEnded + | AttackWithoutMovingRequest + | CharacterInfoRequested Int + | CharacterSelected Int + | DebugLoadBattleRequest + | DebugTeamSwitchRequest + | DebugTestAnimation + | DirectionRequested Struct.Direction.Type + | Failed Struct.Error.Type + | LookingForCharacter Int + | None + | ScaleChangeRequested Float + | ServerReplied (Result Http.Error (List Struct.ServerReply.Type)) + | TabSelected Struct.UI.Tab + | TileSelected Struct.Location.Ref + | CharacterOrTileSelected Struct.Location.Ref + | TurnEnded + | RequestedHelp Struct.HelpRequest.Type + | WeaponSwitchRequest + +attempted : (Result.Result err val) -> Type +attempted act = + case act of + (Result.Ok _) -> None + (Result.Err msg) -> + (Failed (Struct.Error.new Struct.Error.Failure (toString msg))) diff --git a/src/character/src/Struct/Flags.elm b/src/character/src/Struct/Flags.elm new file mode 100644 index 0000000..228d258 --- /dev/null +++ b/src/character/src/Struct/Flags.elm @@ -0,0 +1,42 @@ +module Struct.Flags exposing + ( + Type, + maybe_get_param + ) + +-- Elm ------------------------------------------------------------------------- +import List + +-- Map ------------------------------------------------------------------- +import Util.List + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type alias Type = + { + user_id : String, + token : String, + url_params : (List (List String)) + } + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +maybe_get_param : String -> Type -> (Maybe String) +maybe_get_param param flags = + case + (Util.List.get_first + (\e -> ((List.head e) == (Just param))) + flags.url_params + ) + of + Nothing -> Nothing + (Just a) -> + case (List.tail a) of + Nothing -> Nothing + (Just b) -> (List.head b) diff --git a/src/character/src/Struct/HelpRequest.elm b/src/character/src/Struct/HelpRequest.elm new file mode 100644 index 0000000..a0693e2 --- /dev/null +++ b/src/character/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/character/src/Struct/Model.elm b/src/character/src/Struct/Model.elm new file mode 100644 index 0000000..d1f2fc7 --- /dev/null +++ b/src/character/src/Struct/Model.elm @@ -0,0 +1,140 @@ +module Struct.Model exposing + ( + Type, + new, + add_character, + update_character, + update_character_fun, + add_weapon, + add_armor, + invalidate, + reset, + clear_error + ) + +-- Elm ------------------------------------------------------------------------- +import Array + +import Dict + +-- Map ------------------------------------------------------------------- +import Struct.Armor +import Struct.Map +import Struct.Character +import Struct.CharacterTurn +import Struct.Error +import Struct.Flags +import Struct.HelpRequest +import Struct.Tile +import Struct.TurnResult +import Struct.TurnResultAnimator +import Struct.UI +import Struct.Weapon + +import Util.Array + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type alias Type = + { + help_request: Struct.HelpRequest.Type, + 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, + session_token: String, + ui: Struct.UI.Type + } + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +new : Struct.Flags.Type -> Type +new flags = + { + help_request = Struct.HelpRequest.None, + characters = (Array.empty), + weapons = (Dict.empty), + armors = (Dict.empty), + error = Nothing, + player_id = + ( + if (flags.user_id == "") + then "0" + else flags.user_id + ), + session_token = flags.token, + ui = (Struct.UI.default) + } + +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 + ) + } + +reset : Type -> Type +reset model = + {model | + help_request = Struct.HelpRequest.None, + error = Nothing, + ui = (Struct.UI.set_previous_action Nothing model.ui) + } + +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/character/src/Struct/ServerReply.elm b/src/character/src/Struct/ServerReply.elm new file mode 100644 index 0000000..87325a5 --- /dev/null +++ b/src/character/src/Struct/ServerReply.elm @@ -0,0 +1,33 @@ +module Struct.ServerReply exposing (Type(..)) + +-- Elm ------------------------------------------------------------------------- + +-- Map ------------------------------------------------------------------- +import Struct.Armor +import Struct.Map +import Struct.Character +import Struct.Tile +import Struct.TurnResult +import Struct.Weapon + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +type Type = + Okay + | AddArmor Struct.Armor.Type + | AddWeapon Struct.Weapon.Type + | AddCharacter (Struct.Character.Type, Int, Int, Int) + | AddTile Struct.Tile.Type + | SetMap Struct.Map.Type + | TurnResults (List Struct.TurnResult.Type) + | SetTimeline (List Struct.TurnResult.Type) + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- diff --git a/src/character/src/Struct/Statistics.elm b/src/character/src/Struct/Statistics.elm new file mode 100644 index 0000000..aa3de39 --- /dev/null +++ b/src/character/src/Struct/Statistics.elm @@ -0,0 +1,176 @@ +module Struct.Statistics exposing + ( + Type, + get_movement_points, + get_max_health, + get_dodges, + get_parries, + get_damage_min, + get_damage_max, + get_accuracy, + get_double_hits, + get_critical_hits, + new + ) + +-- Elm ------------------------------------------------------------------------- +import List + +-- Map ------------------------------------------------------------------- +import Struct.Attributes +import Struct.Armor +import Struct.Weapon +import Struct.WeaponSet + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type alias Type = + { + movement_points : Int, + max_health : Int, + dodges : Int, + parries : Int, + damage_min : Int, + damage_max : Int, + accuracy : Int, + double_hits : Int, + critical_hits : Int + } + +-------------------------------------------------------------------------------- +-- 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))) + +already_high_slow_growth : Int -> Int +already_high_slow_growth v = + (float_to_int + (30.0 * (logBase 2.718281828459 (((toFloat v) + 5.0)/4.0))) + ) + +damage_base_mod : Float -> Float +damage_base_mod str = (((str^1.8)/2000.0) - 0.75) + +apply_damage_base_mod : Float -> Float -> Int +apply_damage_base_mod bmod dmg = + (max 0 (float_to_int (dmg + (bmod * dmg)))) + +-------------------------------------------------------------------------------- +-- 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_damage_min : Type -> Int +get_damage_min t = t.damage_min + +get_damage_max : Type -> Int +get_damage_max t = t.damage_max + +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 + +new : ( + Struct.Attributes.Type -> + Struct.WeaponSet.Type -> + Struct.Armor.Type -> + Type + ) +new att wp_set ar = + let + active_weapon = (Struct.WeaponSet.get_active_weapon wp_set) + actual_att = + (Struct.Armor.apply_to_attributes + ar + (Struct.Weapon.apply_to_attributes active_weapon att) + ) + constitution = (Struct.Attributes.get_constitution actual_att) + dexterity = (Struct.Attributes.get_dexterity actual_att) + intelligence = (Struct.Attributes.get_intelligence actual_att) + mind = (Struct.Attributes.get_mind actual_att) + speed = (Struct.Attributes.get_speed actual_att) + strength = (Struct.Attributes.get_strength actual_att) + dmg_bmod = (damage_base_mod (toFloat strength)) + 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 = + (clamp + 0 + 100 + (sudden_exp_growth_f + (average + [dexterity, mind, speed] + ) + ) + ), + parries = + (clamp + 0 + 75 + (sudden_exp_growth_f + (average [dexterity, intelligence, speed, strength]) + ) + ), + damage_min = + (apply_damage_base_mod + dmg_bmod + (toFloat (Struct.Weapon.get_min_damage active_weapon)) + ), + damage_max = + (apply_damage_base_mod + dmg_bmod + (toFloat (Struct.Weapon.get_max_damage active_weapon)) + ), + accuracy = (sudden_squared_growth dexterity), + double_hits = + (clamp 0 100 (sudden_squared_growth_f (average [mind, speed]))), + critical_hits = + (clamp 0 100 (sudden_squared_growth intelligence)) + } diff --git a/src/character/src/Struct/UI.elm b/src/character/src/Struct/UI.elm new file mode 100644 index 0000000..4837434 --- /dev/null +++ b/src/character/src/Struct/UI.elm @@ -0,0 +1,135 @@ +module Struct.UI exposing + ( + Type, + Tab(..), + Action(..), + default, + -- Zoom + get_zoom_level, + reset_zoom_level, + mod_zoom_level, + -- Tab + try_getting_displayed_tab, + set_displayed_tab, + reset_displayed_tab, + to_string, + get_all_tabs, + -- Navigator + try_getting_displayed_nav, + set_displayed_nav, + reset_displayed_nav, + -- Manual Controls + has_manual_controls_enabled, + -- Previous Action + get_previous_action, + set_previous_action + ) + +-- Map ------------------------------------------------------------------- +import Struct.Location +import Struct.Navigator + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type Tab = + StatusTab + | CharactersTab + | SettingsTab + | TimelineTab + +type Action = + UsedManualControls + | SelectedLocation Struct.Location.Ref + | SelectedCharacter Int + | AttackedCharacter Int + +type alias Type = + { + zoom_level : Float, + show_manual_controls : Bool, + displayed_tab : (Maybe Tab), + previous_action : (Maybe Action), + displayed_nav : (Maybe Struct.Navigator.Type) + } + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +default : Type +default = + { + zoom_level = 1.0, + show_manual_controls = True, + displayed_tab = Nothing, + previous_action = Nothing, + displayed_nav = Nothing + } + +-- Zoom ------------------------------------------------------------------------ +get_zoom_level : Type -> Float +get_zoom_level ui = ui.zoom_level + +reset_zoom_level : Type -> Type +reset_zoom_level ui = {ui | zoom_level = 1.0} + +mod_zoom_level : Float -> Type -> Type +mod_zoom_level mod ui = {ui | zoom_level = (mod * ui.zoom_level)} + +-- Tab ------------------------------------------------------------------------- +try_getting_displayed_tab : Type -> (Maybe Tab) +try_getting_displayed_tab ui = ui.displayed_tab + +set_displayed_tab : Tab -> Type -> Type +set_displayed_tab tab ui = {ui | displayed_tab = (Just tab)} + +reset_displayed_tab : Type -> Type +reset_displayed_tab ui = {ui | displayed_tab = Nothing} + +to_string : Tab -> String +to_string tab = + case tab of + StatusTab -> "Status" + CharactersTab -> "Characters" + SettingsTab -> "Settings" + TimelineTab -> "Timeline" + +get_all_tabs : (List Tab) +get_all_tabs = + [StatusTab, CharactersTab, SettingsTab, TimelineTab] + +-- Navigator ------------------------------------------------------------------- +try_getting_displayed_nav : Type -> (Maybe Struct.Navigator.Type) +try_getting_displayed_nav ui = ui.displayed_nav + +set_displayed_nav : Struct.Navigator.Type -> Type -> Type +set_displayed_nav nav ui = {ui | displayed_nav = (Just nav)} + +reset_displayed_nav : Type -> Type +reset_displayed_nav ui = {ui | displayed_nav = Nothing} + +-- ManualControls -------------------------------------------------------------- +has_manual_controls_enabled : Type -> Bool +has_manual_controls_enabled ui = ui.show_manual_controls + +toggle_manual_controls : Type -> Type +toggle_manual_controls ui = + if (ui.show_manual_controls) + then + {ui | show_manual_controls = False} + else + {ui | show_manual_controls = True} + +set_enable_manual_controls : Bool -> Type -> Type +set_enable_manual_controls val ui = {ui | show_manual_controls = val} + +-- Previous Action ------------------------------------------------------------- +set_previous_action : (Maybe Action) -> Type -> Type +set_previous_action act ui = {ui | previous_action = act} + +get_previous_action : Type -> (Maybe Action) +get_previous_action ui = ui.previous_action diff --git a/src/character/src/Struct/Weapon.elm b/src/character/src/Struct/Weapon.elm new file mode 100644 index 0000000..d572ed6 --- /dev/null +++ b/src/character/src/Struct/Weapon.elm @@ -0,0 +1,248 @@ +module Struct.Weapon exposing + ( + Type, + Ref, + RangeType(..), + RangeModifier(..), + DamageType(..), + DamageModifier(..), + new, + get_id, + get_name, + get_range_type, + get_range_modifier, + get_damage_type, + get_damage_modifier, + get_attack_range, + get_defense_range, + get_max_damage, + get_min_damage, + decoder, + none, + apply_to_attributes + ) + +-- Elm ------------------------------------------------------------------------- +import Json.Decode +import Json.Decode.Pipeline + +-- Map ------------------------------------------------------------------- +import Struct.Attributes + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type alias PartiallyDecoded = + { + id : Int, + nam : String, + rt : String, + rm : String, + dt : String, + dm : String, + cf : Float + } + +type alias Type = + { + id : Int, + name : String, + coef : Float, + range_type : RangeType, + range_mod : RangeModifier, + dmg_type : DamageType, + dmg_mod : DamageModifier, + def_range : Int, + atk_range : Int, + dmg_min : Int, + dmg_max : Int + } + +type alias Ref = Int + +type RangeType = Ranged | Melee +type RangeModifier = Long | Short +-- Having multiple types at the same time, like Warframe does, would be nice. +type DamageType = Slash | Blunt | Pierce +type DamageModifier = Heavy | Light + +type alias WeaponType = + { + range : RangeType, + range_mod : RangeModifier, + dmg_type : DamageType + } + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_ranges : RangeType -> RangeModifier -> (Int, Int) +get_ranges rt rm = + case (rt, rm) of + (Ranged, Long) -> (2, 6) + (Ranged, Short) -> (1, 4) + (Melee, Long) -> (0, 2) + (Melee, Short) -> (0, 1) + +get_damages : Float -> RangeType -> DamageModifier -> (Int, Int) +get_damages coef rt dm = + case (rt, dm) of + (Ranged, Heavy) -> ((ceiling (15.0 * coef)), (ceiling (30.0 * coef))) + (Ranged, Light) -> ((ceiling (10.0 * coef)), (ceiling (25.0 * coef))) + (Melee, Heavy) -> ((ceiling (20.0 * coef)), (ceiling (35.0 * coef))) + (Melee, Light) -> ((ceiling (15.0 * coef)), (ceiling (30.0 * coef))) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +new : ( + Int -> + String -> + Float -> + RangeType -> + RangeModifier -> + DamageType -> + DamageModifier -> + Type + ) +new + id name coef + range_type range_mod + dmg_type dmg_mod + = + let + (def_range, atk_range) = (get_ranges range_type range_mod) + (dmg_min, dmg_max) = (get_damages coef range_type dmg_mod) + in + { + id = id, + name = name, + coef = coef, + range_type = range_type, + range_mod = range_mod, + dmg_type = dmg_type, + dmg_mod = dmg_mod, + def_range = def_range, + atk_range = atk_range, + dmg_min = dmg_min, + dmg_max = dmg_max + } + +get_id : Type -> Int +get_id wp = wp.id + +get_name : Type -> String +get_name wp = wp.name + +get_range_type : Type -> RangeType +get_range_type wp = wp.range_type + +get_range_modifier : Type -> RangeModifier +get_range_modifier wp = wp.range_mod + +get_damage_type : Type -> DamageType +get_damage_type wp = wp.dmg_type + +get_damage_modifier : Type -> DamageModifier +get_damage_modifier wp = wp.dmg_mod + +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_max_damage : Type -> Int +get_max_damage wp = wp.dmg_max + +get_min_damage : Type -> Int +get_min_damage wp = wp.dmg_min + +apply_to_attributes : Type -> Struct.Attributes.Type -> Struct.Attributes.Type +apply_to_attributes wp atts = + let + impact = (20.0 * wp.coef) + full_impact = (-1 * (ceiling impact)) + quarter_impact = (-1 * (ceiling (impact / 4.0))) + in + case (wp.range_mod, wp.dmg_mod) of + (Long, Heavy) -> + (Struct.Attributes.mod_dexterity + full_impact + (Struct.Attributes.mod_speed full_impact atts) + ) + + (Long, Light) -> + (Struct.Attributes.mod_dexterity + full_impact + (Struct.Attributes.mod_speed quarter_impact atts) + ) + + (Short, Heavy) -> + (Struct.Attributes.mod_dexterity + quarter_impact + (Struct.Attributes.mod_speed full_impact atts) + ) + + (Short, Light) -> + (Struct.Attributes.mod_dexterity + quarter_impact + (Struct.Attributes.mod_speed quarter_impact atts) + ) + +finish_decoding : PartiallyDecoded -> Type +finish_decoding add_weapon = + (new + add_weapon.id + add_weapon.nam + add_weapon.cf + ( + case add_weapon.rt of + "m" -> Melee + _ -> Ranged + ) + ( + case add_weapon.rm of + "l" -> Long + _ -> Short + ) + ( + case add_weapon.dt of + "s" -> Slash + "p" -> Pierce + _ -> Blunt + ) + ( + case add_weapon.dm of + "l" -> Light + _ -> Heavy + ) + ) + +decoder : (Json.Decode.Decoder Type) +decoder = + (Json.Decode.map + (finish_decoding) + (Json.Decode.Pipeline.decode + PartiallyDecoded + |> (Json.Decode.Pipeline.required "id" Json.Decode.int) + |> (Json.Decode.Pipeline.required "nam" Json.Decode.string) + |> (Json.Decode.Pipeline.required "rt" Json.Decode.string) + |> (Json.Decode.Pipeline.required "rm" Json.Decode.string) + |> (Json.Decode.Pipeline.required "dt" Json.Decode.string) + |> (Json.Decode.Pipeline.required "dm" Json.Decode.string) + |> (Json.Decode.Pipeline.required "cf" Json.Decode.float) + ) + ) + +none : Type +none = + (new + 0 + "None" + 0.0 + Melee + Short + Blunt + Light + ) diff --git a/src/character/src/Struct/WeaponSet.elm b/src/character/src/Struct/WeaponSet.elm new file mode 100644 index 0000000..de96daf --- /dev/null +++ b/src/character/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/character/src/Update/DisplayCharacterInfo.elm b/src/character/src/Update/DisplayCharacterInfo.elm new file mode 100644 index 0000000..e482e2f --- /dev/null +++ b/src/character/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/character/src/Update/HandleServerReply.elm b/src/character/src/Update/HandleServerReply.elm new file mode 100644 index 0000000..ff6cc67 --- /dev/null +++ b/src/character/src/Update/HandleServerReply.elm @@ -0,0 +1,230 @@ +module Update.HandleServerReply exposing (apply_to) + +-- Elm ------------------------------------------------------------------------- +import Array + +import Delay + +import Dict + +import Http + +import Time + +-- Map ------------------------------------------------------------------- +import Struct.Armor +import Struct.Map +import Struct.Character +import Struct.Error +import Struct.Event +import Struct.Model +import Struct.ServerReply +import Struct.Tile +import Struct.TurnResult +import Struct.TurnResultAnimator +import Struct.UI +import Struct.Weapon + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +weapon_getter : Struct.Model.Type -> Struct.Weapon.Ref -> Struct.Weapon.Type +weapon_getter model ref = + case (Dict.get ref model.weapons) of + (Just w) -> w + Nothing -> Struct.Weapon.none + +armor_getter : Struct.Model.Type -> Struct.Armor.Ref -> Struct.Armor.Type +armor_getter model ref = + case (Dict.get ref model.armors) of + (Just w) -> w + Nothing -> Struct.Armor.none + +----------- + +add_armor : ( + Struct.Armor.Type -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) + ) +add_armor ar current_state = + case current_state of + (_, (Just _)) -> current_state + (model, _) -> ((Struct.Model.add_armor ar model), Nothing) + +add_tile : ( + Struct.Tile.Type -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) + ) +add_tile tl current_state = + case current_state of + (_, (Just _)) -> current_state + (model, _) -> ((Struct.Model.add_tile tl model), Nothing) + +add_weapon : ( + Struct.Weapon.Type -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) + ) +add_weapon wp current_state = + case current_state of + (_, (Just _)) -> current_state + (model, _) -> ((Struct.Model.add_weapon wp model), Nothing) + +add_character : ( + (Struct.Character.Type, Int, Int, Int) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) + ) +add_character char_and_refs current_state = + case current_state of + (_, (Just _)) -> current_state + (model, _) -> + let + (char, awp_ref, swp_ref, ar_ref) = char_and_refs + awp = (weapon_getter model awp_ref) + swp = (weapon_getter model swp_ref) + ar = (armor_getter model ar_ref) + in + ( + (Struct.Model.add_character + (Struct.Character.fill_missing_equipment awp swp ar char) + model + ), + Nothing + ) + +set_map : ( + Struct.Map.Type -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) + ) +set_map map current_state = + case current_state of + (_, (Just _)) -> current_state + (model, _) -> + ( + {model | + map = + (Struct.Map.solve_tiles model.tiles map) + }, + Nothing + ) + +add_to_timeline : ( + (List Struct.TurnResult.Type) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) + ) +add_to_timeline turn_results current_state = + case current_state of + (_, (Just _)) -> current_state + + (model, _) -> + ( + {model | + animator = + (Struct.TurnResultAnimator.maybe_new + (List.reverse turn_results) + False + ), + timeline = + (Array.append + (Array.fromList turn_results) + model.timeline + ), + ui = + (Struct.UI.set_displayed_tab + Struct.UI.TimelineTab + model.ui + ) + }, + Nothing + ) + +set_timeline : ( + (List Struct.TurnResult.Type) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) + ) +set_timeline turn_results current_state = + case current_state of + (_, (Just _)) -> current_state + + (model, _) -> + ( + {model | timeline = (Array.fromList turn_results)}, + Nothing + ) + +apply_command : ( + Struct.ServerReply.Type -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) -> + (Struct.Model.Type, (Maybe Struct.Error.Type)) + ) +apply_command command current_state = + case command of + (Struct.ServerReply.AddWeapon wp) -> + (add_weapon wp current_state) + + (Struct.ServerReply.AddArmor ar) -> + (add_armor ar current_state) + + (Struct.ServerReply.AddTile tl) -> + (add_tile tl current_state) + + (Struct.ServerReply.AddCharacter char) -> + (add_character char current_state) + + (Struct.ServerReply.SetMap map) -> + (set_map map current_state) + + (Struct.ServerReply.TurnResults results) -> + (add_to_timeline results current_state) + + (Struct.ServerReply.SetTimeline timeline) -> + (set_timeline timeline current_state) + + Struct.ServerReply.Okay -> current_state + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +apply_to : ( + Struct.Model.Type -> + (Result Http.Error (List Struct.ServerReply.Type)) -> + (Struct.Model.Type, (Cmd Struct.Event.Type)) + ) +apply_to model query_result = + case query_result of + (Result.Err error) -> + ( + (Struct.Model.invalidate + (Struct.Error.new Struct.Error.Networking (toString error)) + model + ), + Cmd.none + ) + + (Result.Ok commands) -> + let + new_model = + ( + case (List.foldl (apply_command) (model, Nothing) commands) of + (updated_model, Nothing) -> updated_model + (_, (Just error)) -> (Struct.Model.invalidate error model) + ) + in + ( + new_model, + if (new_model.animator == Nothing) + then + Cmd.none + else + (Delay.after 1 Time.millisecond Struct.Event.AnimationEnded) + ) diff --git a/src/character/src/Update/SelectCharacter.elm b/src/character/src/Update/SelectCharacter.elm new file mode 100644 index 0000000..1137435 --- /dev/null +++ b/src/character/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_attack_range weapon) + (Struct.Weapon.get_defense_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/character/src/Update/SelectTab.elm b/src/character/src/Update/SelectTab.elm new file mode 100644 index 0000000..d15a463 --- /dev/null +++ b/src/character/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/character/src/Update/SendLoadRosterRequest.elm b/src/character/src/Update/SendLoadRosterRequest.elm new file mode 100644 index 0000000..b7b5f11 --- /dev/null +++ b/src/character/src/Update/SendLoadRosterRequest.elm @@ -0,0 +1,29 @@ +module Update.SendLoadRosterRequest exposing (apply_to) +-- Elm ------------------------------------------------------------------------- + +-- Map ------------------------------------------------------------------- +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 = + ( + (Struct.Model.reset model), + (case (Comm.LoadRoster.try model) of + (Just cmd) -> cmd + Nothing -> Cmd.none + ) + ) + diff --git a/src/character/src/Update/SetRequestedHelp.elm b/src/character/src/Update/SetRequestedHelp.elm new file mode 100644 index 0000000..dfc58db --- /dev/null +++ b/src/character/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/character/src/Util/Array.elm b/src/character/src/Util/Array.elm new file mode 100644 index 0000000..9e57c18 --- /dev/null +++ b/src/character/src/Util/Array.elm @@ -0,0 +1,34 @@ +module Util.Array exposing + ( + update, + update_unsafe, + filter_first + ) + +import Array + +update : ( + Int -> + ((Maybe t) -> (Maybe t)) -> + (Array.Array t) -> + (Array.Array t) + ) +update index fun array = + case (fun (Array.get index array)) of + Nothing -> array + (Just e) -> (Array.set index e array) + +update_unsafe : ( + Int -> + (t -> t) -> + (Array.Array t) -> + (Array.Array t) + ) +update_unsafe index fun array = + case (Array.get index array) of + Nothing -> array + (Just e) -> (Array.set index (fun e) array) + +filter_first : (t -> Bool) -> (Array.Array t) -> (Maybe t) +filter_first fun array = + (Array.get 0 (Array.filter fun array)) diff --git a/src/character/src/Util/Html.elm b/src/character/src/Util/Html.elm new file mode 100644 index 0000000..42eadba --- /dev/null +++ b/src/character/src/Util/Html.elm @@ -0,0 +1,6 @@ +module Util.Html exposing (nothing) + +import Html + +nothing : (Html.Html a) +nothing = (Html.text "") diff --git a/src/character/src/Util/List.elm b/src/character/src/Util/List.elm new file mode 100644 index 0000000..2bc5217 --- /dev/null +++ b/src/character/src/Util/List.elm @@ -0,0 +1,16 @@ +module Util.List exposing (..) + +import List + +pop : List a -> (Maybe (a, List a)) +pop l = + case + ((List.head l), (List.tail l)) + of + (Nothing, _) -> Nothing + (_ , Nothing) -> Nothing + ((Just head), (Just tail)) -> (Just (head, tail)) + +get_first : (a -> Bool) -> (List a) -> (Maybe a) +get_first fun list = + (List.head (List.filter fun list)) diff --git a/src/character/src/View/Character.elm b/src/character/src/View/Character.elm new file mode 100644 index 0000000..d33feb1 --- /dev/null +++ b/src/character/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/character/src/View/Controlled.elm b/src/character/src/View/Controlled.elm new file mode 100644 index 0000000..e0e20bf --- /dev/null +++ b/src/character/src/View/Controlled.elm @@ -0,0 +1,133 @@ +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") ] + ) + +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 : (Html.Html Struct.Event.Type) +inventory_button = + (Html.button + [ (Html.Events.onClick Struct.Event.WeaponSwitchRequest) ] + [ (Html.text "Switch Weapon") ] + ) + +get_available_actions : ( + Struct.CharacterTurn.Type -> + (List (Html.Html Struct.Event.Type)) + ) +get_available_actions char_turn = + case (Struct.CharacterTurn.get_state char_turn) of + Struct.CharacterTurn.SelectedCharacter -> + [ + (attack_button char_turn), + (inventory_button), + (end_turn_button " Doing Nothing"), + (abort_button) + ] + + Struct.CharacterTurn.MovedCharacter -> + [ + (end_turn_button " Without Attacking"), + (abort_button) + ] + + Struct.CharacterTurn.ChoseTarget -> + [ + (end_turn_button " By Attacking"), + (abort_button) + ] + + _ -> + [ + ] + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : Struct.CharacterTurn.Type -> Int -> (Html.Html Struct.Event.Type) +get_html char_turn player_ix = + case + (Struct.CharacterTurn.try_getting_active_character char_turn) + of + (Just char) -> + (Html.div + [(Html.Attributes.class "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/character/src/View/Controlled/CharacterCard.elm b/src/character/src/View/Controlled/CharacterCard.elm new file mode 100644 index 0000000..0e29502 --- /dev/null +++ b/src/character/src/View/Controlled/CharacterCard.elm @@ -0,0 +1,611 @@ +module View.Controlled.CharacterCard exposing + ( + get_minimal_html, + get_summary_html, + get_full_html + ) + +-- Elm ------------------------------------------------------------------------- +import Html +import Html.Attributes +import Html.Events + +-- Map ------------------------------------------------------------------- +import Struct.Armor +import Struct.Attributes +import Struct.Character +import Struct.CharacterTurn +import Struct.Event +import Struct.HelpRequest +import Struct.Navigator +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_details : ( + Struct.Statistics.Type -> + Struct.Weapon.Type -> + (Html.Html Struct.Event.Type) + ) +get_weapon_details stats weapon = + (Html.div + [ + (Html.Attributes.class "battle-character-card-weapon") + ] + [ + (Html.div + [ + (Html.Attributes.class "battle-character-card-weapon-name") + ] + [ + (Html.text (Struct.Weapon.get_name weapon)) + ] + ), + (Html.div + [ + (Html.Attributes.class "battle-character-card-weapon-name") + ] + [ + (Html.text + ( + "[" + ++ (toString (Struct.Statistics.get_damage_min stats)) + ++ ", " + ++ (toString (Struct.Statistics.get_damage_max stats)) + ++ "] " + ++ + (case (Struct.Weapon.get_damage_type weapon) of + Struct.Weapon.Slash -> "slashing " + Struct.Weapon.Pierce -> "piercing " + Struct.Weapon.Blunt -> "bludgeoning " + ) + ++ + (case (Struct.Weapon.get_range_type weapon) of + Struct.Weapon.Ranged -> "ranged" + Struct.Weapon.Melee -> "melee" + ) + ) + ) + ] + ) + ] + ) + +get_weapon_summary : ( + Struct.Weapon.Type -> + (Html.Html Struct.Event.Type) + ) +get_weapon_summary weapon = + (Html.div + [ + (Html.Attributes.class "battle-character-card-weapon-summary") + ] + [ + (Html.div + [ + (Html.Attributes.class "battle-character-card-weapon-name") + ] + [ + (Html.text (Struct.Weapon.get_name weapon)) + ] + ), + (Html.div + [ + (Html.Attributes.class "battle-character-card-weapon-name") + ] + [ + (Html.text + ( + (case (Struct.Weapon.get_damage_type weapon) of + Struct.Weapon.Slash -> "Slashing " + Struct.Weapon.Pierce -> "Piercing " + Struct.Weapon.Blunt -> "Bludgeoning " + ) + ++ + (case (Struct.Weapon.get_range_type weapon) of + Struct.Weapon.Ranged -> "ranged" + Struct.Weapon.Melee -> "melee" + ) + ) + ) + ] + ) + ] + ) + +get_armor_details : ( + Struct.Armor.Type -> + (Html.Html Struct.Event.Type) + ) +get_armor_details 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-character-card-armor-stats") + ] + [ + (stat_name "Slash"), + (stat_val + (Struct.Armor.get_resistance_to Struct.Weapon.Slash armor) + False + ), + (stat_name "Pierc."), + (stat_val + (Struct.Armor.get_resistance_to Struct.Weapon.Pierce armor) + False + ), + (stat_name "Blund."), + (stat_val + (Struct.Armor.get_resistance_to Struct.Weapon.Blunt armor) + False + ) + ] + ) + ] + ) + +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 + "" + ) + ) + ) + ] + ) + +att_dual_val : Int -> Int -> (Html.Html Struct.Event.Type) +att_dual_val base active = + let + diff = (active - base) + in + (Html.div + [ + (Html.Attributes.class "battle-character-card-att-dual-val") + ] + [ + (Html.text + ( + (toString base) + ++ " (" + ++ + ( + if (diff > 0) + then + ("+" ++ (toString diff)) + else + if (diff == 0) + then + "~" + else + (toString diff) + ) + ++ ")" + ) + ) + ] + ) + +get_relevant_stats : ( + Struct.Character.Type -> + Struct.Weapon.Type -> + (Html.Html Struct.Event.Type) + ) +get_relevant_stats char weapon = + let + stats = (Struct.Character.get_statistics char) + in + (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 + (case (Struct.Weapon.get_range_type weapon) of + Struct.Weapon.Ranged -> 0 + Struct.Weapon.Melee -> (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) + ] + ) + +get_attributes : ( + Struct.Character.Type -> + Struct.Weapon.Type -> + Struct.Armor.Type -> + (Html.Html Struct.Event.Type) + ) +get_attributes char weapon armor = + let + base_atts = (Struct.Character.get_attributes char) + active_atts = + (Struct.Armor.apply_to_attributes + armor + (Struct.Weapon.apply_to_attributes weapon base_atts) + ) + in + (Html.div + [ + (Html.Attributes.class "battle-character-card-stats") + ] + [ + (stat_name "Con"), + (att_dual_val + (Struct.Attributes.get_constitution base_atts) + (Struct.Attributes.get_constitution active_atts) + ), + (stat_name "Dex"), + (att_dual_val + (Struct.Attributes.get_dexterity base_atts) + (Struct.Attributes.get_dexterity active_atts) + ), + (stat_name "Int"), + (att_dual_val + (Struct.Attributes.get_intelligence base_atts) + (Struct.Attributes.get_intelligence active_atts) + ), + (stat_name "Min"), + (att_dual_val + (Struct.Attributes.get_mind base_atts) + (Struct.Attributes.get_mind active_atts) + ), + (stat_name "Spe"), + (att_dual_val + (Struct.Attributes.get_speed base_atts) + (Struct.Attributes.get_speed active_atts) + ), + (stat_name "Str"), + (att_dual_val + (Struct.Attributes.get_strength base_atts) + (Struct.Attributes.get_strength active_atts) + ) + ] + ) + +-------------------------------------------------------------------------------- +-- 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) + secondary_weapon = (Struct.WeaponSet.get_secondary_weapon weapon_set) + 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 char_statistics main_weapon), + (get_armor_details (Struct.Character.get_armor char)), + (get_relevant_stats char main_weapon), + (get_weapon_summary 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) + secondary_weapon = (Struct.WeaponSet.get_secondary_weapon weapon_set) + armor = (Struct.Character.get_armor 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 char_statistics main_weapon), + (get_armor_details armor), + (get_relevant_stats char main_weapon), + (get_weapon_summary secondary_weapon), + (get_attributes char main_weapon armor) + ] + ) diff --git a/src/character/src/View/Controlled/ManualControls.elm b/src/character/src/View/Controlled/ManualControls.elm new file mode 100644 index 0000000..1dceafb --- /dev/null +++ b/src/character/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/character/src/View/Controlled/Targets.elm b/src/character/src/View/Controlled/Targets.elm new file mode 100644 index 0000000..eee5a54 --- /dev/null +++ b/src/character/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/character/src/View/Gauge.elm b/src/character/src/View/Gauge.elm new file mode 100644 index 0000000..cf89f3a --- /dev/null +++ b/src/character/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/character/src/View/MainMenu.elm b/src/character/src/View/MainMenu.elm new file mode 100644 index 0000000..9f3099b --- /dev/null +++ b/src/character/src/View/MainMenu.elm @@ -0,0 +1,38 @@ +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)) ] + ) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html : (Html.Html Struct.Event.Type) +get_html = + (Html.div + [ + (Html.Attributes.class "battle-main-menu") + ] + (List.map + (get_menu_button_html) + (Struct.UI.get_all_tabs) + ) + ) diff --git a/src/character/src/View/MessageBoard.elm b/src/character/src/View/MessageBoard.elm new file mode 100644 index 0000000..736f938 --- /dev/null +++ b/src/character/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/character/src/View/MessageBoard/Animator.elm b/src/character/src/View/MessageBoard/Animator.elm new file mode 100644 index 0000000..49bb83a --- /dev/null +++ b/src/character/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/character/src/View/MessageBoard/Animator/Attack.elm b/src/character/src/View/MessageBoard/Animator/Attack.elm new file mode 100644 index 0000000..437a76d --- /dev/null +++ b/src/character/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/character/src/View/MessageBoard/Error.elm b/src/character/src/View/MessageBoard/Error.elm new file mode 100644 index 0000000..797d89f --- /dev/null +++ b/src/character/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/character/src/View/MessageBoard/Help.elm b/src/character/src/View/MessageBoard/Help.elm new file mode 100644 index 0000000..6c20bbc --- /dev/null +++ b/src/character/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/character/src/View/MessageBoard/Help/Guide.elm b/src/character/src/View/MessageBoard/Help/Guide.elm new file mode 100644 index 0000000..0a41e91 --- /dev/null +++ b/src/character/src/View/MessageBoard/Help/Guide.elm @@ -0,0 +1,100 @@ +module View.MessageBoard.Help.Guide exposing (get_html_contents) + +-- Elm ------------------------------------------------------------------------- +import Html +import Html.Attributes + +-- 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 a Target"), + (Html.text + ( + "You can now choose a target in range. Dashed tiles indicate" + ++ " where your character will not be able to defend themselves" + ++ " against counter attacks." + ) + ) + ] + +get_chose_target_html_contents : (List (Html.Html Struct.Event.Type)) +get_chose_target_html_contents = + [ + (get_header_html "Finalizing the Character's Turn"), + (Html.text + ( + "If you are satisfied with your choices, you can end this" + ++ " character's turn and see the results unfold. Otherwise, click" + ++ " on the abort button to undo it all." + ) + ) + ] + +get_default_html_contents : (List (Html.Html Struct.Event.Type)) +get_default_html_contents = + [ + (get_header_html "Selecting a Character"), + (Html.text + ( + "Click once on a character to focus them. This will show you" + ++ " their stats, equipment, and other infos. If they are in" + ++ " your team and active (the pulsating characters)," + ++ " clicking on them again will let you take control." + ) + ) + ] + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +get_html_contents : ( + Struct.Model.Type -> + (List (Html.Html Struct.Event.Type)) + ) +get_html_contents model = + case (Struct.CharacterTurn.get_state model.char_turn) of + Struct.CharacterTurn.SelectedCharacter -> + (get_selected_character_html_contents) + + Struct.CharacterTurn.MovedCharacter -> + (get_moved_character_html_contents) + + Struct.CharacterTurn.ChoseTarget -> + (get_chose_target_html_contents) + + _ -> + (get_default_html_contents) diff --git a/src/character/src/View/MessageBoard/Help/Rank.elm b/src/character/src/View/MessageBoard/Help/Rank.elm new file mode 100644 index 0000000..4a01e75 --- /dev/null +++ b/src/character/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/character/src/View/SubMenu.elm b/src/character/src/View/SubMenu.elm new file mode 100644 index 0000000..e661b9c --- /dev/null +++ b/src/character/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/character/src/View/SubMenu/Characters.elm b/src/character/src/View/SubMenu/Characters.elm new file mode 100644 index 0000000..396dbee --- /dev/null +++ b/src/character/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/character/src/View/SubMenu/Settings.elm b/src/character/src/View/SubMenu/Settings.elm new file mode 100644 index 0000000..e0ad4d7 --- /dev/null +++ b/src/character/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/character/src/View/SubMenu/Status.elm b/src/character/src/View/SubMenu/Status.elm new file mode 100644 index 0000000..485704e --- /dev/null +++ b/src/character/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/character/src/View/SubMenu/Status/CharacterInfo.elm b/src/character/src/View/SubMenu/Status/CharacterInfo.elm new file mode 100644 index 0000000..814ce5f --- /dev/null +++ b/src/character/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/character/src/View/SubMenu/Status/TileInfo.elm b/src/character/src/View/SubMenu/Status/TileInfo.elm new file mode 100644 index 0000000..920b5ce --- /dev/null +++ b/src/character/src/View/SubMenu/Status/TileInfo.elm @@ -0,0 +1,137 @@ +module View.SubMenu.Status.TileInfo exposing (get_html) + +-- Elm ------------------------------------------------------------------------- +import Dict + +import Html +import Html.Attributes + +-- Struct.Map ------------------------------------------------------------------- +import Constants.Movement + +import Struct.Map +import Struct.Event +import Struct.Location +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) + ++ "}" + ) + ) + ] + ) + +-------------------------------------------------------------------------------- +-- 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) + ] + ) + ] + ) + + Nothing -> (Html.text "Error: Unknown tile location selected.") diff --git a/src/character/src/View/SubMenu/Timeline.elm b/src/character/src/View/SubMenu/Timeline.elm new file mode 100644 index 0000000..7fb1813 --- /dev/null +++ b/src/character/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/character/src/View/SubMenu/Timeline/Attack.elm b/src/character/src/View/SubMenu/Timeline/Attack.elm new file mode 100644 index 0000000..682540d --- /dev/null +++ b/src/character/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/character/src/View/SubMenu/Timeline/Movement.elm b/src/character/src/View/SubMenu/Timeline/Movement.elm new file mode 100644 index 0000000..0746f1f --- /dev/null +++ b/src/character/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/character/src/View/SubMenu/Timeline/PlayerDefeat.elm b/src/character/src/View/SubMenu/Timeline/PlayerDefeat.elm new file mode 100644 index 0000000..db5e023 --- /dev/null +++ b/src/character/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/character/src/View/SubMenu/Timeline/PlayerTurnStart.elm b/src/character/src/View/SubMenu/Timeline/PlayerTurnStart.elm new file mode 100644 index 0000000..a6486fa --- /dev/null +++ b/src/character/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/character/src/View/SubMenu/Timeline/PlayerVictory.elm b/src/character/src/View/SubMenu/Timeline/PlayerVictory.elm new file mode 100644 index 0000000..4d47f62 --- /dev/null +++ b/src/character/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/character/src/View/SubMenu/Timeline/WeaponSwitch.elm b/src/character/src/View/SubMenu/Timeline/WeaponSwitch.elm new file mode 100644 index 0000000..499e0c3 --- /dev/null +++ b/src/character/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/character/www/index.html b/src/character/www/index.html new file mode 100644 index 0000000..7954e54 --- /dev/null +++ b/src/character/www/index.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html> + <head> + <link rel="stylesheet" type="text/css" href="../css/global.css"> + <link rel="stylesheet" type="text/css" href="../css/character.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> + 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); + </script> + </body> +</html> |