1 ////////////////////////////////////////////////////////////////////////////////
2 //            Copyright (C) 2004-2011 by The Allacrost Project
3 //            Copyright (C) 2012-2018 by Bertram (Valyria Tear)
4 //                         All Rights Reserved
5 //
6 // This code is licensed under the GNU GPL version 2. It is free software
7 // and you may modify it and/or redistribute it under the terms of this license.
8 // See http://www.gnu.org/copyleft/gpl.html for details.
9 ////////////////////////////////////////////////////////////////////////////////
10 
11 #ifndef __GLOBAL_ATTACK_POINT_HEADER__
12 #define __GLOBAL_ATTACK_POINT_HEADER__
13 
14 #include "common/global/status_effects/status_effect_enums.h"
15 
16 #include "engine/video/image.h"
17 
18 #include "utils/ustring.h"
19 
20 #include <memory>
21 
22 namespace vt_script
23 {
24 class ReadScriptDescriptor;
25 }
26 
27 namespace vt_global
28 {
29 
30 class GlobalArmor;
31 class GlobalActor;
32 
33 /** \name Character Attack Point Positions
34 *** \brief They represent the index location of the attack points and armor types for characters
35 **/
36 enum GLOBAL_POSITION {
37     GLOBAL_POSITION_HEAD     = 0,
38     GLOBAL_POSITION_TORSO    = 1,
39     GLOBAL_POSITION_ARMS     = 2,
40     GLOBAL_POSITION_LEGS     = 3,
41     GLOBAL_POSITION_INVALID  = 4
42 };
43 
44 /** ****************************************************************************
45 *** \brief Represents the points of attack present on an actor
46 ***
47 *** An attack point is a location where an actor may be attacked. It is <b>not</b> a numerical
48 *** quantity. Actors typically have multiple attack points, each with their own resistances and
49 *** weaknesses. For example, the number of attack points on all characters is four and they
50 *** are located on the head, torso, arms, and legs. Each attack points may have certain weaknesses
51 *** or resistances.
52 *** ***************************************************************************/
53 class GlobalAttackPoint
54 {
55 public:
56     //! \param actor_owner A pointer to the GlobalActor owner of this attack point
57     explicit GlobalAttackPoint(GlobalActor* owner);
~GlobalAttackPoint()58     ~GlobalAttackPoint() {
59         _actor_owner = nullptr;
60     }
61 
62     /** \brief Reads in the attack point's data from a script file
63     *** \param script A reference to the open script file where to retrieve the data from
64     *** \return True upon success, false upon failure.
65     ***
66     *** There are two requirements for using this function. First, the script file must already
67     *** be opened for reading permissions. Second, the table which contains the attack point data
68     *** must be opened <b>prior</b> to making this function call. This function will not close the
69     *** table containing the attack point when it finishes loading the data, so the calling routine
70     *** must remember to close the table after this call is made.
71     **/
72     bool LoadData(vt_script::ReadScriptDescriptor& script);
73 
74     /** \brief Determines the total physical and magical defense of the attack point
75     *** \param equipped_armor A pointer to the armor equipped on the attack point, or nullptr if no armor is equipped
76     ***
77     *** This method uses the owning GlobalActor's base defense stats, the attack point's defense modifiers stats,
78     *** and the properties of the equipped armor to calculate the attack point's total physical and magical defense.
79     *** This method should be called whenever the actor's base defense stats or equipped armor on this point changes.
80     **/
81     void CalculateTotalDefense(const std::shared_ptr<GlobalArmor>& equipped_armor);
82 
83     /** \brief Determines the total evade rating of the attack point
84     ***
85     *** This method uses the owning GlobalActor's base evade rating and the attack point's evade modifiers stats to
86     *** calculate the attack point's total evade rating. This method should be called whenever the actor's base defense
87     *** rating changes.
88     **/
89     void CalculateTotalEvade();
90 
91     //! \name Class Member Access Functions
92     //@{
GetName()93     vt_utils::ustring& GetName() {
94         return _name;
95     }
96 
GetActorOwner()97     GlobalActor* GetActorOwner() const {
98         return _actor_owner;
99     }
100 
GetXPosition()101     int16_t GetXPosition() const {
102         return _x_position;
103     }
104 
GetYPosition()105     int16_t GetYPosition() const {
106         return _y_position;
107     }
108 
GetPhysDefModifier()109     float GetPhysDefModifier() const {
110         return _phys_def_modifier;
111     }
112 
GetMagDefModifier()113     float GetMagDefModifier() const {
114         return _mag_def_modifier;
115     }
116 
GetEvadeModifier()117     float GetEvadeModifier() const {
118         return _evade_modifier;
119     }
120 
GetTotalPhysicalDefense()121     uint16_t GetTotalPhysicalDefense() const {
122         return _total_physical_defense;
123     }
124 
GetTotalMagicalDefense(GLOBAL_ELEMENTAL element)125     uint16_t GetTotalMagicalDefense(GLOBAL_ELEMENTAL element) const {
126         if (element <= GLOBAL_ELEMENTAL_INVALID || element >= GLOBAL_ELEMENTAL_TOTAL)
127             element = GLOBAL_ELEMENTAL_NEUTRAL;
128 
129         return _total_magical_defense[element];
130     }
131 
GetTotalEvadeRating()132     float GetTotalEvadeRating() const {
133         return _total_evade_rating;
134     }
135 
GetStatusEffects()136     const std::vector<std::pair<GLOBAL_STATUS, float> >& GetStatusEffects() const {
137         return _status_effects;
138     }
139 
140     //! \note Use this method with extreme caution. It does not update defense/evade totals or any other members
SetActorOwner(GlobalActor * new_owner)141     void SetActorOwner(GlobalActor* new_owner) {
142         _actor_owner = new_owner;
143     }
144     //@}
145 
146 private:
147     /** \brief The name of the attack point as is displayed on the screen
148     *** Usually, this is simply the name of a body part such as "head" or "tail". More elaborate names
149     *** may be chosen for special foes and bosses, however.
150     **/
151     vt_utils::ustring _name;
152 
153     //! \brief A pointer to the actor which "owns" this attack point (i.e., the attack point is a location on the actor)
154     GlobalActor* _actor_owner;
155 
156     /** \brief The position of the physical attack point relative to the actor's battle sprite
157     *** These members treat the bottom center of the sprite as the origin (0, 0) and increase in the
158     *** right and upwards directions. The combination of these two members point to the center pinpoint
159     *** location of the attack point. The units of these two members are in number of pixels. The _y_position
160     *** member should always be positive, by _x_position may be either positive or negative.
161     **/
162     int16_t _x_position;
163     int16_t _y_position;
164 
165     /** \brief The defense and evasion percentage modifiers for this attack point
166     ***
167     *** These are called "modifiers" because they modify the value of phys_def, mag_def, and evade ratings of the
168     *** actor. They represent percentage change from the base stat. So for example, a phys_def modifer that is 0.25f
169     *** increases the phys_def of the attack point by 25%. If the base mag_def rating was 10 and the mag_def
170     *** modifier was -0.30f, the resulting mag_def for the attack point would be: 10 + (10 * -0.30f) = 7.
171     ***
172     *** The lower bound for each modifier is -1.0f (-100%), which will result in a value of zero for that stat. No
173     *** actor stats can be negative so even if the modifier drops below -1.0f, the resulting value will still be zero.
174     *** There is no theoretical upper bound, but it is usually advised to keep it under 1.0f (100%).
175     **/
176     //@{
177     float _phys_def_modifier;
178     float _mag_def_modifier;
179     float _evade_modifier;
180     //@}
181 
182     /** \brief The cumulative defense and evade stats for this attack point
183     *** These totals include the actor's base stat, the percentage modifier for the attack point, and the stats of any
184     *** armor that is equipped on the attack point.
185     **/
186     //@{
187     uint32_t _total_physical_defense;
188     //! \brief The magical defense is computed against each elements.
189     uint32_t _total_magical_defense[GLOBAL_ELEMENTAL_TOTAL];
190     float _total_evade_rating;
191     //@}
192 
193     /** \brief A vector containing all status effects that may be triggered by attacking the point
194     *** This vector contains only the status effects that have a non-zero chance of affecting their target. Therefore,
195     *** it is very possible that this vector may be empty, and usually it will contain only a single entry. The first
196     *** element of the pair is an identifier for the type of status. The second element is a floating point value from
197     *** 0.0 to 100.0, representing a 0-100% probability range for this effect to be triggered upon being hit.
198     **/
199     std::vector<std::pair<GLOBAL_STATUS, float> > _status_effects;
200 }; // class GlobalAttackPoint
201 
202 } // namespace vt_global
203 
204 #endif // __GLOBAL_ATTACK_POINT_HEADER__
205