aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornsensfel <SpamShield0@noot-noot.org>2018-02-23 18:46:05 +0100
committernsensfel <SpamShield0@noot-noot.org>2018-02-23 18:46:05 +0100
commitf512cb83df8dea9fb39bd98540b0616fe7607f6d (patch)
tree1e11c44c66533a3ce6e55c1c7533f9a0c04a662d
parentacf9e9f1eb880ffb8ab918c40724eda566aefcc7 (diff)
downloadtacticians-server-f512cb83df8dea9fb39bd98540b0616fe7607f6d.zip
tacticians-server-f512cb83df8dea9fb39bd98540b0616fe7607f6d.tar.bz2
Rewritting "character_turn.erl"...
-rw-r--r--src/io/security.erl19
-rw-r--r--src/query/character_turn.erl437
-rw-r--r--src/query/character_turn/handle_character_attacking_2.erl59
3 files changed, 328 insertions, 187 deletions
diff --git a/src/io/security.erl b/src/io/security.erl
new file mode 100644
index 0000000..fb7be8d
--- /dev/null
+++ b/src/io/security.erl
@@ -0,0 +1,19 @@
+-module(security).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-export([assert_identity/2]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+assert_identity (_PlayerID, _SessionToken) -> true.
diff --git a/src/query/character_turn.erl b/src/query/character_turn.erl
index 501c82b..d71c64a 100644
--- a/src/query/character_turn.erl
+++ b/src/query/character_turn.erl
@@ -9,11 +9,10 @@
(
input,
{
- session_token,
player_id,
- battlemap_id,
- instance_id,
- char_id,
+ session_token,
+ battlemap_instance_id,
+ character_instance_id,
path,
target_id
}
@@ -23,14 +22,9 @@
(
query_state,
{
- input,
- battlemap,
- battlemap_inst,
- main_char,
- main_char_inst,
- main_char_new_loc,
- target_char,
- target_char_inst
+ battlemap_instance,
+ character_instance,
+ rolls
}
).
@@ -44,231 +38,300 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
parse_input (Req) ->
JSONReqMap = jiffy:decode(Req, [return_maps]),
- PlayerID = maps:get(<<"player_id">>, JSONReqMap),
- SessionToken = maps:get(<<"session_token">>, JSONReqMap),
- Target =
- case maps:get(<<"targets_id">>, JSONReqMap) of
- [] -> <<"">>;
- [T] -> T
- end,
+ CharacterInstanceID = binary_to_integer(maps:get(<<"cid">>, JSONReqMap)),
+ TargetID = binary_to_integer(maps:get(<<"tid">>, JSONReqMap)),
#input
{
- player_id = PlayerID,
- battlemap_id = maps:get(<<"battlemap_id">>, JSONReqMap),
- instance_id = maps:get(<<"instance_id">>, JSONReqMap),
- char_id = maps:get(<<"char_id">>, JSONReqMap),
- path = maps:get(<<"path">>, JSONReqMap),
- target_id = Target
+ player_id = maps:get(<<"pid">>, JSONReqMap),
+ session_token = maps:get(<<"stk">>, JSONReqMap),
+ battlemap_instance_id = maps:get(<<"bmp">>, JSONReqMap),
+ character_instance_id = CharacterInstanceID,
+ path = maps:get(<<"p">>, JSONReqMap),
+ target_id = TargetID
}.
fetch_data (Input) ->
- Battlemap =
- timed_cache:fetch
- (
- battlemap_db,
- Input#input.player_id,
- Input#input.battlemap_id
- ),
- BattlemapInst =
+ BattlemapInstance =
timed_cache:fetch
(
battlemap_instance_db,
Input#input.player_id,
- <<"0">>
- ),
- MainChar =
- timed_cache:fetch
- (
- character_db,
- Input#input.player_id,
- Input#input.char_id
+ Input#input.battlemap_instance_id
),
- MainCharInst =
- battlemap_instance:get_char_instance
+ CharacterInstance =
+ array:get
(
- BattlemapInst,
- Input#input.char_id
+ Input#input.character_instance_id,
+ battlemap_instance:get_character_instances(BattlemapInstance)
),
- case Input#input.target_id of
- <<"">> ->
- TargetChar = nothing,
- TargetCharInst = nothing;
-
- TargetID ->
- TargetChar =
- timed_cache:fetch
- (
- character_db,
- Input#input.player_id,
- TargetID
- ),
- TargetCharInst =
- battlemap_instance:get_char_instance
- (
- BattlemapInst,
- TargetID
- )
- end,
#query_state
{
- input = Input,
- battlemap = Battlemap,
- battlemap_inst = BattlemapInst,
- main_char = MainChar,
- main_char_inst = MainCharInst,
- main_char_new_loc = nothing,
- target_char = TargetChar,
- target_char_inst = TargetCharInst
+ battlemap_instance = BattlemapInstance,
+ character_instance = CharacterInstance,
+ rolls = []
}.
-assert_main_char_can_be_used (QueryState) ->
- false = character_instance:is_dead(QueryState#query_state.main_char_inst),
- true =
- battlemap_instance:can_play_char_instance
+assert_character_can_be_played (QueryState, Input) ->
+ %%% Var
+ BattlemapInstance = QueryState#query_state.battlemap_instance,
+ PlayerID = Input#input.player_id,
+ ControlledCharacterInstance = QueryState#query_state.character_instance,
+ %%% Asserts
+ PlayerID =
+ arrays:get
(
- QueryState#query_state.battlemap_inst,
- QueryState#query_state.input#input.player_id,
- QueryState#query_state.input#input.char_id
- ).
+ player_turn:get_player_id
+ (
+ battlemap_instance:get_player_turn(BattlemapInstance)
+ ),
+ battlemap_instance:get_players(BattlemapInstance)
+ ),
+ PlayerID =
+ character:get_owner
+ (
+ character_instance:get_character(ControlledCharacterInstance)
+ ),
+ true = character_instance:is_active(ControlledCharacterInstance).
-handle_main_char_movement (QueryState) ->
- {X, Y} =
- battlemap:cross
+handle_character_moving (QueryState, Input) ->
+ BattlemapInstance = QueryState#query_state.battlemap_instance,
+ ControlledCharacterInstance = QueryState#query_state.character_instance,
+ ControlledCharacter =
+ character_instance:get_character(ControlledCharacterInstance),
+ Path = Input#input.path,
+ Battlemap = battlemap_instance:get_battlemap(BattlemapInstance),
+ ForbiddenLocations =
+ array:map
(
- QueryState#query_state.battlemap,
- character_instance:get_location(QueryState#query_state.main_char_inst),
+ fun (CharacterInstance) ->
+ character_instance:get_location(CharacterInstance)
+ end,
+ battlemap_instance:get_character_instances(BattlemapInstance)
+ ),
+ {ok, NewLocation, _} =
+ movement:cross
+ (
+ Battlemap,
+ character_instance:get_location(ControlledCharacterInstance),
statistics:get_movement_points
(
- character_instance:get_statistics
- (
- QueryState#query_state.main_char_inst
- )
+ character:get_statistics(ControlledCharacter)
),
- QueryState#query_state.input#input.path,
- battlemap_instance:get_char_instances
+ Path,
+ ForbiddenLocations
+ ),
+ QueryState#query_state
+ {
+ character_instance =
+ character_instance:set_location
(
- QueryState#query_state.battlemap_inst
+ NewLocation,
+ ControlledCharacterInstance
)
- ),
+ }.
+
+handle_character_switching_weapons (QueryState) ->
+ ControlledCharacterInstance = QueryState#query_state.character_instance,
+ ControlledCharacter =
+ character_instance:get_character(ControlledCharacterInstance),
QueryState#query_state
{
- battlemap_inst =
- battlemap_instance:set_char_instance
+ character_instance =
+ character_instance:set_character
(
- battlemap_instance:post_play_char_instance
+ character:set_weapons
(
- QueryState#query_state.battlemap_inst,
- QueryState#query_state.input#input.char_id
+ weapon_set:switch
+ (
+ character:get_weapons(ControlledCharacter)
+ ),
+ ControlledCharacter
),
- QueryState#query_state.input#input.char_id,
- character_instance:set_location
- (
- QueryState#query_state.main_char_inst,
- X,
- Y
- )
- ),
- main_char_new_loc = {X, Y}
+ ControlledCharacterInstance
+ )
}.
-handle_target (QueryState)
- when (QueryState#query_state.target_char_inst == nothing) ->
- QueryState;
-handle_target (QueryState) ->
- TargetLoc =
- character_instance:get_location(QueryState#query_state.target_char_inst),
- Dist =
- battlemap:dist(QueryState#query_state.main_char_new_loc, TargetLoc),
- AtkWeapon =
- weapon:from_id
- (
- character_instance:get_active_weapon
- (
- QueryState#query_state.main_char_inst,
- QueryState#query_state.main_char
- )
- ),
- {_, AtkRange} = weapon:get_ranges(AtkWeapon),
- io:format
- (
- "~nAttack from ~p to ~p (wp: ~p, dist: ~p, range: ~p).~n",
- [
- QueryState#query_state.main_char_new_loc,
- TargetLoc,
- weapon:get_id(AtkWeapon),
- Dist,
- AtkRange
- ]
- ),
- true = (Dist =< AtkRange),
- TargetStatistics =
- character_instance:get_statistics
- (
- QueryState#query_state.target_char_inst
- ),
- {MinDamage, MaxDamage} = weapon:get_damages(AtkWeapon),
- Diff = max(1, MaxDamage - MinDamage),
- NewTargetCharInst =
- character_instance:mod_health
+-include("character_turn/handle_character_attacking_2.erl").
+
+get_type_of_turn (Input) ->
+ case {Input#input.path, Input#input.target_id} of
+ {[], -1} -> [nothing, nothing];
+ {[], _} -> [nothing, attack];
+ {[<<"S">>], -1} -> [switch, nothing];
+ {[<<"S">>], _} -> [switch, attack];
+ {_, -1} -> [move, nothing];
+ {_, _} -> [move, attack]
+ end.
+
+finalize_character_instance (QueryState, Input) ->
+ BattlemapInstance = QueryState#query_state.battlemap_instance,
+ FinalizedCharacterInstance =
+ character_instance:set_active
(
- QueryState#query_state.target_char_inst,
- statistics:get_health(TargetStatistics),
- (MinDamage + rand:uniform(Diff) - 1)
+ false,
+ QueryState#query_state.character_instance
),
- %% TODO: test for (and handle) riposte.
QueryState#query_state
{
- battlemap_inst =
- battlemap_instance:set_char_instance
+ battlemap_instance =
+ battlemap_instance:set_characters
(
- QueryState#query_state.battlemap_inst,
- QueryState#query_state.input#input.target_id,
- NewTargetCharInst
+ array:set
+ (
+ Input#input.character_instance_id,
+ FinalizedCharacterInstance,
+ battlemap_instance:get_characters(BattlemapInstance)
+ ),
+ BattlemapInstance
),
- target_char_inst = NewTargetCharInst
+ character_instance = FinalizedCharacterInstance
}.
-generate_reply (QueryState) ->
- case QueryState#query_state.target_char_inst of
- nothing -> [<<"okay">>];
+unnamed_function (IDs, CharacterInstances, _Owner, -1) ->
+ {IDs, CharacterInstances};
+unnamed_function (IDs, CharacterInstances, Owner, I) ->
+ CharacterInstance = array:get(I, CharacterInstances),
+ Character = character_instance:get_character(CharacterInstance),
+ case character:get_owner(Character) of
+ OwnerID when (OwnerID == Owner) ->
+ unnamed_function
+ (
+ [I|IDs],
+ array:set
+ (
+ I,
+ character_instance:set_is_active(true, CharacterInstance),
+ CharacterInstances
+ ),
+ Owner,
+ (I - 1)
+ );
- CharInst ->
- add_char:generate
+ _ ->
+ unnamed_function
(
- QueryState#query_state.target_char,
- CharInst,
+ IDs,
+ CharacterInstances,
+ Owner,
+ (I - 1)
+ )
+ end.
+
+start_next_players_turn (QueryState, Input) ->
+ BattlemapInstance = QueryState#query_state.battlemap_instance,
+ Players = battlemap_instance:get_players(BattlemapInstance),
+ PlayerTurn = battlemap_instance:get_player_turn(BattlemapInstance),
+ CurrentPlayerID = player_turn:get_player_id(PlayerTurn),
+ CurrentTurnNumber = player_turn:get_number(PlayerTurn),
+ CharacterInstances =
+ battlemap_instance:get_character_instances(BattlemapInstance),
+
+ NextPlayer = ((CurrentPlayerID + 1) rem (array:size(Players))),
+ NextPlayerTurn =
+ player_turn:new
+ (
+ case NextPlayer of
+ 0 -> (CurrentTurnNumber + 1);
+ _ -> CurrentTurnNumber
+ end,
+ NextPlayer
+ ),
+
+ {ActivatedCharacterInstancesID, UpdatedCharacterInstances} =
+ unnamed_function
+ (
+ [],
+ CharacterInstances,
+ array:get(NextPlayer, Players),
+ array:size(CharacterInstances)
+ ),
+ {
+ ActivatedCharacterInstancesID,
+ QueryState#query_state
+ {
+ battlemap_instance =
+ battlemap_instance:set_character_instances
(
- battlemap_instance:can_play_char_instance
+ UpdatedCharacterInstances,
+ battlemap_instance:set_player_turn
(
- QueryState#query_state.battlemap_inst,
- QueryState#query_state.input#input.player_id,
- QueryState#query_state.input#input.target_id
+ NextPlayerTurn,
+ BattlemapInstance
)
- and
- (not character_instance:is_dead(CharInst))
)
- )
+ }
+ }.
+
+finalize_character_turn (QueryState, Input) ->
+ BattlemapInstance = QueryState#query_state.battlemap_instance,
+ Players = battlemap_instance:get_players(BattlemapInstance),
+
+ CharacterInstanceRemains =
+ array:foldl
+ (
+ fun (_I, CharacterInstance, Prev) ->
+ (Prev or character_instance:get_is_active(CharacterInstance))
+ end,
+ Players
+ ),
+
+ case CharacterInstanceRemains of
+ true -> {false, {[], QueryState}};
+ false -> {true, start_next_players_turn(QueryState, Input)}
end.
+play (QueryState, [], Input) ->
+ finalize_character_turn
+ (
+ finalize_character_instance(QueryState, Input),
+ Input
+ );
+play (QueryState, [nothing|Next], Input) ->
+ play(QueryState, Next, Input);
+play (QueryState, [move|Next], Input) ->
+ play
+ (
+ handle_character_moving(QueryState, Input),
+ Next,
+ Input
+ );
+play (QueryState, [switch|Next], Input) ->
+ play
+ (
+ handle_character_switching_weapons(QueryState),
+ Next,
+ Input
+ );
+
+play (QueryState, [attack|Next], Input) ->
+ play
+ (
+ handle_character_attacking(QueryState, Input),
+ Next,
+ Input
+ ).
+
+send_to_database (QueryState, TurnType, Input) ->
+ unimplemented.
+
+update_cache (QueryState, TurnType, Input) ->
+ unimplemented.
+
+generate_reply (QueryState, TurnType, Input) ->
+ jiffy:encode([[<<"ok">>]]).
+
handle (Req) ->
- %%%% Parse
Input = parse_input(Req),
- assert_player_identity(Req),
- %%%% Fetch
+ security:assert_identity(Req#input.player_id, Req#input.session_token),
QueryState = fetch_data(Input),
- %%%% Calc
- assert_main_char_can_be_used(QueryState),
- NQueryState = handle_target(handle_main_char_movement(QueryState)),
- %%%% Commit
- database_shim:commit
- (
- battlemap_instance_db,
- Input#input.player_id,
- <<"0">>,
- NQueryState#query_state.battlemap_inst
- ),
- %%%% Reply
- jiffy:encode([generate_reply(NQueryState)]).
+ assert_character_can_be_played(Input, QueryState),
+ TurnType = get_type_of_turn(Input),
+ {IsNewTurn, {UpdatedCharacterInstancesID, PostPlayQueryState}} =
+ play(QueryState, TurnType, Input),
+ send_to_database(PostPlayQueryState, TurnType, Input),
+ update_cache(PostPlayQueryState, TurnType, Input),
+ generate_reply(PostPlayQueryState, TurnType, Input).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/src/query/character_turn/handle_character_attacking_2.erl b/src/query/character_turn/handle_character_attacking_2.erl
new file mode 100644
index 0000000..3fd2687
--- /dev/null
+++ b/src/query/character_turn/handle_character_attacking_2.erl
@@ -0,0 +1,59 @@
+roll_hits (AttackerStatistics, DefenderStatistics) ->
+ MissChance =
+ max
+ (
+ 0,
+ (
+ statistics:get_dodges(DefenderStatistics)
+ -
+ statistics:get_accuracy(AttackerStatistics)
+ )
+ ),
+ case roll:percentage() of
+ X when (X < MissChance) -> misses;
+ X when (X < (MissChance * 2)) -> grazes;
+ _ -> hits
+ end.
+
+roll_damage (AttackerStatistics, _DefenderStatistics) ->
+ {MinimumDamage, MaximumDamage} = statistics:get_damages(AttackerStatistics),
+ MaximumRoll = max(1, MaximumDamage - MinimumDamage),
+ MinimumDamage + (rand:uniform(MaximumRoll) - 1).
+
+handle_character_attacking (QueryState, Input) ->
+ BattlemapInstance = QueryState#query_state.battlemap_instance,
+ ControlledCharacterInstance = QueryState#query_state.character_instance,
+ ControlledCharacter =
+ character_instance:get_character(ControlledCharacterInstance),
+ ControlledCharacterStatistics =
+ character:get_statistics(ControlledCharacter),
+ TargettedCharacterInstance =
+ array:get
+ (
+ Input#input.target_id,
+ battlemap_instance:get_characters(BattlemapInstance)
+ ),
+ TargettedCharacter =
+ character_instance:get_character(TargettedCharacterInstance),
+ TargettedCharacterStatistics = character:get_statistics(TargettedCharacter),
+ RequiredRange =
+ movement:steps_between
+ (
+ character_instance:get_location(ControlledCharacterInstance),
+ character_instance:get_location(TargettedCharacterInstance)
+ ),
+ {AttackingWeaponID, _} = character:get_weapon_ids(ControlledCharacter),
+ AttackingWeapon = weapon:from_id(AttackingWeaponID),
+ {_, AttackingWeaponRange} = weapon:get_ranges(AttackingWeapon),
+ {DefendingWeaponID, _} = character:get_weapon_ids(TargettedCharacter),
+ DefendingWeapon = weapon:from_id(DefendingWeaponID),
+ {DefendingWeaponRange, _} = weapon:get_ranges(DefendingWeapon),
+
+ true = (RequiredRange =< AttackingWeaponRange),
+
+ {Rolls, HealthMod} =
+ handle_attack
+ (
+ ControlledCharacterStatistics,
+ TargettedCharacterStatistics
+ ).