summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/battle')
-rw-r--r--src/battle/mechanic/action/btl_action_skill.erl111
-rw-r--r--src/battle/struct/btl_character.erl38
2 files changed, 148 insertions, 1 deletions
diff --git a/src/battle/mechanic/action/btl_action_skill.erl b/src/battle/mechanic/action/btl_action_skill.erl
index 548eafe..7e6579b 100644
--- a/src/battle/mechanic/action/btl_action_skill.erl
+++ b/src/battle/mechanic/action/btl_action_skill.erl
@@ -17,6 +17,88 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec pay_for_cast
+ (
+ non_neg_integer(),
+ btl_character_turn_update:type()
+ )
+ -> btl_character_turn_update:type().
+pay_for_cast (ActorIX, S0Update) ->
+ S0Battle = btl_character_turn_update:get_battle(S0Update),
+ S0Actor = btl_battle:get_character(ActorIX, S0Battle),
+ BaseActor = btl_character:get_base_character(S0Actor),
+ Equipment = shr_character:get_equipment(BaseActor),
+ Skill = shr_equipment:get_skill(Equipment),
+
+ SkillCost = shr_skill:get_cost(Skill),
+ S0SkillPoints = btl_character:get_skill_points(S0Actor),
+ S1SkillPoints = (S0SkillPoints - SkillCost),
+
+ {S1Actor, ActorAtaxiaUpdate} =
+ case (S1SkillPoints < 0) of
+ true -> error({skill, points, S0SkillPoints, Skill});
+ false ->
+ btl_character:ataxia_set_skill_points(S1SkillPoints, S0Actor)
+ end,
+
+ {S1Battle, BattleAtaxiaUpdate} =
+ btl_battle:ataxia_set_character
+ (
+ ActorIX,
+ S1Actor,
+ ActorAtaxiaUpdate,
+ S0Battle
+ ),
+
+ S1Update =
+ btl_character_turn:ataxia_set_battle
+ (
+ S1Battle,
+ BattleAtaxiaUpdate,
+ S0Update
+ ),
+
+ {S1Update, Skill}.
+
+-spec cast_skill
+ (
+ btl_action:type(),
+ btl_character_turn_update:type()
+ )
+ -> btl_character_turn_update:type().
+cast_skill (Action, S0Update) ->
+ ActorIX = btl_action:get_actor_index(Action),
+ {S1Update, Skill} = pay_for_cast(ActorIX, S0Update),
+
+ S2Update =
+ erlang:apply
+ (
+ shr_skill:get_module(Skill),
+ cast,
+ [Skill, Action, S1Update]
+ ),
+
+ {none, S3Update} =
+ btl_condition:apply_to_character
+ (
+ ActorIX,
+ ?CONDITION_TRIGGER_HAS_CAST_SKILL,
+ Action,
+ none,
+ S2Update
+ ),
+
+ {none, S3Update} =
+ btl_condition:apply_to_battle
+ (
+ ?CONDITION_TRIGGER_A_CHARACTER_HAS_CAST_SKILL,
+ Action,
+ none,
+ S2Update
+ ),
+
+ S3Update.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -27,4 +109,31 @@
btl_character_turn_update:type()
)
-> btl_character_turn_update:type().
-handle (_Action, S0Update) -> S0Update. % TODO
+handle (S0Action, S0Update) ->
+ ActorIX = btl_action:get_actor_index(S0Action),
+
+ S0PerformAction = true,
+
+ {{S1Action, S1PerformAction}, S1Update} =
+ btl_condition:apply_to_character
+ (
+ ActorIX,
+ ?CONDITION_TRIGGER_ABOUT_TO_CAST_SKILL,
+ none,
+ {S0Action, S0PerformAction},
+ S0Update
+ ),
+
+ {{S2Action, S2PerformAction}, S2Update} =
+ btl_condition:apply_to_battle
+ (
+ ?CONDITION_TRIGGER_A_CHARACTER_IS_ABOUT_TO_CAST_SKILL,
+ none,
+ {S1Action, S1PerformAction},
+ S1Update
+ ),
+
+ case S2PerformAction of
+ true -> cast_skill(S2Action, S2Update);
+ false -> S2Update
+ end.
diff --git a/src/battle/struct/btl_character.erl b/src/battle/struct/btl_character.erl
index 6a4fe2f..422ee7d 100644
--- a/src/battle/struct/btl_character.erl
+++ b/src/battle/struct/btl_character.erl
@@ -4,6 +4,7 @@
-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">>).
@@ -22,6 +23,7 @@
rank :: rank(),
location :: {non_neg_integer(), non_neg_integer()},
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(),
@@ -37,6 +39,7 @@
rank :: rank(),
location :: {non_neg_integer(), non_neg_integer()},
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(),
@@ -60,6 +63,7 @@
get_rank/1,
get_location/1,
get_current_health/1,
+ get_skill_points/1,
get_is_alive/1,
get_is_active/1,
get_is_defeated/1,
@@ -69,6 +73,7 @@
set_rank/2,
set_location/3,
set_current_health/2,
+ set_skill_points/2,
set_is_active/2,
set_is_defeated/2,
set_base_character/2,
@@ -77,6 +82,7 @@
ataxia_set_rank/2,
ataxia_set_location/3,
ataxia_set_current_health/2,
+ ataxia_set_skill_points/2,
ataxia_set_is_active/2,
ataxia_set_is_defeated/2,
ataxia_set_base_character/2,
@@ -87,6 +93,7 @@
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,
@@ -157,6 +164,10 @@ get_location (#btl_char_ref{ location = R }) -> R.
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));
@@ -306,6 +317,27 @@ ataxia_set_current_health (Health, Char) ->
)
}.
+-spec set_skill_points
+ (integer(), type()) -> type();
+ (integer(), unresolved()) -> unresolved().
+set_skill_points (SkillPoints, Char) when is_record(Char, btl_char) ->
+ Char#btl_char{ skill_points = SkillPoints };
+set_skill_points (SkillPoints, Char) when is_record(Char, btl_char_ref) ->
+ Char#btl_char_ref{ skill_points = SkillPoints }.
+
+-spec ataxia_set_skill_points
+ (integer(), type()) -> {type(), ataxic:basic()};
+ (integer(), unresolved()) -> {unresolved(), ataxic:basic()}.
+ataxia_set_skill_points (SkillPoints, Char) ->
+ {
+ set_skill_points(SkillPoints, Char),
+ ataxic:update_field
+ (
+ get_skill_points_field(),
+ ataxic:constant(SkillPoints)
+ )
+ }.
+
-spec set_is_active
(boolean(), type()) -> type();
(boolean(), unresolved()) -> unresolved().
@@ -508,6 +540,7 @@ new
rank = Rank,
location = Location,
current_health = shr_attributes:get_health(Attributes),
+ skill_points = 0,
is_active = (PlayerIX == 0),
is_defeated = false,
base = Base,
@@ -522,6 +555,7 @@ resolve (LocalOmnimods, CharRef) when is_record(CharRef, btl_char_ref) ->
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),
@@ -537,6 +571,7 @@ to_unresolved (Char) when is_record(Char, btl_char) ->
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),
@@ -553,6 +588,8 @@ get_rank_field () -> #btl_char_ref.rank.
get_location_field () -> #btl_char_ref.location.
-spec get_current_health_field() -> non_neg_integer().
get_current_health_field () -> #btl_char_ref.current_health.
+-spec get_skill_points_field() -> non_neg_integer().
+get_skill_points_field () -> #btl_char_ref.skill_points.
-spec get_is_active_field() -> non_neg_integer().
get_is_active_field () -> #btl_char_ref.is_active.
-spec get_is_defeated_field() -> non_neg_integer().
@@ -570,6 +607,7 @@ encode (CharRef) ->
{?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},
{?IS_ACTIVE_FIELD, CharRef#btl_char_ref.is_active},
{?IS_DEFEATED_FIELD, CharRef#btl_char_ref.is_defeated},
{?BASE_CHAR_FIELD, shr_character:encode(CharRef#btl_char_ref.base)},