summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2019-11-18 10:40:03 +0100
committerNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2019-11-18 10:40:03 +0100
commit3fb30b108828e3ad6bf811c0f3372a79ec6e9595 (patch)
treeef12976907cea83f7ef70168173d487b3cdc018e /src
parentcc4e39960d3c56fceb2e31c01bf286dccc73615c (diff)
...
Diffstat (limited to 'src')
-rw-r--r--src/battle/mechanic/condition/btl_cond_heal.erl17
-rw-r--r--src/battle/struct/btl_character.erl249
-rw-r--r--src/battle/struct/btl_condition_parameters.erl37
-rw-r--r--src/battle/struct/btl_conditions.erl146
-rw-r--r--src/battle/struct/btl_status_indicators.erl859
-rw-r--r--src/battle/struct/btl_turn_result.erl34
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])).