| summaryrefslogtreecommitdiff | 
diff options
| author | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2019-11-18 10:40:03 +0100 | 
|---|---|---|
| committer | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2019-11-18 10:40:03 +0100 | 
| commit | 3fb30b108828e3ad6bf811c0f3372a79ec6e9595 (patch) | |
| tree | ef12976907cea83f7ef70168173d487b3cdc018e | |
| parent | cc4e39960d3c56fceb2e31c01bf286dccc73615c (diff) | |
...
| -rw-r--r-- | src/battle/mechanic/condition/btl_cond_heal.erl | 17 | ||||
| -rw-r--r-- | src/battle/struct/btl_character.erl | 249 | ||||
| -rw-r--r-- | src/battle/struct/btl_condition_parameters.erl | 37 | ||||
| -rw-r--r-- | src/battle/struct/btl_conditions.erl | 146 | ||||
| -rw-r--r-- | src/battle/struct/btl_status_indicators.erl | 859 | ||||
| -rw-r--r-- | src/battle/struct/btl_turn_result.erl | 34 | 
6 files changed, 1109 insertions, 233 deletions
| diff --git a/src/battle/mechanic/condition/btl_cond_heal.erl b/src/battle/mechanic/condition/btl_cond_heal.erl index 04806ba..ba9840d 100644 --- a/src/battle/mechanic/condition/btl_cond_heal.erl +++ b/src/battle/mechanic/condition/btl_cond_heal.erl @@ -11,8 +11,7 @@  -export  (     [ -%      encode/1, -%      get_turn_result_encoding/1, +      encode_turn_result/1,        apply/3     ]  ). @@ -43,14 +42,14 @@ heal_character (ActorIX, S0Actor, S0HealingAmount) ->           CurrentHealth = btl_character:get_current_health(S0Actor),           BaseActor = btl_character:get_base_character(S0Actor),           ActorAttributes = shr_character:get_attributes(BaseActor), -         MaxHealth = shr_attributes:get_maximum_health(ActorAttributes), +         MaxHealth = shr_attributes:get_health(ActorAttributes),           MaxHealing = (MaxHealth - CurrentHealth),           S1HealingAmount = min(MaxHealing, S0HealingAmount),           {S1Actor, ActorAtaxicUpdate} =              btl_character:ataxia_set_current_health              ( -               S0Actor, -               (CurrentHealth + S1HealingAmount) +               (CurrentHealth + S1HealingAmount), +               S0Actor              ),           { @@ -89,7 +88,7 @@ perform_on_target (TargetIX, Power, S0Update) ->        }           ->              {S2Battle, BattleAtaxicUpdate} = -               btl_battle:ataxic_set_character +               btl_battle:ataxia_set_character                 (                    TargetIX,                    S1Target, @@ -98,7 +97,7 @@ perform_on_target (TargetIX, Power, S0Update) ->                 ),              S1Update = -               btl_character_turn_update:ataxic_set_battle +               btl_character_turn_update:ataxia_set_battle                 (                    S2Battle,                    BattleAtaxicUpdate, @@ -123,7 +122,7 @@ perform_on_location (Location, Power, Update) ->     Characters = btl_battle:get_characters(Battle),     MaybeResultIX = -      orddict:foldl +      orddict:fold        (           fun (IX, Char, CurrentResult) ->              case CurrentResult of @@ -155,7 +154,7 @@ perform_on_location (Location, Power, Update) ->  standard_perform (Condition, S0Update) ->     Parameters = btl_conditions:get_parameters(Condition),     Power = -      case btl_condition_parameters:get_other(Condition) of +      case btl_condition_parameters:get_other(Parameters) of           N when (is_integer(N) and (N >= 0)) -> N;           Other ->              error({param, other, Other}), 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, @@ -59,6 +64,38 @@  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%%%%%% +%%%% 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 %%%%  %%%%%%%%%%%%%%%%%  -spec get_targets (type(_)) -> list(non_neg_integer()). 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])). | 


