aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornsensfel <SpamShield0@noot-noot.org>2018-03-20 18:04:39 +0100
committernsensfel <SpamShield0@noot-noot.org>2018-03-20 18:04:39 +0100
commit7a49310e8d1909201d790e61297caeed0145b0c3 (patch)
tree5e9c2a5d5dd0f8d1e43d16c62b16c6b4fbcf6a79
parentce67d4a66521cd5b3e573ef71ea23d4c60e06d49 (diff)
downloadtacticians-client-altar.zip
tacticians-client-altar.tar.bz2
Starting to work on the Altar page.altar
-rw-r--r--Makefile7
-rw-r--r--src/altar/Makefile19
-rw-r--r--src/altar/elm-package.json17
-rw-r--r--src/altar/src/Comm/AddChar.elm40
-rw-r--r--src/altar/src/Comm/Send.elm74
-rw-r--r--src/altar/src/Constants/IO.elm13
-rw-r--r--src/altar/src/Data/Weapons.elm309
-rw-r--r--src/altar/src/ElmModule/Init.elm27
-rw-r--r--src/altar/src/ElmModule/Subscriptions.elm7
-rw-r--r--src/altar/src/ElmModule/Update.elm62
-rw-r--r--src/altar/src/ElmModule/View.elm54
-rw-r--r--src/altar/src/Main.elm22
-rw-r--r--src/altar/src/Struct/Attributes.elm134
-rw-r--r--src/altar/src/Struct/Character.elm174
-rw-r--r--src/altar/src/Struct/Error.elm43
-rw-r--r--src/altar/src/Struct/Event.elm27
-rw-r--r--src/altar/src/Struct/Model.elm89
-rw-r--r--src/altar/src/Struct/ServerReply.elm27
-rw-r--r--src/altar/src/Struct/Statistics.elm170
-rw-r--r--src/altar/src/Struct/UI.elm124
-rw-r--r--src/altar/src/Struct/Weapon.elm150
-rw-r--r--src/altar/src/Struct/WeaponSet.elm39
-rw-r--r--src/altar/src/Update/HandleServerReply.elm154
-rw-r--r--src/altar/src/Update/SelectCharacter.elm203
-rw-r--r--src/altar/src/Update/SelectTab.elm25
-rw-r--r--src/altar/src/Update/SwitchWeapon.elm100
-rw-r--r--src/altar/src/Util/Array.elm25
-rw-r--r--src/altar/src/Util/Html.elm6
-rw-r--r--src/altar/src/Util/List.elm12
-rw-r--r--src/altar/www/index.html13
-rw-r--r--src/altar/www/style.css0
31 files changed, 2163 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index 1e9d569..ec9d717 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,7 @@
-MODULES = battlemap global asset
-SRC_DIR = ${CURDIR}/src
-WWW_DIR = ${CURDIR}/www
+MODULES ?= battlemap global asset
+CONF_DIR ?= ${CURDIR}/conf
+SRC_DIR ?= ${CURDIR}/src
+WWW_DIR ?= ${CURDIR}/www
MODULES_SRC = $(addprefix $(SRC_DIR)/,$(MODULES))
MODULES_WWW = $(addprefix $(WWW_DIR)/,$(MODULES))
diff --git a/src/altar/Makefile b/src/altar/Makefile
new file mode 100644
index 0000000..d5372f1
--- /dev/null
+++ b/src/altar/Makefile
@@ -0,0 +1,19 @@
+ELM_CC = elm-make --warn
+
+SRC_DIR = src
+WWW_DIR = www
+WWW_SCRIPT_DIR = $(WWW_DIR)/script
+
+MAIN_MODULE = $(SRC_DIR)/Main.elm
+SUB_MODULES = $(shell find $(SRC_DIR) -type f | grep "elm$$")
+
+$(WWW_SCRIPT_DIR)/main.js: $(MAIN_MODULE) $(SUB_MODULES)
+ $(ELM_CC) $(MAIN_MODULE) --output $@
+
+build: $(WWW_SCRIPT_DIR)/main.js
+
+clean:
+ rm -f $(WWW_SCRIPT_DIR)/main.js
+
+reset:
+ rm -rf elm-stuff
diff --git a/src/altar/elm-package.json b/src/altar/elm-package.json
new file mode 100644
index 0000000..82d19f0
--- /dev/null
+++ b/src/altar/elm-package.json
@@ -0,0 +1,17 @@
+{
+ "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/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/altar/src/Comm/AddChar.elm b/src/altar/src/Comm/AddChar.elm
new file mode 100644
index 0000000..1270b0d
--- /dev/null
+++ b/src/altar/src/Comm/AddChar.elm
@@ -0,0 +1,40 @@
+module Comm.AddChar exposing (decode)
+
+-- Elm -------------------------------------------------------------------------
+import Dict
+
+import Json.Decode
+
+-- Battlemap -------------------------------------------------------------------
+import Data.Weapons
+
+import Struct.Character
+import Struct.Model
+import Struct.ServerReply
+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 -> Data.Weapons.none
+
+internal_decoder : Struct.Character.Type -> Struct.ServerReply.Type
+internal_decoder char = (Struct.ServerReply.AddCharacter char)
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+decode : (Struct.Model.Type -> (Json.Decode.Decoder Struct.ServerReply.Type))
+decode model =
+ (Json.Decode.map
+ (internal_decoder)
+ (Struct.Character.decoder (weapon_getter model))
+ )
diff --git a/src/altar/src/Comm/Send.elm b/src/altar/src/Comm/Send.elm
new file mode 100644
index 0000000..485b9b9
--- /dev/null
+++ b/src/altar/src/Comm/Send.elm
@@ -0,0 +1,74 @@
+module Comm.Send exposing (try_sending)
+
+-- Elm -------------------------------------------------------------------------
+import Http
+
+import Json.Decode
+import Json.Encode
+
+-- Battlemap -------------------------------------------------------------------
+import Comm.AddChar
+import Comm.SetMap
+import Comm.SetTimeline
+import Comm.TurnResults
+
+import Struct.Event
+import Struct.ServerReply
+import Struct.Model
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+internal_decoder : (
+ Struct.Model.Type ->
+ String ->
+ (Json.Decode.Decoder Struct.ServerReply.Type)
+ )
+internal_decoder model reply_type =
+ case reply_type of
+ "add_char" -> (Comm.AddChar.decode model)
+ "set_map" -> (Comm.SetMap.decode model)
+ "turn_results" -> (Comm.TurnResults.decode)
+ "set_timeline" -> (Comm.SetTimeline.decode)
+ other ->
+ (Json.Decode.fail
+ (
+ "Unknown server command \""
+ ++ other
+ ++ "\""
+ )
+ )
+
+decode : Struct.Model.Type -> (Json.Decode.Decoder Struct.ServerReply.Type)
+decode model =
+ (Json.Decode.field "msg" Json.Decode.string)
+ |> (Json.Decode.andThen (internal_decoder model))
+
+--------------------------------------------------------------------------------
+-- 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 model))
+ )
+ )
+ )
+
+ Nothing -> Nothing
diff --git a/src/altar/src/Constants/IO.elm b/src/altar/src/Constants/IO.elm
new file mode 100644
index 0000000..dbf6422
--- /dev/null
+++ b/src/altar/src/Constants/IO.elm
@@ -0,0 +1,13 @@
+module Constants.IO exposing (..)
+
+base_url : String
+base_url = "${BASE_URL}"
+
+altar_handler_url : String
+altar_handler_url = (base_url ++ "/handler/altar")
+
+altar_saving_handler : String
+altar_saving_handler = (battlemap_handler_url ++ "/save")
+
+altar_loading_handler : String
+altar_loading_handler = (battlemap_handler_url ++ "/load")
diff --git a/src/altar/src/Data/Weapons.elm b/src/altar/src/Data/Weapons.elm
new file mode 100644
index 0000000..e74d89e
--- /dev/null
+++ b/src/altar/src/Data/Weapons.elm
@@ -0,0 +1,309 @@
+module Data.Weapons exposing (generate_dict, none)
+-- Elm -------------------------------------------------------------------------
+import Dict
+
+-- Battlemap -------------------------------------------------------------------
+import Struct.Weapon
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+dataset : (List (Struct.Weapon.Ref, Struct.Weapon.Type))
+dataset =
+ [
+ -- TODO: have those in separate text files, and put them here only at
+ -- compilation.
+ (
+ 0,
+ (Struct.Weapon.new
+ 0
+ "None"
+ Struct.Weapon.Melee
+ Struct.Weapon.Short
+ Struct.Weapon.Blunt
+ Struct.Weapon.Light
+ )
+ ),
+ (
+ 1,
+ (Struct.Weapon.new
+ 1
+ "Dagger"
+ Struct.Weapon.Melee
+ Struct.Weapon.Short
+ Struct.Weapon.Slash
+ Struct.Weapon.Light
+ )
+ ),
+ (
+ 2,
+ (Struct.Weapon.new
+ 2
+ "Sword"
+ Struct.Weapon.Melee
+ Struct.Weapon.Short
+ Struct.Weapon.Slash
+ Struct.Weapon.Heavy
+ )
+ ),
+ (
+ 3,
+ (Struct.Weapon.new
+ 3
+ "Claymore"
+ Struct.Weapon.Melee
+ Struct.Weapon.Long
+ Struct.Weapon.Slash
+ Struct.Weapon.Light
+ )
+ ),
+ (
+ 4,
+ (Struct.Weapon.new
+ 4
+ "Bardiche"
+ Struct.Weapon.Melee
+ Struct.Weapon.Long
+ Struct.Weapon.Slash
+ Struct.Weapon.Heavy
+ )
+ ),
+ (
+ 5,
+ (Struct.Weapon.new
+ 5
+ "Stiletto"
+ Struct.Weapon.Melee
+ Struct.Weapon.Short
+ Struct.Weapon.Pierce
+ Struct.Weapon.Light
+ )
+ ),
+ (
+ 6,
+ (Struct.Weapon.new
+ 6
+ "Pickaxe"
+ Struct.Weapon.Melee
+ Struct.Weapon.Short
+ Struct.Weapon.Pierce
+ Struct.Weapon.Heavy
+ )
+ ),
+ (
+ 7,
+ (Struct.Weapon.new
+ 7
+ "Rapier"
+ Struct.Weapon.Melee
+ Struct.Weapon.Long
+ Struct.Weapon.Pierce
+ Struct.Weapon.Light
+ )
+ ),
+ (
+ 8,
+ (Struct.Weapon.new
+ 8
+ "Pike"
+ Struct.Weapon.Melee
+ Struct.Weapon.Long
+ Struct.Weapon.Pierce
+ Struct.Weapon.Heavy
+ )
+ ),
+ (
+ 9,
+ (Struct.Weapon.new
+ 9
+ "Club"
+ Struct.Weapon.Melee
+ Struct.Weapon.Short
+ Struct.Weapon.Blunt
+ Struct.Weapon.Light
+ )
+ ),
+ (
+ 10,
+ (Struct.Weapon.new
+ 10
+ "Mace"
+ Struct.Weapon.Melee
+ Struct.Weapon.Short
+ Struct.Weapon.Blunt
+ Struct.Weapon.Heavy
+ )
+ ),
+ (
+ 11,
+ (Struct.Weapon.new
+ 11
+ "Staff"
+ Struct.Weapon.Melee
+ Struct.Weapon.Long
+ Struct.Weapon.Blunt
+ Struct.Weapon.Light
+ )
+ ),
+ (
+ 12,
+ (Struct.Weapon.new
+ 12
+ "War Hammer"
+ Struct.Weapon.Melee
+ Struct.Weapon.Long
+ Struct.Weapon.Blunt
+ Struct.Weapon.Heavy
+ )
+ ),
+ (
+ 13,
+ (Struct.Weapon.new
+ 13
+ "Short Bow (Broadhead)"
+ Struct.Weapon.Ranged
+ Struct.Weapon.Short
+ Struct.Weapon.Slash
+ Struct.Weapon.Light
+ )
+ ),
+ (
+ 14,
+ (Struct.Weapon.new
+ 14
+ "Short Bow (Blunt)"
+ Struct.Weapon.Ranged
+ Struct.Weapon.Short
+ Struct.Weapon.Blunt
+ Struct.Weapon.Light
+ )
+ ),
+ (
+ 15,
+ (Struct.Weapon.new
+ 15
+ "Short Bow (Bodkin Point)"
+ Struct.Weapon.Ranged
+ Struct.Weapon.Short
+ Struct.Weapon.Pierce
+ Struct.Weapon.Light
+ )
+ ),
+ (
+ 16,
+ (Struct.Weapon.new
+ 16
+ "Long Bow (Broadhead)"
+ Struct.Weapon.Ranged
+ Struct.Weapon.Long
+ Struct.Weapon.Slash
+ Struct.Weapon.Light
+ )
+ ),
+ (
+ 17,
+ (Struct.Weapon.new
+ 17
+ "Long Bow (Blunt)"
+ Struct.Weapon.Ranged
+ Struct.Weapon.Long
+ Struct.Weapon.Blunt
+ Struct.Weapon.Light
+ )
+ ),
+ (
+ 18,
+ (Struct.Weapon.new
+ 18
+ "Long Bow (Bodkin Point)"
+ Struct.Weapon.Ranged
+ Struct.Weapon.Long
+ Struct.Weapon.Pierce
+ Struct.Weapon.Light
+ )
+ ),
+ (
+ 19,
+ (Struct.Weapon.new
+ 19
+ "Crossbow (Broadhead)"
+ Struct.Weapon.Ranged
+ Struct.Weapon.Short
+ Struct.Weapon.Slash
+ Struct.Weapon.Heavy
+ )
+ ),
+ (
+ 20,
+ (Struct.Weapon.new
+ 20
+ "Crossbow (Blunt)"
+ Struct.Weapon.Ranged
+ Struct.Weapon.Short
+ Struct.Weapon.Blunt
+ Struct.Weapon.Heavy
+ )
+ ),
+ (
+ 21,
+ (Struct.Weapon.new
+ 21
+ "Crossbow (Bodkin Point)"
+ Struct.Weapon.Ranged
+ Struct.Weapon.Short
+ Struct.Weapon.Pierce
+ Struct.Weapon.Heavy
+ )
+ ),
+ (
+ 22,
+ (Struct.Weapon.new
+ 22
+ "Arbalest (Broadhead)"
+ Struct.Weapon.Ranged
+ Struct.Weapon.Long
+ Struct.Weapon.Slash
+ Struct.Weapon.Heavy
+ )
+ ),
+ (
+ 23,
+ (Struct.Weapon.new
+ 23
+ "Arbalest (Blunt)"
+ Struct.Weapon.Ranged
+ Struct.Weapon.Long
+ Struct.Weapon.Blunt
+ Struct.Weapon.Heavy
+ )
+ ),
+ (
+ 24,
+ (Struct.Weapon.new
+ 24
+ "Arbalest (Bodkin Point)"
+ Struct.Weapon.Ranged
+ Struct.Weapon.Long
+ Struct.Weapon.Pierce
+ Struct.Weapon.Heavy
+ )
+ )
+ ]
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+generate_dict : (Dict.Dict Struct.Weapon.Ref Struct.Weapon.Type)
+generate_dict = (Dict.fromList dataset)
+
+-- If it's not found.
+none : (Struct.Weapon.Type)
+none =
+ (Struct.Weapon.new
+ 0
+ "None"
+ Struct.Weapon.Melee
+ Struct.Weapon.Short
+ Struct.Weapon.Blunt
+ Struct.Weapon.Light
+ )
diff --git a/src/altar/src/ElmModule/Init.elm b/src/altar/src/ElmModule/Init.elm
new file mode 100644
index 0000000..f8fb439
--- /dev/null
+++ b/src/altar/src/ElmModule/Init.elm
@@ -0,0 +1,27 @@
+module ElmModule.Init exposing (init)
+
+-- Battlemap -------------------------------------------------------------------
+import Comm.LoadBattlemap
+
+import Struct.Event
+import Struct.Model
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+init : (Struct.Model.Type, (Cmd Struct.Event.Type))
+init =
+ let
+ model = (Struct.Model.new)
+ in
+ (
+ model,
+ (case (Comm.LoadBattlemap.try model) of
+ (Just cmd) -> cmd
+ Nothing -> Cmd.none
+ )
+ )
diff --git a/src/altar/src/ElmModule/Subscriptions.elm b/src/altar/src/ElmModule/Subscriptions.elm
new file mode 100644
index 0000000..c8126b1
--- /dev/null
+++ b/src/altar/src/ElmModule/Subscriptions.elm
@@ -0,0 +1,7 @@
+module ElmModule.Subscriptions exposing (..)
+
+import Struct.Model
+import Struct.Event
+
+subscriptions : Struct.Model.Type -> (Sub Struct.Event.Type)
+subscriptions model = Sub.none
diff --git a/src/altar/src/ElmModule/Update.elm b/src/altar/src/ElmModule/Update.elm
new file mode 100644
index 0000000..22217bf
--- /dev/null
+++ b/src/altar/src/ElmModule/Update.elm
@@ -0,0 +1,62 @@
+module ElmModule.Update exposing (update)
+
+-- Elm -------------------------------------------------------------------------
+
+-- Battlemap -------------------------------------------------------------------
+import Struct.Event
+import Struct.Model
+
+import Update.ChangeScale
+import Update.DisplayCharacterInfo
+import Update.EndTurn
+import Update.HandleServerReply
+import Update.RequestDirection
+import Update.SelectCharacter
+import Update.SelectTab
+import Update.SelectTile
+import Update.SendLoadBattlemapRequest
+import Update.SwitchTeam
+import Update.SwitchWeapon
+
+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.DirectionRequested d) ->
+ (Update.RequestDirection.apply_to new_model d)
+
+ (Struct.Event.TileSelected loc) ->
+ (Update.SelectTile.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.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.DebugLoadBattlemapRequest) ->
+ (Update.SendLoadBattlemapRequest.apply_to new_model)
+
+ (Struct.Event.ServerReplied result) ->
+ (Update.HandleServerReply.apply_to model result)
+
+ Struct.Event.WeaponSwitchRequest ->
+ (Update.SwitchWeapon.apply_to new_model)
diff --git a/src/altar/src/ElmModule/View.elm b/src/altar/src/ElmModule/View.elm
new file mode 100644
index 0000000..63e382f
--- /dev/null
+++ b/src/altar/src/ElmModule/View.elm
@@ -0,0 +1,54 @@
+module ElmModule.View exposing (view)
+
+-- Elm -------------------------------------------------------------------------
+import Html
+import Html.Attributes
+
+-- Battlemap -------------------------------------------------------------------
+import Struct.Event
+import Struct.Model
+
+import View.Battlemap
+import View.SideBar
+import View.Footer
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+view : Struct.Model.Type -> (Html.Html Struct.Event.Type)
+view model =
+ (Html.div
+ [
+ (Html.Attributes.class "fullscreen-module")
+ ]
+ [
+ (Html.div
+ [
+ (Html.Attributes.class "battlemap-left-panel")
+ ]
+ [
+ (Html.div
+ [
+ (Html.Attributes.class "battlemap-container")
+ ]
+ [
+ (View.Battlemap.get_html model)
+ ]
+ ),
+ (View.Footer.get_html model)
+ ]
+ ),
+ (Html.div
+ [
+ (Html.Attributes.class "battlemap-right-panel")
+ ]
+ [
+ (View.SideBar.get_html model)
+ ]
+ )
+ ]
+ )
diff --git a/src/altar/src/Main.elm b/src/altar/src/Main.elm
new file mode 100644
index 0000000..96b267f
--- /dev/null
+++ b/src/altar/src/Main.elm
@@ -0,0 +1,22 @@
+-- Elm ------------------------------------------------------------------------
+import Html
+
+-- Battlemap -------------------------------------------------------------------
+import Struct.Model
+import Struct.Event
+
+import ElmModule.Init
+import ElmModule.Subscriptions
+import ElmModule.View
+import ElmModule.Update
+
+main : (Program Never Struct.Model.Type Struct.Event.Type)
+main =
+ (Html.program
+ {
+ init = ElmModule.Init.init,
+ view = ElmModule.View.view,
+ update = ElmModule.Update.update,
+ subscriptions = ElmModule.Subscriptions.subscriptions
+ }
+ )
diff --git a/src/altar/src/Struct/Attributes.elm b/src/altar/src/Struct/Attributes.elm
new file mode 100644
index 0000000..407856d
--- /dev/null
+++ b/src/altar/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
+
+-- Battlemap -------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- 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/altar/src/Struct/Character.elm b/src/altar/src/Struct/Character.elm
new file mode 100644
index 0000000..d4f65f7
--- /dev/null
+++ b/src/altar/src/Struct/Character.elm
@@ -0,0 +1,174 @@
+module Struct.Character exposing
+ (
+ Type,
+ Ref,
+ get_ref,
+ get_player_id,
+ get_name,
+ get_icon_id,
+ get_portrait_id,
+ get_current_health,
+ set_current_health,
+ get_location,
+ set_location,
+ get_attributes,
+ get_statistics,
+ is_enabled,
+ set_enabled,
+ get_weapons,
+ set_weapons,
+ decoder
+ )
+
+-- Elm -------------------------------------------------------------------------
+import Json.Decode
+import Json.Decode.Pipeline
+
+-- Battlemap -------------------------------------------------------------------
+import Struct.Attributes
+import Struct.Location
+import Struct.Statistics
+import Struct.Weapon
+import Struct.WeaponSet
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type alias PartiallyDecoded =
+ {
+ ix : Int,
+ nam : String,
+ ico : String,
+ prt : String,
+ lc : Struct.Location.Type,
+ hea : Int,
+ pla : String,
+ ena : Bool,
+ att : Struct.Attributes.Type,
+ awp : Int,
+ swp : Int
+ }
+
+type alias Type =
+ {
+ id : String,
+ name : String,
+ icon : String,
+ portrait : String,
+ location : Struct.Location.Type,
+ health : Int,
+ player_id : String,
+ enabled : Bool,
+ attributes : Struct.Attributes.Type,
+ statistics : Struct.Statistics.Type,
+ weapons : Struct.WeaponSet.Type
+ }
+
+type alias Ref = String
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+finish_decoding : (
+ (Struct.Weapon.Ref -> Struct.Weapon.Type) ->
+ PartiallyDecoded ->
+ Type
+ )
+finish_decoding get_weapon add_char =
+ let
+ active_weapon = (get_weapon add_char.awp)
+ secondary_weapon = (get_weapon add_char.swp)
+ weapon_set = (Struct.WeaponSet.new active_weapon secondary_weapon)
+ in
+ {
+ id = (toString add_char.ix),
+ name = add_char.nam,
+ 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),
+ player_id = add_char.pla,
+ enabled = add_char.ena,
+ weapons = weapon_set
+ }
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_ref : Type -> Ref
+get_ref c = c.id
+
+get_name : Type -> String
+get_name c = c.name
+
+get_player_id : Type -> String
+get_player_id c = c.player_id
+
+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
+
+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_enabled : Type -> Bool
+is_enabled char = char.enabled
+
+set_enabled : Bool -> Type -> Type
+set_enabled enabled char = {char | enabled = enabled}
+
+get_weapons : Type -> Struct.WeaponSet.Type
+get_weapons char = char.weapons
+
+set_weapons : Struct.WeaponSet.Type -> Type -> Type
+set_weapons weapons char =
+ {char |
+ weapons = weapons,
+ statistics =
+ (Struct.Statistics.new
+ char.attributes
+ weapons
+ )
+ }
+
+decoder : (
+ (Struct.Weapon.Ref -> Struct.Weapon.Type) ->
+ (Json.Decode.Decoder Type)
+ )
+decoder get_weapon =
+ (Json.Decode.map
+ (finish_decoding get_weapon)
+ (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 "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.string)
+ |> (Json.Decode.Pipeline.required "ena" 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)
+ )
+ )
diff --git a/src/altar/src/Struct/Error.elm b/src/altar/src/Struct/Error.elm
new file mode 100644
index 0000000..3607d1d
--- /dev/null
+++ b/src/altar/src/Struct/Error.elm
@@ -0,0 +1,43 @@
+module Struct.Error exposing (Type, Mode(..), new, to_string)
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type Mode =
+ IllegalAction
+ | Programming
+ | Unimplemented
+ | Networking
+
+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
+ 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/altar/src/Struct/Event.elm b/src/altar/src/Struct/Event.elm
new file mode 100644
index 0000000..ecda85b
--- /dev/null
+++ b/src/altar/src/Struct/Event.elm
@@ -0,0 +1,27 @@
+module Struct.Event exposing (Type(..))
+
+-- Elm -------------------------------------------------------------------------
+import Http
+
+-- Battlemap -------------------------------------------------------------------
+import Struct.Character
+import Struct.Direction
+import Struct.Location
+import Struct.ServerReply
+import Struct.UI
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type Type =
+ DirectionRequested Struct.Direction.Type
+ | TileSelected Struct.Location.Ref
+ | CharacterSelected Struct.Character.Ref
+ | CharacterInfoRequested Struct.Character.Ref
+ | TurnEnded
+ | ScaleChangeRequested Float
+ | TabSelected Struct.UI.Tab
+ | ServerReplied (Result Http.Error (List Struct.ServerReply.Type))
+ | DebugTeamSwitchRequest
+ | DebugLoadBattlemapRequest
+ | WeaponSwitchRequest
diff --git a/src/altar/src/Struct/Model.elm b/src/altar/src/Struct/Model.elm
new file mode 100644
index 0000000..4955163
--- /dev/null
+++ b/src/altar/src/Struct/Model.elm
@@ -0,0 +1,89 @@
+module Struct.Model exposing
+ (
+ Type,
+ new,
+ add_character,
+ invalidate,
+ reset,
+ clear_error
+ )
+
+-- Elm -------------------------------------------------------------------------
+import Dict
+import Array
+
+-- Battlemap -------------------------------------------------------------------
+import Data.Weapons
+
+import Struct.Battlemap
+import Struct.Character
+import Struct.CharacterTurn
+import Struct.TurnResult
+import Struct.Error
+import Struct.UI
+import Struct.Weapon
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type alias Type =
+ {
+ battlemap: Struct.Battlemap.Type,
+ characters: (Dict.Dict Struct.Character.Ref Struct.Character.Type),
+ weapons: (Dict.Dict Struct.Weapon.Ref Struct.Weapon.Type),
+ error: (Maybe Struct.Error.Type),
+ player_id: String,
+ ui: Struct.UI.Type,
+ char_turn: Struct.CharacterTurn.Type,
+ timeline: (Array.Array Struct.TurnResult.Type)
+ }
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+new : Type
+new =
+ {
+ battlemap = (Struct.Battlemap.empty),
+ characters = (Dict.empty),
+ weapons = (Data.Weapons.generate_dict),
+ error = Nothing,
+ player_id = "0",
+ ui = (Struct.UI.default),
+ char_turn = (Struct.CharacterTurn.new),
+ timeline = (Array.empty)
+ }
+
+add_character : Struct.Character.Type -> Type -> Type
+add_character char model =
+ {model |
+ characters =
+ (Dict.insert
+ (Struct.Character.get_ref char)
+ char
+ model.characters
+ )
+ }
+
+reset : Type -> (Dict.Dict Struct.Character.Ref Struct.Character.Type) -> Type
+reset model characters =
+ {model |
+ characters = characters,
+ error = Nothing,
+ ui = (Struct.UI.set_previous_action model.ui Nothing),
+ char_turn = (Struct.CharacterTurn.new)
+ }
+
+invalidate : Type -> Struct.Error.Type -> Type
+invalidate model err =
+ {model |
+ error = (Just err),
+ ui = (Struct.UI.set_displayed_tab model.ui Struct.UI.StatusTab)
+ }
+
+clear_error : Type -> Type
+clear_error model = {model | error = Nothing}
diff --git a/src/altar/src/Struct/ServerReply.elm b/src/altar/src/Struct/ServerReply.elm
new file mode 100644
index 0000000..b986abe
--- /dev/null
+++ b/src/altar/src/Struct/ServerReply.elm
@@ -0,0 +1,27 @@
+module Struct.ServerReply exposing (Type(..))
+
+-- Elm -------------------------------------------------------------------------
+
+-- Battlemap -------------------------------------------------------------------
+import Struct.Battlemap
+import Struct.Character
+import Struct.TurnResult
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+type Type =
+ Okay
+ | AddCharacter Struct.Character.Type
+ | SetMap Struct.Battlemap.Type
+ | TurnResults (List Struct.TurnResult.Type)
+ | SetTimeline (List Struct.TurnResult.Type)
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
diff --git a/src/altar/src/Struct/Statistics.elm b/src/altar/src/Struct/Statistics.elm
new file mode 100644
index 0000000..aad1411
--- /dev/null
+++ b/src/altar/src/Struct/Statistics.elm
@@ -0,0 +1,170 @@
+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
+
+-- Battlemap -------------------------------------------------------------------
+import Struct.Attributes
+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 ->
+ Type
+ )
+new att wp_set =
+ let
+ active_weapon = (Struct.WeaponSet.get_active_weapon wp_set)
+ actual_att = (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 [mind, constitution, constitution])
+ ),
+ 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/altar/src/Struct/UI.elm b/src/altar/src/Struct/UI.elm
new file mode 100644
index 0000000..3343565
--- /dev/null
+++ b/src/altar/src/Struct/UI.elm
@@ -0,0 +1,124 @@
+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,
+ -- Manual Controls
+ has_manual_controls_enabled,
+ -- Previous Action
+ has_focus,
+ get_previous_action,
+ set_previous_action
+ )
+
+-- Battlemap -------------------------------------------------------------------
+import Struct.Location
+
+import Struct.Character
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type Tab =
+ StatusTab
+ | CharactersTab
+ | SettingsTab
+ | TimelineTab
+
+type Action =
+ UsedManualControls
+ | SelectedLocation Struct.Location.Ref
+ | SelectedCharacter Struct.Character.Ref
+ | AttackedCharacter Struct.Character.Ref
+
+type alias Type =
+ {
+ zoom_level : Float,
+ show_manual_controls : Bool,
+ displayed_tab : (Maybe Tab),
+ previous_action : (Maybe Action)
+ }
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+default : Type
+default =
+ {
+ zoom_level = 1.0,
+ show_manual_controls = True,
+ displayed_tab = (Just StatusTab),
+ previous_action = 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 : Type -> Float -> Type
+mod_zoom_level ui mod = {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 : Type -> Tab -> Type
+set_displayed_tab ui tab = {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]
+
+-- 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 : Type -> Bool -> Type
+set_enable_manual_controls ui val = {ui | show_manual_controls = val}
+
+-- Previous Action -------------------------------------------------------------
+has_focus : Type -> Bool
+has_focus ui = True
+
+set_previous_action : Type -> (Maybe Action) -> Type
+set_previous_action ui act = {ui | previous_action = act}
+
+get_previous_action : Type -> (Maybe Action)
+get_previous_action ui = ui.previous_action
diff --git a/src/altar/src/Struct/Weapon.elm b/src/altar/src/Struct/Weapon.elm
new file mode 100644
index 0000000..d1d5807
--- /dev/null
+++ b/src/altar/src/Struct/Weapon.elm
@@ -0,0 +1,150 @@
+module Struct.Weapon exposing
+ (
+ Type,
+ Ref,
+ RangeType(..),
+ RangeModifier(..),
+ DamageType(..),
+ DamageModifier(..),
+ new,
+ 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,
+ apply_to_attributes
+ )
+
+-- Battlemap -------------------------------------------------------------------
+import Struct.Attributes
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type alias Type =
+ {
+ id : Int,
+ name : String,
+ 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 : RangeType -> DamageModifier -> (Int, Int)
+get_damages rt dm =
+ case (rt, dm) of
+ (Ranged, Heavy) -> (10, 25)
+ (Ranged, Light) -> (5, 20)
+ (Melee, Heavy) -> (20, 35)
+ (Melee, Light) -> (15, 30)
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+new : (
+ Int ->
+ String ->
+ RangeType ->
+ RangeModifier ->
+ DamageType ->
+ DamageModifier ->
+ Type
+ )
+new
+ id name
+ 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 range_type dmg_mod)
+ in
+ {
+ id = id,
+ name = name,
+ 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_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 =
+ case (wp.range_mod, wp.dmg_mod) of
+ (Long, Heavy) ->
+ (Struct.Attributes.mod_dexterity
+ -20
+ (Struct.Attributes.mod_speed -20 atts)
+ )
+
+ (Long, Light) -> (Struct.Attributes.mod_dexterity -20 atts)
+
+ (Short, Heavy) -> (Struct.Attributes.mod_speed -20 atts)
+
+ (Short, Light) -> atts
diff --git a/src/altar/src/Struct/WeaponSet.elm b/src/altar/src/Struct/WeaponSet.elm
new file mode 100644
index 0000000..444152d
--- /dev/null
+++ b/src/altar/src/Struct/WeaponSet.elm
@@ -0,0 +1,39 @@
+module Struct.WeaponSet exposing
+ (
+ Type,
+ new,
+ get_active_weapon,
+ get_secondary_weapon,
+ switch_weapons
+ )
+
+-- Battlemap -------------------------------------------------------------------
+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/altar/src/Update/HandleServerReply.elm b/src/altar/src/Update/HandleServerReply.elm
new file mode 100644
index 0000000..8b3ae27
--- /dev/null
+++ b/src/altar/src/Update/HandleServerReply.elm
@@ -0,0 +1,154 @@
+module Update.HandleServerReply exposing (apply_to)
+
+-- Elm -------------------------------------------------------------------------
+import Array
+
+import Http
+
+-- Battlemap -------------------------------------------------------------------
+import Struct.Battlemap
+import Struct.Character
+import Struct.Error
+import Struct.Event
+import Struct.Model
+import Struct.ServerReply
+import Struct.TurnResult
+import Struct.UI
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+add_character : (
+ Struct.Character.Type ->
+ (Struct.Model.Type, (Maybe Struct.Error.Type)) ->
+ (Struct.Model.Type, (Maybe Struct.Error.Type))
+ )
+add_character char current_state =
+ case current_state of
+ (_, (Just _)) -> current_state
+ (model, _) ->
+ (
+ (Struct.Model.add_character
+ char
+ model
+ ),
+ Nothing
+ )
+
+set_map : (
+ Struct.Battlemap.Type ->
+ (Struct.Model.Type, (Maybe Struct.Error.Type)) ->
+ (Struct.Model.Type, (Maybe Struct.Error.Type))
+ )
+set_map map current_state =
+ case current_state of
+ (_, (Just _)) -> current_state
+ (model, _) ->
+ (
+ {model | battlemap = 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, _) ->
+ let
+ updated_characters =
+ (List.foldl
+ (Struct.TurnResult.apply_to_characters)
+ model.characters
+ turn_results
+ )
+ in
+ (
+ {model |
+ timeline =
+ (Array.append
+ (Array.fromList turn_results)
+ model.timeline
+ ),
+ ui =
+ (Struct.UI.set_displayed_tab
+ model.ui
+ Struct.UI.TimelineTab
+ ),
+ characters = updated_characters
+ },
+ 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.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
+ model
+ (Struct.Error.new Struct.Error.Networking (toString error))
+ ),
+ Cmd.none
+ )
+
+ (Result.Ok commands) ->
+ (
+ (
+ case (List.foldl (apply_command) (model, Nothing) commands) of
+ (updated_model, Nothing) -> updated_model
+ (_, (Just error)) -> (Struct.Model.invalidate model error)
+ ),
+ Cmd.none
+ )
diff --git a/src/altar/src/Update/SelectCharacter.elm b/src/altar/src/Update/SelectCharacter.elm
new file mode 100644
index 0000000..0e08a4d
--- /dev/null
+++ b/src/altar/src/Update/SelectCharacter.elm
@@ -0,0 +1,203 @@
+module Update.SelectCharacter exposing (apply_to)
+
+-- Elm -------------------------------------------------------------------------
+import Dict
+
+-- Battlemap -------------------------------------------------------------------
+import Struct.Battlemap
+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 -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+attack_character : (
+ Struct.Model.Type ->
+ Struct.Character.Ref ->
+ 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.set_previous_action model.ui Nothing)
+ }
+
+ctrl_or_focus_character : (
+ Struct.Model.Type ->
+ Struct.Character.Ref ->
+ 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
+ weapon =
+ (Struct.WeaponSet.get_active_weapon
+ (Struct.Character.get_weapons target_char)
+ )
+ in
+ {model |
+ char_turn =
+ (Struct.CharacterTurn.set_navigator
+ (Struct.Navigator.new
+ (Struct.Character.get_location target_char)
+ (Struct.Statistics.get_movement_points
+ (Struct.Character.get_statistics target_char)
+ )
+ (Struct.Weapon.get_attack_range weapon)
+ (Struct.Weapon.get_defense_range weapon)
+ (Struct.Battlemap.get_movement_cost_function
+ model.battlemap
+ (Struct.Character.get_location target_char)
+ (Dict.values model.characters)
+ )
+ )
+ (Struct.CharacterTurn.set_active_character
+ target_char
+ model.char_turn
+ )
+ ),
+ ui = (Struct.UI.set_previous_action model.ui Nothing)
+ }
+ else
+ {model |
+ ui =
+ (Struct.UI.set_previous_action
+ model.ui
+ (Just (Struct.UI.SelectedCharacter target_char_id))
+ )
+ }
+
+can_target_character : (
+ Struct.Model.Type ->
+ Struct.Character.Type ->
+ Bool
+ )
+can_target_character model target =
+ (
+ (Struct.CharacterTurn.can_select_target model.char_turn)
+ &&
+ (
+ case
+ (Struct.CharacterTurn.try_getting_navigator
+ model.char_turn
+ )
+ of
+ (Just nav) ->
+ case
+ (Struct.Navigator.try_getting_path_to
+ nav
+ (Struct.Location.get_ref
+ (Struct.Character.get_location target)
+ )
+ )
+ of
+ (Just _) -> True
+ _ -> False
+
+ _ ->
+ False
+ )
+ )
+
+double_clicked_character : (
+ Struct.Model.Type ->
+ Struct.Character.Ref ->
+ (Struct.Model.Type, (Cmd Struct.Event.Type))
+ )
+double_clicked_character model target_char_id =
+ case (Dict.get target_char_id model.characters) of
+ (Just target_char) ->
+ case
+ (Struct.CharacterTurn.try_getting_active_character
+ model.char_turn
+ )
+ of
+ (Just _) ->
+ if (can_target_character model target_char)
+ then
+ (
+ (attack_character
+ model
+ target_char_id
+ target_char
+ ),
+ Cmd.none
+ )
+ else
+ (
+ (Struct.Model.invalidate
+ model
+ (Struct.Error.new
+ Struct.Error.IllegalAction
+ "Has not yet moved or target is out of range."
+ )
+ ),
+ Cmd.none
+ )
+
+ _ ->
+ (
+ (ctrl_or_focus_character model target_char_id target_char),
+ Cmd.none
+ )
+
+ Nothing ->
+ (
+ (Struct.Model.invalidate
+ model
+ (Struct.Error.new
+ Struct.Error.Programming
+ "SelectCharacter: Unknown char selected."
+ )
+ ),
+ Cmd.none
+ )
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+apply_to : (
+ Struct.Model.Type ->
+ Struct.Character.Ref ->
+ (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
+ (double_clicked_character model target_char_id)
+ else
+ (
+ {model |
+ ui =
+ (Struct.UI.set_previous_action
+ (Struct.UI.set_displayed_tab
+ model.ui
+ Struct.UI.StatusTab
+ )
+ (Just (Struct.UI.SelectedCharacter target_char_id))
+ )
+ },
+ Cmd.none
+ )
diff --git a/src/altar/src/Update/SelectTab.elm b/src/altar/src/Update/SelectTab.elm
new file mode 100644
index 0000000..c48b0fc
--- /dev/null
+++ b/src/altar/src/Update/SelectTab.elm
@@ -0,0 +1,25 @@
+module Update.SelectTab exposing (apply_to)
+-- Elm -------------------------------------------------------------------------
+
+-- Battlemap -------------------------------------------------------------------
+import Struct.Model
+import Struct.Event
+import Struct.UI
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+apply_to : (
+ Struct.Model.Type ->
+ Struct.UI.Tab ->
+ (Struct.Model.Type, (Cmd Struct.Event.Type))
+ )
+apply_to model tab =
+ (
+ {model | ui = (Struct.UI.set_displayed_tab model.ui tab)},
+ Cmd.none
+ )
diff --git a/src/altar/src/Update/SwitchWeapon.elm b/src/altar/src/Update/SwitchWeapon.elm
new file mode 100644
index 0000000..7921b66
--- /dev/null
+++ b/src/altar/src/Update/SwitchWeapon.elm
@@ -0,0 +1,100 @@
+module Update.SwitchWeapon exposing (apply_to)
+-- Elm -------------------------------------------------------------------------
+import Dict
+
+-- Battlemap -------------------------------------------------------------------
+import Struct.Battlemap
+import Struct.Character
+import Struct.CharacterTurn
+import Struct.Error
+import Struct.Event
+import Struct.Model
+import Struct.Navigator
+import Struct.Statistics
+import Struct.Weapon
+import Struct.WeaponSet
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+make_it_so : Struct.Model.Type -> Struct.Model.Type
+make_it_so model =
+ case (Struct.CharacterTurn.try_getting_active_character model.char_turn) of
+ (Just char) ->
+ let
+ new_weapons =
+ (Struct.WeaponSet.switch_weapons
+ (Struct.Character.get_weapons char)
+ )
+ new_char = (Struct.Character.set_weapons new_weapons char)
+ in
+ {model |
+ char_turn =
+ (Struct.CharacterTurn.set_has_switched_weapons
+ True
+ (Struct.CharacterTurn.lock_path
+ (Struct.CharacterTurn.set_navigator
+ (Struct.Navigator.new
+ (Struct.Character.get_location new_char)
+ (Struct.Statistics.get_movement_points
+ (Struct.Character.get_statistics new_char)
+ )
+ (Struct.Weapon.get_attack_range
+ (Struct.WeaponSet.get_active_weapon new_weapons)
+ )
+ (Struct.Weapon.get_defense_range
+ (Struct.WeaponSet.get_active_weapon new_weapons)
+ )
+ (Struct.Battlemap.get_movement_cost_function
+ model.battlemap
+ (Struct.Character.get_location new_char)
+ (Dict.values model.characters)
+ )
+ )
+ (Struct.CharacterTurn.set_active_character
+ new_char
+ model.char_turn
+ )
+ )
+ )
+ )
+ }
+
+ _ ->
+ (Struct.Model.invalidate
+ model
+ (Struct.Error.new
+ Struct.Error.Programming
+ (
+ "CharacterTurn structure in the 'SelectedCharacter' state"
+ ++ " without character being selected."
+ )
+ )
+ )
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+apply_to : (
+ Struct.Model.Type ->
+ (Struct.Model.Type, (Cmd Struct.Event.Type))
+ )
+apply_to model =
+ case (Struct.CharacterTurn.get_state model.char_turn) of
+ Struct.CharacterTurn.SelectedCharacter ->
+ ((make_it_so model), Cmd.none)
+
+ _ ->
+ (
+ (Struct.Model.invalidate
+ model
+ (Struct.Error.new
+ Struct.Error.Programming
+ (
+ "Attempt to switch weapons as a secondary action or"
+ ++ " without character being selected."
+ )
+ )
+ ),
+ Cmd.none
+ )
diff --git a/src/altar/src/Util/Array.elm b/src/altar/src/Util/Array.elm
new file mode 100644
index 0000000..69d329c
--- /dev/null
+++ b/src/altar/src/Util/Array.elm
@@ -0,0 +1,25 @@
+module Util.Array exposing (update, update_unsafe)
+
+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)
diff --git a/src/altar/src/Util/Html.elm b/src/altar/src/Util/Html.elm
new file mode 100644
index 0000000..42eadba
--- /dev/null
+++ b/src/altar/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/altar/src/Util/List.elm b/src/altar/src/Util/List.elm
new file mode 100644
index 0000000..c4db397
--- /dev/null
+++ b/src/altar/src/Util/List.elm
@@ -0,0 +1,12 @@
+module Util.List exposing (pop)
+
+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))
diff --git a/src/altar/www/index.html b/src/altar/www/index.html
new file mode 100644
index 0000000..33485f1
--- /dev/null
+++ b/src/altar/www/index.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../global/style.css">
+ <link rel="stylesheet" type="text/css" href="../altar/style.css">
+ <link rel="stylesheet" type="text/css" href="../asset/tiles.css">
+ <link rel="stylesheet" type="text/css" href="../asset/characters.css">
+ </head>
+ <body>
+ <script src="script/main.js"></script>
+ <script>Elm.Main.fullscreen();</script>
+ </body>
+</html>
diff --git a/src/altar/www/style.css b/src/altar/www/style.css
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/altar/www/style.css