From 3fb30b108828e3ad6bf811c0f3372a79ec6e9595 Mon Sep 17 00:00:00 2001 From: Nathanael Sensfelder Date: Mon, 18 Nov 2019 10:40:03 +0100 Subject: ... --- src/battle/struct/btl_character.erl | 249 ++++--- src/battle/struct/btl_condition_parameters.erl | 37 ++ src/battle/struct/btl_conditions.erl | 146 +---- src/battle/struct/btl_status_indicators.erl | 859 +++++++++++++++++++++++++ src/battle/struct/btl_turn_result.erl | 34 +- 5 files changed, 1101 insertions(+), 224 deletions(-) create mode 100644 src/battle/struct/btl_status_indicators.erl (limited to 'src/battle/struct') diff --git a/src/battle/struct/btl_character.erl b/src/battle/struct/btl_character.erl index 9769f8f..41f5535 100644 --- a/src/battle/struct/btl_character.erl +++ b/src/battle/struct/btl_character.erl @@ -1,33 +1,30 @@ -module(btl_character). -define(PLAYER_IX_FIELD, <<"pla">>). --define(RANK_FIELD, <<"rnk">>). -define(LOCATION_FIELD, <<"lc">>). -define(CURRENT_HEALTH_FIELD, <<"he">>). -define(SKILL_POINTS_FIELD, <<"sp">>). -define(IS_ACTIVE_FIELD, <<"ena">>). -define(IS_DEFEATED_FIELD, <<"dea">>). -define(BASE_CHAR_FIELD, <<"bas">>). --define(CONDITIONS_FIELD, <<"con">>). +-define(STATUS_INDICATORS, <<"sti">>). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --type rank() :: ('optional' | 'target' | 'commander'). - -record ( btl_char_ref, { player_ix :: non_neg_integer(), - rank :: rank(), location :: shr_location:type(), current_health :: integer(), %% Negative integers let us reverse attacks. skill_points :: integer(), %% Negative integers let us reverse skill uses. is_active :: boolean(), is_defeated :: boolean(), base :: shr_character:unresolved(), - conditions :: btl_conditions:type() + conditions :: btl_conditions:type(), + status_indicators :: btl_status_indicators:type() } ). @@ -36,21 +33,22 @@ btl_char, { player_ix :: non_neg_integer(), - rank :: rank(), location :: shr_location:type(), current_health :: integer(), %% Negative integers let us reverse attacks. skill_points :: integer(), %% Negative integers let us reverse skill uses. is_active :: boolean(), is_defeated :: boolean(), base :: shr_character:type(), - conditions :: btl_conditions:type() + conditions :: btl_conditions:type(), + status_indicators :: btl_status_indicators:type() } ). -opaque type() :: #btl_char{}. -opaque unresolved() :: #btl_char_ref{}. -type either() :: (type() | unresolved()). --export_type([type/0, unresolved/0, either/0, rank/0]). + +-export_type([type/0, unresolved/0, either/0]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -60,7 +58,6 @@ ( [ get_player_index/1, - get_rank/1, get_location/1, get_current_health/1, get_skill_points/1, @@ -69,8 +66,8 @@ get_is_defeated/1, get_base_character/1, get_conditions/1, + get_status_indicators/1, - set_rank/2, set_location/3, set_current_health/2, set_skill_points/2, @@ -78,8 +75,8 @@ set_is_defeated/2, set_base_character/2, set_conditions/2, + set_status_indicators/2, - ataxia_set_rank/2, ataxia_set_location/3, ataxia_set_current_health/2, ataxia_set_skill_points/2, @@ -87,18 +84,20 @@ ataxia_set_is_defeated/2, ataxia_set_base_character/2, ataxia_set_conditions/2, + ataxia_set_status_indicators/2, ataxia_set_conditions/3, + ataxia_set_status_indicators/3, ataxia_set_base_character/3, - get_rank_field/0, get_current_health_field/0, get_skill_points_field/0, get_is_active_field/0, get_is_defeated_field/0, get_location_field/0, get_base_character_field/0, - get_conditions_field/0 + get_conditions_field/0, + get_status_indicators_field/0 ] ). @@ -147,82 +146,23 @@ handle_max_health_change (OldBaseChar, NewBaseChar, OldHealth) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%% Accessors + +%%%% Accessors %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%% +%%%% Player Index %%%% +%%%%%%%%%%%%%%%%%%%%%% -spec get_player_index (either()) -> non_neg_integer(). get_player_index (#btl_char{ player_ix = R }) -> R; get_player_index (#btl_char_ref{ player_ix = R }) -> R. --spec get_rank (either()) -> rank(). -get_rank (#btl_char{ rank = R }) -> R; -get_rank (#btl_char_ref{ rank = R }) -> R. - +%%%%%%%%%%%%%%%%%% +%%%% Location %%%% +%%%%%%%%%%%%%%%%%% -spec get_location (either()) -> shr_location:type(). get_location (#btl_char{ location = R }) -> R; get_location (#btl_char_ref{ location = R }) -> R. --spec get_current_health (either()) -> integer(). -get_current_health (#btl_char{ current_health = R }) -> R; -get_current_health (#btl_char_ref{ current_health = R }) -> R. - --spec get_skill_points (either()) -> integer(). -get_skill_points (#btl_char{ skill_points = R }) -> R; -get_skill_points (#btl_char_ref{ skill_points = R }) -> R. - --spec get_is_alive (either()) -> boolean(). -get_is_alive (#btl_char{ current_health = H, is_defeated = D }) -> - ((not D) and (H > 0)); -get_is_alive (#btl_char_ref{ current_health = H, is_defeated = D }) -> - ((not D) and (H > 0)). - --spec get_is_active (either()) -> boolean(). -get_is_active -( - #btl_char{ current_health = H, is_defeated = D, is_active = A } -) -> - ((not D) and (H > 0) and A); -get_is_active -( - #btl_char_ref{ current_health = H, is_defeated = D, is_active = A } -) -> - ((not D) and (H > 0) and A). - --spec get_is_defeated (either()) -> boolean(). -get_is_defeated (#btl_char{ is_defeated = R }) -> R; -get_is_defeated (#btl_char_ref{ is_defeated = R }) -> R. - --spec get_base_character - (type()) -> shr_character:type(); - (unresolved()) -> shr_character:unresolved(). -get_base_character (#btl_char{ base = R }) -> R; -get_base_character (#btl_char_ref{ base = R }) -> R. - --spec get_conditions - (type()) -> btl_conditions:type(); - (unresolved()) -> btl_conditions:type(). -get_conditions (#btl_char{ conditions = R }) -> R; -get_conditions (#btl_char_ref{ conditions = R }) -> R. - --spec set_rank - (rank(), type()) -> type(); - (rank(), unresolved()) -> unresolved(). -set_rank (Rank, Char) when is_record(Char, btl_char) -> - Char#btl_char{ rank = Rank }; -set_rank (Rank, Char) when is_record(Char, btl_char_ref) -> - Char#btl_char_ref{ rank = Rank }. - --spec ataxia_set_rank - (rank(), type()) -> {type(), ataxic:basic()}; - (rank(), unresolved()) -> {unresolved(), ataxic:basic()}. -ataxia_set_rank (Rank, Char) -> - { - set_rank(Rank, Char), - ataxic:update_field - ( - get_rank_field(), - ataxic:constant(Rank) - ) - }. - -spec set_location ( shr_location:type(), @@ -296,6 +236,19 @@ ataxia_set_location (Location, LocOmnimods, Char) -> end }. +%%%%%%%%%%%%%%%%%%%%%%%% +%%%% Current Health %%%% +%%%%%%%%%%%%%%%%%%%%%%%% +-spec get_current_health (either()) -> integer(). +get_current_health (#btl_char{ current_health = R }) -> R; +get_current_health (#btl_char_ref{ current_health = R }) -> R. + +-spec get_is_alive (either()) -> boolean(). +get_is_alive (#btl_char{ current_health = H, is_defeated = D }) -> + ((not D) and (H > 0)); +get_is_alive (#btl_char_ref{ current_health = H, is_defeated = D }) -> + ((not D) and (H > 0)). + -spec set_current_health (integer(), type()) -> type(); (integer(), unresolved()) -> unresolved(). @@ -317,6 +270,13 @@ ataxia_set_current_health (Health, Char) -> ) }. +%%%%%%%%%%%%%%%%%%%%%% +%%%% Skill Points %%%% +%%%%%%%%%%%%%%%%%%%%%% +-spec get_skill_points (either()) -> integer(). +get_skill_points (#btl_char{ skill_points = R }) -> R; +get_skill_points (#btl_char_ref{ skill_points = R }) -> R. + -spec set_skill_points (integer(), type()) -> type(); (integer(), unresolved()) -> unresolved(). @@ -338,6 +298,21 @@ ataxia_set_skill_points (SkillPoints, Char) -> ) }. +%%%%%%%%%%%%%%%%%%% +%%%% Is Active %%%% +%%%%%%%%%%%%%%%%%%% +-spec get_is_active (either()) -> boolean(). +get_is_active +( + #btl_char{ current_health = H, is_defeated = D, is_active = A } +) -> + ((not D) and (H > 0) and A); +get_is_active +( + #btl_char_ref{ current_health = H, is_defeated = D, is_active = A } +) -> + ((not D) and (H > 0) and A). + -spec set_is_active (boolean(), type()) -> type(); (boolean(), unresolved()) -> unresolved(). @@ -359,6 +334,13 @@ ataxia_set_is_active (Active, Char) -> ) }. +%%%%%%%%%%%%%%%%%%%%% +%%%% Is Defeated %%%% +%%%%%%%%%%%%%%%%%%%%% +-spec get_is_defeated (either()) -> boolean(). +get_is_defeated (#btl_char{ is_defeated = R }) -> R; +get_is_defeated (#btl_char_ref{ is_defeated = R }) -> R. + -spec set_is_defeated (boolean(), type()) -> type(); (boolean(), unresolved()) -> unresolved(). @@ -380,6 +362,15 @@ ataxia_set_is_defeated (Defeated, Char) -> ) }. +%%%%%%%%%%%%%%%%%%%%%%%% +%%%% Base Character %%%% +%%%%%%%%%%%%%%%%%%%%%%%% +-spec get_base_character + (type()) -> shr_character:type(); + (unresolved()) -> shr_character:unresolved(). +get_base_character (#btl_char{ base = R }) -> R; +get_base_character (#btl_char_ref{ base = R }) -> R. + -spec set_base_character (shr_character:type(), type()) -> type(). set_base_character (NewBaseCharacter, Char) -> CurrentBaseCharacter = Char#btl_char.base, @@ -456,6 +447,15 @@ ataxia_set_base_character (NewBaseCharacter, Char) -> Char ). +%%%%%%%%%%%%%%%%%%%% +%%%% Conditions %%%% +%%%%%%%%%%%%%%%%%%%% +-spec get_conditions + (type()) -> btl_conditions:type(); + (unresolved()) -> btl_conditions:type(). +get_conditions (#btl_char{ conditions = R }) -> R; +get_conditions (#btl_char_ref{ conditions = R }) -> R. + -spec set_conditions (btl_conditions:type(), type()) -> type(); (btl_conditions:type(), unresolved()) -> unresolved(). @@ -464,7 +464,6 @@ set_conditions (Conditions, Char) when is_record(Char, btl_char) -> set_conditions (Conditions, Char) when is_record(Char, btl_char_ref) -> Char#btl_char_ref{ conditions = Conditions }. - -spec ataxia_set_conditions ( btl_conditions:type(), @@ -498,37 +497,90 @@ ataxia_set_conditions (Conditions, Char) -> Char ). +%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%% Status Indicators %%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec get_status_indicators + (type()) -> btl_status_indicators:type(); + (unresolved()) -> btl_status_indicators:type(). +get_status_indicators (#btl_char{ status_indicators = R }) -> R; +get_status_indicators (#btl_char_ref{ status_indicators = R }) -> R. + +-spec set_status_indicators + (btl_status_indicators:type(), type()) -> type(); + (btl_status_indicators:type(), unresolved()) -> unresolved(). +set_status_indicators (StatusIndicators, Char) when is_record(Char, btl_char) -> + Char#btl_char{ status_indicators = StatusIndicators }; +set_status_indicators (StatusIndicators, Char) when is_record(Char, btl_char_ref) -> + Char#btl_char_ref{ status_indicators = StatusIndicators }. + +-spec ataxia_set_status_indicators + ( + btl_status_indicators:type(), + ataxic:basic(), + type() + ) + -> {type(), ataxic:basic()}; + ( + btl_status_indicators:type(), + ataxic:basic(), + unresolved() + ) -> {unresolved(), ataxic:basic()}. +ataxia_set_status_indicators (StatusIndicators, Update, Char) -> + { + set_status_indicators(StatusIndicators, Char), + ataxic:update_field + ( + get_status_indicators_field(), + Update + ) + }. + +-spec ataxia_set_status_indicators + (btl_status_indicators:type(), type()) -> {type(), ataxic:basic()}; + ( + btl_status_indicators:type(), + unresolved() + ) -> {unresolved(), ataxic:basic()}. +ataxia_set_status_indicators (StatusIndicators, Char) -> + ataxia_set_status_indicators + ( + StatusIndicators, + ataxic:constant(StatusIndicators), + Char + ). + %%%% Utils -spec new ( non_neg_integer(), - rank(), shr_location:type(), shr_character:type(), - btl_conditions:type() + btl_conditions:type(), + btl_status_indicators:type() ) -> type(). new ( PlayerIX, - Rank, Location, Base, - Conditions + Conditions, + StatusIndicators ) -> Attributes = shr_character:get_attributes(Base), #btl_char { player_ix = PlayerIX, - rank = Rank, location = Location, current_health = shr_attributes:get_health(Attributes), skill_points = 0, is_active = (PlayerIX == 0), is_defeated = false, base = Base, - conditions = Conditions + conditions = Conditions, + status_indicators = StatusIndicators }. -spec resolve (shr_omnimods:type(), either()) -> type(). @@ -536,14 +588,14 @@ resolve (LocalOmnimods, CharRef) when is_record(CharRef, btl_char_ref) -> #btl_char { player_ix = CharRef#btl_char_ref.player_ix, - rank = CharRef#btl_char_ref.rank, location = CharRef#btl_char_ref.location, current_health = CharRef#btl_char_ref.current_health, skill_points = CharRef#btl_char_ref.skill_points, is_active = CharRef#btl_char_ref.is_active, is_defeated = CharRef#btl_char_ref.is_defeated, base = shr_character:resolve(LocalOmnimods, CharRef#btl_char_ref.base), - conditions = CharRef#btl_char_ref.conditions + conditions = CharRef#btl_char_ref.conditions, + status_indicators = CharRef#btl_char_ref.status_indicators }; resolve (_LocalOmnimods, Char) when is_record(Char, btl_char) -> Char. @@ -552,22 +604,20 @@ to_unresolved (Char) when is_record(Char, btl_char) -> #btl_char_ref { player_ix = Char#btl_char.player_ix, - rank = Char#btl_char.rank, location = Char#btl_char.location, current_health = Char#btl_char.current_health, skill_points = Char#btl_char.skill_points, is_active = Char#btl_char.is_active, is_defeated = Char#btl_char.is_defeated, base = shr_character:to_unresolved(Char#btl_char.base), - conditions = Char#btl_char.conditions + conditions = Char#btl_char.conditions, + status_indicators = Char#btl_char.status_indicators }; to_unresolved (CharRef) when is_record(CharRef, btl_char_ref) -> CharRef. -spec is_unresolved (either()) -> boolean(). is_unresolved (Char) -> is_record(Char, btl_char_ref). --spec get_rank_field() -> non_neg_integer(). -get_rank_field () -> #btl_char_ref.rank. -spec get_location_field() -> non_neg_integer(). get_location_field () -> #btl_char_ref.location. -spec get_current_health_field() -> non_neg_integer(). @@ -582,13 +632,14 @@ get_is_defeated_field () -> #btl_char_ref.is_defeated. get_base_character_field () -> #btl_char_ref.base. -spec get_conditions_field() -> non_neg_integer(). get_conditions_field () -> #btl_char_ref.conditions. +-spec get_status_indicators_field() -> non_neg_integer(). +get_status_indicators_field () -> #btl_char_ref.status_indicators. -spec encode_for (non_neg_integer(), unresolved()) -> {list({binary(), any()})}. encode_for (RequestingPlayerIX, CharRef) -> { [ {?PLAYER_IX_FIELD, CharRef#btl_char_ref.player_ix}, - {?RANK_FIELD, CharRef#btl_char_ref.rank}, {?LOCATION_FIELD, shr_location:encode(CharRef#btl_char_ref.location)}, {?CURRENT_HEALTH_FIELD, CharRef#btl_char_ref.current_health}, {?SKILL_POINTS_FIELD, CharRef#btl_char_ref.skill_points}, @@ -596,11 +647,11 @@ encode_for (RequestingPlayerIX, CharRef) -> {?IS_DEFEATED_FIELD, CharRef#btl_char_ref.is_defeated}, {?BASE_CHAR_FIELD, shr_character:encode(CharRef#btl_char_ref.base)}, { - ?CONDITIONS_FIELD, - btl_conditions:encode_for + ?STATUS_INDICATORS, + btl_status_indicators:encode_for ( RequestingPlayerIX, - CharRef#btl_char_ref.conditions + CharRef#btl_char_ref.status_indicators ) } ] diff --git a/src/battle/struct/btl_condition_parameters.erl b/src/battle/struct/btl_condition_parameters.erl index eb78245..e00dfeb 100644 --- a/src/battle/struct/btl_condition_parameters.erl +++ b/src/battle/struct/btl_condition_parameters.erl @@ -35,6 +35,11 @@ ataxia_set_targets/2, ataxia_set_targets/3, + get_locations/1, + set_locations/2, + ataxia_set_locations/2, + ataxia_set_locations/3, + get_uses/1, set_uses/2, ataxia_set_uses/2, @@ -58,6 +63,38 @@ %% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%% +%%%% Locations %%%% +%%%%%%%%%%%%%%%%% +-spec get_locations (type(_)) -> list(shr_location:type()). +get_locations (Params) -> Params#btl_cond_params.locations. + +-spec set_locations (list(shr_location:type()), type(ODT)) -> type(ODT). +set_locations (Locations, Params) -> + Params#btl_cond_params{ locations = Locations }. + +-spec ataxia_set_locations + ( + list(shr_location:type()), + type(ODT) + ) + -> {type(ODT), ataxic:basic()}. +ataxia_set_locations (Locations, Params) -> + ataxia_set_locations(Locations, ataxic:constant(Locations), Params). + +-spec ataxia_set_locations + ( + list(shr_location:type()), + ataxic:basic(), + type(ODT) + ) + -> {type(ODT), ataxic:basic()}. +ataxia_set_locations (Locations, LocationsAtaxicUpdate, Params) -> + { + set_locations(Locations, Params), + ataxic:update_field(#btl_cond_params.locations, LocationsAtaxicUpdate) + }. + %%%%%%%%%%%%%%%%% %%%% Targets %%%% %%%%%%%%%%%%%%%%% diff --git a/src/battle/struct/btl_conditions.erl b/src/battle/struct/btl_conditions.erl index 70ceed6..69f1ac8 100644 --- a/src/battle/struct/btl_conditions.erl +++ b/src/battle/struct/btl_conditions.erl @@ -5,13 +5,6 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -include("tacticians/conditions.hrl"). --type visibility() :: - ( - none - | {limited, ordsets:ordset(non_neg_integer())} % PlayerIXs - | all - ). - -type ref() :: ( {char, non_neg_integer(), non_neg_integer()} @@ -24,8 +17,7 @@ { category :: shr_condition:id(), triggers :: ordsets:ordset(shr_condition:trigger()), - parameters :: btl_condition_parameters:type(any()), - visibility :: visibility() + parameters :: btl_condition_parameters:type(any()) } ). @@ -52,7 +44,6 @@ [ type/0, ref/0, - visibility/0, single/0 ] ). @@ -72,19 +63,15 @@ get_triggers/1, set_triggers/3, % IX, Value, Conditions - ataxia_set_triggers/3, % IX, Value, Conditions - - get_visibility/1, - set_visibility/3, % IX, Value, Conditions - ataxia_set_visibility/3 % IX, Value, Conditions + ataxia_set_triggers/3 % IX, Value, Conditions ] ). -export ( [ - add/5, - ataxia_add/5, + add/4, + ataxia_add/4, remove/2, ataxia_remove/2, new/0 @@ -99,13 +86,6 @@ ] ). --export -( - [ - encode_for/2 - ] -). - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -185,31 +165,6 @@ compute_next_index (Conditions) -> Result. --spec encode_single (non_neg_integer(), single()) -> {list({binary(), any()})}. -encode_single (IX, Condition) -> - Module = - shr_condition:get_module - ( - shr_condition:from_id(Condition#btl_cond.category) - ), - - EncodedParameters = - erlang:apply - ( - Module, - encode_parameters, - [ - Condition#btl_cond.parameters - ] - ), - - { - [ - {<<"ix">>, IX}, - {<<"p">>, EncodedParameters} - ] - }. - -spec get_relevant_condition_indices ( shr_condition:trigger(), @@ -227,12 +182,20 @@ get_relevant_condition_indices(Trigger, Conditions) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% Accessors %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec get_condition (ref(), btl_character_turn_update:type()) -> single(). +-spec get_condition + ( + ref(), + btl_character_turn_update:type() + ) + -> ({ok, single()} | none). get_condition ({battle, IX}, Update) -> Conditions = btl_battle:get_conditions(btl_character_turn_update:get_battle(Update)), - orddict:fetch(IX, Conditions#btl_conds.collection); + case orddict:find(IX, Conditions#btl_conds.collection) of + error -> none; + Other -> Other + end; get_condition ({char, CharIX, CondIX}, Update) -> Conditions = btl_character:get_conditions @@ -244,53 +207,10 @@ get_condition ({char, CharIX, CondIX}, Update) -> ) ), - orddict:fetch(CondIX, Conditions#btl_conds.collection). - -%%%%%%%%%%%%%%%%%%%% -%%%% Visibility %%%% -%%%%%%%%%%%%%%%%%%%% --spec get_visibility (single()) -> visibility(). -get_visibility (Condition) -> Condition#btl_cond.visibility. - --spec set_visibility (non_neg_integer(), visibility(), type()) -> type(). -set_visibility (IX, NewVisibility, Conditions) -> - Conditions#btl_conds - { - collection = - orddict:update - ( - IX, - fun (Condition) -> - Condition#btl_cond{ visibility = NewVisibility } - end, - Conditions#btl_conds.collection - ) - }. - --spec ataxia_set_visibility - ( - non_neg_integer(), - visibility(), - type() - ) - -> {type(), ataxic:basic()}. -ataxia_set_visibility (IX, NewVisibility, Conditions) -> - { - set_visibility(IX, NewVisibility, Conditions), - ataxic:update_field - ( - #btl_conds.collection, - ataxic_sugar:update_orddict_element - ( - IX, - ataxic:update_field - ( - #btl_cond.visibility, - ataxic:constant(NewVisibility) - ) - ) - ) - }. + case orddict:find(CondIX, Conditions#btl_conds.collection) of + error -> none; + Other -> Other + end. %%%%%%%%%%%%%%%%%% %%%% Triggers %%%% @@ -640,18 +560,16 @@ apply_to_battle shr_condition:id(), ordsets:ordset(shr_condition:trigger()), any(), - visibility(), type() ) -> {type(), non_neg_integer()}. -add (CondID, Triggers, Params, Visibility, Conditions) -> +add (CondID, Triggers, Params, Conditions) -> NewCondition = #btl_cond { category = CondID, triggers = Triggers, - parameters = Params, - visibility = Visibility + parameters = Params }, NewConditionIX = compute_next_index(Conditions), @@ -693,18 +611,16 @@ add (CondID, Triggers, Params, Visibility, Conditions) -> shr_condition:id(), ordsets:ordset(shr_condition:trigger()), any(), - visibility(), type() ) -> {type(), non_neg_integer(), ataxic:basic()}. -ataxia_add (CondID, Triggers, Params, Visibility, Conditions) -> +ataxia_add (CondID, Triggers, Params, Conditions) -> NewCondition = #btl_cond { category = CondID, triggers = Triggers, - parameters = Params, - visibility = Visibility + parameters = Params }, NewConditionIX = compute_next_index(Conditions), @@ -846,21 +762,3 @@ new () -> collection = orddict:new(), from_trigger = orddict:new() }. - --spec encode_for (non_neg_integer(), type()) -> list(any()). -encode_for (PlayerIX, Conditions) -> - lists:filtermap - ( - fun ({IX, Condition}) -> - case Condition#btl_cond.visibility of - none -> false; - all -> encode_single(IX, Condition); - {limited, AllowedPlayerIXs} -> - case ordsets:is_element(PlayerIX, AllowedPlayerIXs) of - false -> false; - true -> {true, encode_single(IX, Condition)} - end - end - end, - orddict:to_list(Conditions#btl_conds.collection) - ). diff --git a/src/battle/struct/btl_status_indicators.erl b/src/battle/struct/btl_status_indicators.erl new file mode 100644 index 0000000..9c852d4 --- /dev/null +++ b/src/battle/struct/btl_status_indicators.erl @@ -0,0 +1,859 @@ +-module(btl_status_indicators). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-type visibility() :: + ( + none + | {limited, ordsets:ordset(non_neg_integer())} % PlayerIXs + | all + ). + +-type ref() :: + ( + {char, non_neg_integer(), non_neg_integer()} + | {battle, non_neg_integer()} + ). + +-record +( + btl_sti, + { + icon :: binary(), + extra :: binary(), + visibility :: visibility() + } +). + +-type single() :: #btl_cond{}. +-type type () :: orddict:orddict(non_neg_integer(), single()), + +-export_type +( + [ + type/0, + ref/0, + visibility/0, + single/0 + ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export +( + [ + get_status_indicator/2, + + get_parameters/1, + set_parameters/3, % IX, Value, Conditions + ataxia_set_parameters/3, % IX, Value, Conditions + ataxia_set_parameters/4, % IX, Value, Conditions + + get_triggers/1, + set_triggers/3, % IX, Value, Conditions + ataxia_set_triggers/3, % IX, Value, Conditions + + get_visibility/1, + set_visibility/3, % IX, Value, Conditions + ataxia_set_visibility/3 % IX, Value, Conditions + ] +). + +-export +( + [ + add/5, + ataxia_add/5, + remove/2, + ataxia_remove/2, + new/0 + ] +). + +-export +( + [ + apply_to_character/5, + apply_to_battle/4 + ] +). + +-export +( + [ + encode_for/2 + ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec apply_trigger + ( + shr_condition:context(_ReadOnlyDataType, VolatileDataType), + fun((non_neg_integer()) -> ref()), + btl_character_turn_update:type(), + ordsets:ordset(non_neg_integer()), + type() + ) + -> {VolatileDataType, btl_character_turn_update:type()}. +apply_trigger (Context, IXtoRef, S0Update, RelevantIndices, Conditions) -> + {Trigger, ReadOnlyData, S0VolatileData} = Context, + + ConditionCollection = Conditions#btl_conds.collection, + + {LastVolatileData, LastUpdate} = + ordsets:fold + ( + fun (IX, {CurrentVolatileData, CurrentUpdate}) -> + case orddict:find(IX, ConditionCollection) of + {ok, Condition} -> + Module = + shr_condition:get_module + ( + shr_condition:from_id(Condition#btl_cond.category) + ), + + {NextVolatileData, NextUpdate} = + erlang:apply + ( + Module, + apply, + [ + IXtoRef(IX), + CurrentUpdate, + {Trigger, ReadOnlyData, CurrentVolatileData} + ] + ), + + {NextVolatileData, NextUpdate}; + + error -> + % TODO: Remove the condition. + {CurrentVolatileData, CurrentUpdate} + end + end, + {S0VolatileData, S0Update, []}, + RelevantIndices + ), + + {LastVolatileData, LastUpdate}. + +-spec compute_next_index (type()) -> non_neg_integer(). +compute_next_index (Conditions) -> + Collection = Conditions#btl_conds.collection, + CollectionSize = orddict:size(Collection), + Candidates = lists:seq(0, CollectionSize), + + Result = + lists:foldr + ( + fun (Candidate, CurrentResult) -> + case is_integer(CurrentResult) of + true -> CurrentResult; + false -> + case orddict:is_key(Candidate, Collection) of + true -> none; + false -> Candidate + end + end + end, + none, + Candidates + ), + + Result. + +-spec encode_single (non_neg_integer(), single()) -> {list({binary(), any()})}. +encode_single (IX, Condition) -> + Module = + shr_condition:get_module + ( + shr_condition:from_id(Condition#btl_cond.category) + ), + + EncodedParameters = + erlang:apply + ( + Module, + encode_parameters, + [ + Condition#btl_cond.parameters + ] + ), + + { + [ + {<<"ix">>, IX}, + {<<"p">>, EncodedParameters} + ] + }. + +-spec get_relevant_condition_indices + ( + shr_condition:trigger(), + type() + ) + -> ordsets:ordset(non_neg_integer()). +get_relevant_condition_indices(Trigger, Conditions) -> + case orddict:find(Trigger, Conditions#btl_conds.from_trigger) of + {ok, Result} -> Result; + _ -> ordsets:new() + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%% Accessors %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec get_condition + ( + ref(), + btl_character_turn_update:type() + ) + -> ({ok, single()} | none). +get_condition ({battle, IX}, Update) -> + Conditions = + btl_battle:get_conditions(btl_character_turn_update:get_battle(Update)), + + case orddict:find(IX, Conditions#btl_conds.collection) of + error -> none; + Other -> Other + end; +get_condition ({char, CharIX, CondIX}, Update) -> + Conditions = + btl_character:get_conditions + ( + btl_battle:get_character + ( + CharIX, + btl_character_turn_update:get_battle(Update) + ) + ), + + case orddict:find(CondIX, Conditions#btl_conds.collection) of + error -> none; + Other -> Other + end. + +%%%%%%%%%%%%%%%%%%%% +%%%% Visibility %%%% +%%%%%%%%%%%%%%%%%%%% +-spec get_visibility (single()) -> visibility(). +get_visibility (Condition) -> Condition#btl_cond.visibility. + +-spec set_visibility (non_neg_integer(), visibility(), type()) -> type(). +set_visibility (IX, NewVisibility, Conditions) -> + Conditions#btl_conds + { + collection = + orddict:update + ( + IX, + fun (Condition) -> + Condition#btl_cond{ visibility = NewVisibility } + end, + Conditions#btl_conds.collection + ) + }. + +-spec ataxia_set_visibility + ( + non_neg_integer(), + visibility(), + type() + ) + -> {type(), ataxic:basic()}. +ataxia_set_visibility (IX, NewVisibility, Conditions) -> + { + set_visibility(IX, NewVisibility, Conditions), + ataxic:update_field + ( + #btl_conds.collection, + ataxic_sugar:update_orddict_element + ( + IX, + ataxic:update_field + ( + #btl_cond.visibility, + ataxic:constant(NewVisibility) + ) + ) + ) + }. + +%%%%%%%%%%%%%%%%%% +%%%% Triggers %%%% +%%%%%%%%%%%%%%%%%% +-spec get_triggers (single()) -> ordsets:ordset(shr_condition:trigger()). +get_triggers (Condition) -> Condition#btl_cond.triggers. + +-spec set_triggers + ( + non_neg_integer(), + ordsets:ordset(shr_condition:trigger()), + type() + ) + -> type(). +set_triggers (IX, NewTriggers, Conditions) -> + CurrentCondition = orddict:fetch(IX, Conditions#btl_conds.collection), + CurrentTriggers = CurrentCondition#btl_cond.triggers, + AddedTriggers = ordsets:subtract(NewTriggers, CurrentTriggers), + RemovedTriggers = ordsets:subtract(CurrentTriggers, NewTriggers), + + S0FromTrigger = + ordsets:fold + ( + fun (Trigger, FromTrigger) -> + orddict:update + ( + Trigger, + fun (ConditionIXs) -> + ordsets:del_element(IX, ConditionIXs) + end, + FromTrigger + ) + end, + Conditions#btl_conds.from_trigger, + RemovedTriggers + ), + + S1FromTrigger = + ordsets:fold + ( + fun (Trigger, FromTrigger) -> + orddict:update + ( + Trigger, + fun (ConditionIXs) -> + ordsets:add_element(IX, ConditionIXs) + end, + FromTrigger + ) + end, + S0FromTrigger, + AddedTriggers + ), + + Conditions#btl_conds + { + from_trigger = S1FromTrigger, + collection = + orddict:update + ( + IX, + fun (Condition) -> Condition#btl_cond{ triggers = NewTriggers } end, + Conditions#btl_conds.collection + ) + }. + +-spec ataxia_set_triggers + ( + non_neg_integer(), + ordsets:ordset(shr_condition:trigger()), + type() + ) + -> {type(), ataxic:basic()}. +ataxia_set_triggers (IX, NewTriggers, Conditions) -> + CurrentCondition = orddict:fetch(IX, Conditions#btl_conds.collection), + CurrentTriggers = CurrentCondition#btl_cond.triggers, + AddedTriggers = ordsets:subtract(NewTriggers, CurrentTriggers), + RemovedTriggers = ordsets:subtract(CurrentTriggers, NewTriggers), + AtaxicFromTriggerParams = [ataxic:constant(IX), ataxic:current_value()], + + {S0FromTrigger, S0FromTriggerAtaxicUpdates} = + ordsets:fold + ( + fun (Trigger, {FromTrigger, PrevFromTriggerAtaxicUpdates}) -> + { + orddict:update + ( + Trigger, + fun (ConditionIXs) -> + ordsets:del_element(IX, ConditionIXs) + end, + FromTrigger + ), + [ + ataxic_sugar:update_orddict_element + ( + IX, + ataxic:apply_function + ( + ordsets, + del_element, + AtaxicFromTriggerParams + ) + ) + | PrevFromTriggerAtaxicUpdates + ] + } + end, + {Conditions#btl_conds.from_trigger, []}, + RemovedTriggers + ), + + {S1FromTrigger, S1FromTriggerAtaxicUpdates} = + ordsets:fold + ( + fun (Trigger, {FromTrigger, PrevFromTriggerAtaxicUpdates}) -> + { + orddict:update + ( + Trigger, + fun (ConditionIXs) -> + ordsets:add_element(IX, ConditionIXs) + end, + FromTrigger + ), + [ + ataxic_sugar:update_orddict_element + ( + IX, + ataxic:apply_function + ( + ordsets, + add_element, + AtaxicFromTriggerParams + ) + ) + | PrevFromTriggerAtaxicUpdates + ] + } + end, + {S0FromTrigger, S0FromTriggerAtaxicUpdates}, + AddedTriggers + ), + + { + Conditions#btl_conds + { + from_trigger = S1FromTrigger, + collection = + orddict:update + ( + IX, + fun (Condition) -> + Condition#btl_cond{ triggers = NewTriggers } + end, + Conditions#btl_conds.collection + ) + }, + ataxic:sequence + ( + [ + ataxic:update_field + ( + #btl_conds.collection, + ataxic_sugar:update_orddict_element + ( + IX, + ataxic:update_field + ( + #btl_cond.triggers, + ataxic:sequence + ( + [ + ataxic:apply_function + ( + ordsets, + subtract, + [ + ataxic:current_value(), + ataxic:constant(RemovedTriggers) + ] + ), + ataxic:apply_function + ( + ordsets, + union, + [ + ataxic:current_value(), + ataxic:constant(AddedTriggers) + ] + ) + ] + ) + ) + ) + ), + ataxic:update_field + ( + #btl_conds.from_trigger, + ataxic:sequence(S1FromTriggerAtaxicUpdates) + ) + ] + ) + }. + +%%%%%%%%%%%%%%%%%%%% +%%%% Parameters %%%% +%%%%%%%%%%%%%%%%%%%% +-spec get_parameters (single()) -> any(). +get_parameters (Condition) -> Condition#btl_cond.parameters. + +-spec set_parameters (non_neg_integer(), any(), type()) -> type(). +set_parameters (IX, NewValue, Conditions) -> + Conditions#btl_conds + { + collection = + orddict:update + ( + IX, + fun (Condition) -> Condition#btl_cond{ parameters = NewValue } end, + Conditions#btl_conds.collection + ) + }. + +-spec ataxia_set_parameters + ( + non_neg_integer(), + any(), + type() + ) + -> {type(), ataxic:basic()}. +ataxia_set_parameters (IX, NewValue, Conditions) -> + ataxia_set_parameters(IX, NewValue, ataxic:constant(NewValue), Conditions). + +-spec ataxia_set_parameters + ( + non_neg_integer(), + any(), + ataxic:basic(), + type() + ) + -> {type(), ataxic:basic()}. +ataxia_set_parameters (IX, NewValue, ParamsAtaxicUpdate, Conditions) -> + { + set_parameters(IX, NewValue, Conditions), + ataxic:update_field + ( + #btl_conds.collection, + ataxic_sugar:update_orddict_element + ( + IX, + ataxic:update_field + ( + #btl_cond.parameters, + ParamsAtaxicUpdate + ) + ) + ) + }. + +%%%% Apply %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec apply_to_character + ( + non_neg_integer(), + shr_condition:trigger(), + any(), + VolatileDataType, + btl_character_turn_update:type() + ) + -> {VolatileDataType, btl_character_turn_update:type()}. +apply_to_character +( + ActorIX, + Trigger, + ReadOnlyData, + S0VolatileData, + S0Update +) -> + S0Battle = btl_character_turn_update:get_battle(S0Update), + {S0Actor, S1Battle} = btl_battle:get_resolved_character(ActorIX, S0Battle), + S1Update = btl_character_turn_update:set_battle(S1Battle, S0Update), + + CharacterConditions = btl_character:get_conditions(S0Actor), + MatchingConditionIndices = + get_relevant_condition_indices(Trigger, CharacterConditions), + + case ordsets:is_empty(MatchingConditionIndices) of + true -> {S0VolatileData, S1Update}; + false -> + {S1VolatileContext, S2Update} = + apply_trigger + ( + {Trigger, ReadOnlyData, S0VolatileData}, + fun (IX) -> {char, ActorIX, IX} end, + S1Update, + MatchingConditionIndices, + CharacterConditions + ), + + {S1VolatileContext, S2Update} + end. + +-spec apply_to_battle + ( + shr_condition:trigger(), + any(), + VolatileDataType, + btl_character_turn_update:type() + ) + -> {VolatileDataType, btl_character_turn_update:type()}. +apply_to_battle +( + Trigger, + ReadOnlyData, + S0VolatileData, + S0Update +) -> + S0Battle = btl_character_turn_update:get_battle(S0Update), + + BattleConditions = btl_battle:get_conditions(S0Battle), + MatchingConditionIndices = + get_relevant_condition_indices(Trigger, BattleConditions), + + case ordsets:is_empty(MatchingConditionIndices) of + true -> {S0VolatileData, S0Update}; + false -> + {S1VolatileContext, S1Update} = + apply_trigger + ( + {Trigger, ReadOnlyData, S0VolatileData}, + fun (IX) -> {battle, IX} end, + S0Update, + MatchingConditionIndices, + BattleConditions + ), + + {S1VolatileContext, S1Update} + end. + +%%%% Add/Remove Elements %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%% +%%%% Add %%%% +%%%%%%%%%%%%% +-spec add + ( + shr_condition:id(), + ordsets:ordset(shr_condition:trigger()), + any(), + visibility(), + type() + ) + -> {type(), non_neg_integer()}. +add (CondID, Triggers, Params, Visibility, Conditions) -> + NewCondition = + #btl_cond + { + category = CondID, + triggers = Triggers, + parameters = Params, + visibility = Visibility + }, + + NewConditionIX = compute_next_index(Conditions), + + UpdatedCollection = + orddict:store + ( + NewConditionIX, + NewCondition, + Conditions#btl_conds.collection + ), + + UpdatedFromTrigger = + ordsets:fold + ( + fun (Trigger, FromTrigger) -> + orddict:update + ( + Trigger, + fun (Set) -> ordsets:add_element(NewConditionIX, Set) end, + FromTrigger + ) + end, + Conditions#btl_conds.from_trigger, + Triggers + ), + + { + Conditions#btl_conds + { + collection = UpdatedCollection, + from_trigger = UpdatedFromTrigger + }, + NewConditionIX + }. + +-spec ataxia_add + ( + shr_condition:id(), + ordsets:ordset(shr_condition:trigger()), + any(), + visibility(), + type() + ) + -> {type(), non_neg_integer(), ataxic:basic()}. +ataxia_add (CondID, Triggers, Params, Visibility, Conditions) -> + NewCondition = + #btl_cond + { + category = CondID, + triggers = Triggers, + parameters = Params, + visibility = Visibility + }, + + NewConditionIX = compute_next_index(Conditions), + AtaxicNewConditionIX = ataxic:constant(NewConditionIX), + + UpdatedCollection = + orddict:store + ( + NewConditionIX, + NewCondition, + Conditions#btl_conds.collection + ), + + CollectionAtaxicUpdate = + ataxic:apply_function + ( + orddict, + store, + [ + AtaxicNewConditionIX, + ataxic:constant(NewCondition), + ataxic:current_value() + ] + ), + + SetAtaxicUpdate = + ataxic:apply_function + ( + ordsets, + add_element, + [ + AtaxicNewConditionIX, + ataxic:current_value() + ] + ), + + {UpdatedFromTrigger, FromTriggerAtaxicUpdateList} = + ordsets:fold + ( + fun (Trigger, {FromTrigger, FromTriggerUpdates}) -> + { + orddict:update + ( + Trigger, + fun (Set) -> ordsets:add_element(NewConditionIX, Set) end, + FromTrigger + ), + [ + ataxic_sugar:update_orddict_element + ( + Trigger, + SetAtaxicUpdate + ) + | FromTriggerUpdates + ] + } + end, + Conditions#btl_conds.from_trigger, + Triggers + ), + + { + Conditions#btl_conds + { + collection = UpdatedCollection, + from_trigger = UpdatedFromTrigger + }, + NewConditionIX, + ataxic:sequence + ( + [ + ataxic:update_field + ( + #btl_conds.collection, + CollectionAtaxicUpdate + ), + ataxic:update_field + ( + #btl_conds.from_trigger, + ataxic:sequence(FromTriggerAtaxicUpdateList) + ) + ] + ) + }. + +%%%%%%%%%%%%%%%% +%%%% Remove %%%% +%%%%%%%%%%%%%%%% +-spec remove (non_neg_integer(), type()) -> type(). +remove (IX, S0Conditions) -> + S1Conditions = set_triggers(IX, ordsets:new(), S0Conditions), + S2Conditions = + S1Conditions#btl_conds + { + collection = orddict:erase(IX, S1Conditions#btl_conds.collection) + }, + + S2Conditions. + +-spec ataxia_remove (non_neg_integer(), type()) -> {type(), ataxic:basic()}. +ataxia_remove (IX, S0Conditions) -> + {S1Conditions, ConditionsAtaxicUpdate1} = + ataxia_set_triggers(IX, ordsets:new(), S0Conditions), + + S2Conditions = + S1Conditions#btl_conds + { + collection = orddict:erase(IX, S1Conditions#btl_conds.collection) + }, + + { + S2Conditions, + ataxic:sequence + ( + [ + ConditionsAtaxicUpdate1, + ataxic:update_field + ( + #btl_conds.collection, + ataxic:apply_function + ( + orddict, + erase, + [ + ataxic:constant(IX), + ataxic:current_value() + ] + ) + ) + ] + ) + }. + +%%%% Other %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec new () -> type(). +new () -> + #btl_conds + { + collection = orddict:new(), + from_trigger = orddict:new() + }. + +-spec encode_for (non_neg_integer(), type()) -> list(any()). +encode_for (PlayerIX, Conditions) -> + lists:filtermap + ( + fun ({IX, Condition}) -> + case Condition#btl_cond.visibility of + none -> false; + all -> encode_single(IX, Condition); + {limited, AllowedPlayerIXs} -> + case ordsets:is_element(PlayerIX, AllowedPlayerIXs) of + false -> false; + true -> {true, encode_single(IX, Condition)} + end + end + end, + orddict:to_list(Conditions#btl_conds.collection) + ). diff --git a/src/battle/struct/btl_turn_result.erl b/src/battle/struct/btl_turn_result.erl index 3e1be50..d8e20c0 100644 --- a/src/battle/struct/btl_turn_result.erl +++ b/src/battle/struct/btl_turn_result.erl @@ -3,7 +3,15 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% +-record +( + condition, + { + module :: atom(), + params :: any() + } +). + -record ( switched_weapon, @@ -80,6 +88,7 @@ | #player_won{} | #player_lost{} | #player_turn_started{} + | #condition{} ). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -90,6 +99,7 @@ -export ( [ + new_condition/2, new_player_won/1, new_player_lost/1, new_player_turn_started/1, @@ -114,6 +124,10 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec new_condition (atom(), any()) -> type(). +new_condition (Module, Params) -> + #condition{ module = Module, params = Params }. + -spec new_player_won (non_neg_integer()) -> type(). new_player_won (PlayerIX) -> #player_won { player_ix = PlayerIX }. @@ -280,5 +294,23 @@ encode (TurnResult) when is_record(TurnResult, player_turn_started) -> {<<"ix">>, PlayerIX} ] }; +encode (TurnResult) when is_record(TurnResult, condition) -> + {ModuleID, EncodedParams} = + erlang:apply + ( + TurnResult#condition.module, + encode_turn_result, + [ + TurnResult#condition.params + ] + ), + + { + [ + {<<"t">>, <<"con">>}, + {<<"m">>, ModuleID}, + {<<"p">>, EncodedParams} + ] + }; encode (Other) -> error(io_lib:format("~n invalid encode param\"~p\"~n", [Other])). -- cgit v1.2.3-70-g09d2