To start your Tarragon server you can either use Docker or run it locally.
- Copy
env/.env.dev
to.env
and fill in the values - Run
docker-compose up
to start the server
- Run postgres with username/password: postgres/postgres
- Run
mix setup
to install and setup dependencies - Seed the database:
START_WORKERS=false mix ecto.setup
- Start Phoenix endpoint with
mix phx.server
or inside IEx withiex -S mix phx.server
Visit localhost:4000/login/1
to authenticate yourself.
- Optimizing loading pictures https://css-tricks.com/the-blur-up-technique-for-loading-background-images/
- Passing Viewport dimensions on mount https://gist.github.com/cblavier/0e227de6fd1dfa00814b88642cdcb2a9
- Time Shards are introduces as a currency (S)
- Time Shards are given for every battle as an item of 1, 1k, 10k, 100k (M)
- Time Shards are subtracted for every 10 minutes of being offline/online (S)
- in-game resource/item exchange is created with one tab (Time Shards shop) (M)
- bundle store is created (Time Shard bundles) (M)
- distance mechanic is implemented (L)
- multiplayer is working (>1 player per team) (M)
- equipment condition is decreased after the battle (S)
- rewards are given after the battle (more if win, less if loss) (S)
- health is updated in real time (S-M)
- datetime in UTC (XS)
- absolute player power is calculated and displayed (S)
- currency (Time Shards) is displayed (S)
- world chat with history is available (L)
- translation per message (L)
- spam bot (M)
- similar items are batched together (M)
- broken items can be fixed with "components" (S)
- resources and currency bundles can be "used" to be transfered to the player's account (M)
- transition from tile to tile (connected tiles) (M)
- navigation from tile to tile (distant tiles) (S)
- a map objective details can be previewed (L)
- resource buildings are available on the map (L)
- player can collect resources from buildings (M)
character has_one primary_weapon_slot(item_container fk: primary_weapon_slot_id); item_container(primary_weapon_slot) belongs_to character (fk: primary_weapon_slot_id) item_container has_many character_items; character_item belongs_to item_container (fk: item_container_id) character_item belongs_to game_item (fk: game_item_id)
-
Lobby
-
"search_for_battles"
- create participant record (without battle_room_id)
- subscribe to "awaiting_participant:#{participant.id}" (PubSub channel)
-
"stop_searching_for_battles"
- delete participant record
- unsubscribe to "awaiting_participant:#{participant.id}" (PubSub channel)
-
"battle_room_assigned" (PubSub channel)
- unsubscribe to "awaiting_participant:#{participant.id}" (PubSub channel)
- redirect to BattleScreen
-
-
BattleBots GenServer
- {:init_bot, battle_room_id} - load bot character in memory (returns character_id)
- {:take_hit, bot_id, damage}
- {:decide_move, bot_id, attack_options}
- attack_options: [%{distance: 1, health: 10, target_id: 1}]
- {:end_battle, bot_id}
-
LobbyTracker GenServer
- loops and queries if there are any participants (without battle_room_id assigned)
- if so, start a battle
- add battle_room_id to participants
- add team_a/team_b to participants
- push "battle_room_assigned" to "awaiting_participant:#{participant.id}"
- loops and queries if there are any participants (without battle_room_id assigned)
-
BattleRoom GenServer
- {:init_battle, character_structs} -> battle_room_id initializes actions/logs structure for the battle
- also submit actions for bots
- {:submit_action, battle_room_id, %{character_id: character_id, move: move, attack: attack, target_id: target_id}}
- {:finalize_turn, battle_room_id}
- also submit actions for bots
- {:init_battle, character_structs} -> battle_room_id initializes actions/logs structure for the battle
-
BattleScreen LiveView
- mount - read battle_room from db, assign ally and enemy teams
- assign current_user_id
- init timer check every 1 second
- remember move
- remember attack
- submit action (human)
- timer check
- if all submitted - call BattleRoom.finalize_turn
- if not - timer check in 1 second
- mount - read battle_room from db, assign ally and enemy teams
-
Lobby view
-
User clicks "Join Battle"
- create Participant for the user (without battle_room_id)
- PubSub subscribes to
awaiting_participant:#{participant.id}
channel
-
LobbyTracker
- check_awaiting_participants On TimerTick (
check_awaiting_participants
)- checks if there are any participants without
battle_room_id
- group participants by
max_participants
- for every participant group
- call
BattleRoom.init_battle
with human characters + bots
- call
- checks if there are any participants without
- check_awaiting_participants On TimerTick (
-
BattleRoom
- handle_call
BattleRoom.init_battle(characters, rest_with_bots: true)
- create
Room
,awaiting_start: false
- create additional Bot characters (
BattleBots.init_bot
) - assign
battle_room_id
,team_a
/team_b
to participants - broadcasts PubSub
"battle_room_assigned"
to"awaiting_participant:#{participant.id}"
- create actions/logs structure for the battle
- submit actions for bots
BattleBot.decide_move
- create
- handle_call
-
Lobby View
- on "battle_room_assigned"
- unsubscribe from
awaiting_participant:#{participant.id}
channel - redirect to
BattleScreen
- unsubscribe from
- on "battle_room_assigned"
-
BattleScreen
- mount
- load participants/characters from room record
- load timer settings from room record
- accept move, attack
- submit action (not allowed to edit after submit)
- submit action to
BattleRoom.submit_action
- submit action to
- on TimerTick
- check if all human participants submitted actions
- TODO: call
BattleRoom.check_all_submitted()
- if all submitted - call
BattleRoom.finalize_turn
- else: check again in 1 second
- check if current player is dead
- if so - set a variable
dead
to true, allow user to quit the battle
- if so - set a variable
- check if all players from one team are dead
- do cleanup
- TODO: call
BattleRoom.end_battle
- mount
-
BattleRoom
-
finalize_turn:
- call
BattleBot.decide_move
for all bots - call
BattleRoom.finalize_turn
for all bots
- call
-
end_battle:
- Call
BattleBot.end_battle()
for all bots - Update Room record with
ended_at
- Call
-
-
Lobby View
+GenServer
- creates battle room and participants entities in DB
-
Tarragon.Battles.BattleTrackerEcs
- calls
build_ecs_lobby()
which includes- building
Tarragon.Ecspanse.Lobby.LobbyGame
structure withTarragon.Ecspanse.Lobby.LobbyGame.PlayerCombatant
(s) where every combatant is filled in from theRoom
entity created by the lobby.
- building
- calls
Tarragon.Ecspanse.Battles.Api.spawn_battle(lobby_game)
on the filled in structure- that generates a
Events.SpawnBattleRequest
- that generates a
- calls
-
Tarragon.Ecspanse.Battles.Systems.Synchronous.BattleSpawnerV2
- receives
SpawnBattleRequest
and spawn all the entities
- receives