1-- Set the namespace
2local ns = {};
3setmetatable(ns, {__index = _G});
4wolf_fangs_party_attack = ns;
5setfenv(1, ns);
6
7-- local references
8local attacker = nil
9local target = nil
10local skill = nil
11
12local attacker_pos_x = 0.0;
13local attacker_pos_y = 0.0;
14
15local distance_moved = 0.0;
16local start_x_position = 0.0;
17local start_y_position = 0.0;
18local jump_end_x_position = 0.0;
19local diff_x = 0.0;
20local diff_y = 0.0;
21
22local targets = {}
23
24local attack_step = 0;
25
26local damage_triggered = false;
27
28local Battle = nil
29local claw_slash = nil
30local slash_effect_time = 0
31local slash_effect_started = false
32
33-- attacker, the BattleActor attacking
34-- target, the BattleActor target
35-- The skill id used on target
36function Initialize(_attacker, _target, _skill)
37    -- Keep the reference in memory
38    attacker = _attacker;
39    target = _target;
40    skill = _skill;
41
42    -- Don't attack if the attacker isn't alive
43    if (attacker:IsAlive() == false) then
44        return;
45    end
46
47    -- Get the current attackers' positions
48    attacker_pos_x = attacker:GetXLocation();
49    attacker_pos_y = attacker:GetYLocation();
50
51    attack_step = 0;
52
53    damage_triggered = false;
54
55    distance_moved = SystemManager:GetUpdateTime() / vt_map.MapMode.NORMAL_SPEED * 100.0;
56    start_x_position = attacker_pos_x;
57    jump_end_x_position = attacker_pos_x - 140
58    start_y_position = attacker_pos_y;
59    diff_x = attacker_pos_x - 70;
60    diff_y = attacker_pos_y - 50;
61
62
63    Battle = ModeManager:GetTop();
64    slash_effect_time = 0;
65    slash_effect_started = false;
66
67    -- Register all the valid actors position in the table
68    local index = 0;
69    while (target:GetPartyActor(index) ~= nil) do
70        local actor = target:GetPartyActor(index)
71        if (actor:CanFight() == true) then
72          targets[index] = {};
73          targets[index].actor = actor
74          targets[index].slash_anim = Battle:CreateBattleAnimation("data/entities/battle/effects/fangs_crush.lua");
75        end
76
77        index = index + 1
78    end
79end
80
81
82function Update()
83    -- The update time can vary, so update the distance on each update as well.
84    distance_moved = SystemManager:GetUpdateTime() / vt_map.MapMode.NORMAL_SPEED * 100.0;
85
86    -- Start to jump slightly
87    if (attack_step == 0) then
88        attacker:ChangeSpriteAnimation("idle")
89        Battle:TriggerBattleParticleEffect("data/visuals/particle_effects/dust.lua", attacker_pos_x, attacker_pos_y)
90        AudioManager:PlaySound("data/sounds/growl1_IFartInUrGeneralDirection_freesound.wav")
91
92        attack_step = 1
93    end
94    -- Make the attacker jump
95    if (attack_step == 1) then
96
97        if (attacker_pos_x > diff_x) then
98            attacker_pos_x = attacker_pos_x - distance_moved;
99            if attacker_pos_x < diff_x then attacker_pos_x = diff_x end
100        end
101        if (attacker_pos_x < diff_x) then
102            attacker_pos_x = attacker_pos_x + distance_moved;
103            if attacker_pos_x > diff_x then attacker_pos_x = diff_x end
104        end
105
106        if (attacker_pos_y > diff_y) then
107            attacker_pos_y = attacker_pos_y - distance_moved;
108            if attacker_pos_y < diff_y then attacker_pos_y = diff_y end
109        end
110        if (attacker_pos_y < diff_y) then
111            attacker_pos_y = attacker_pos_y + distance_moved;
112            if attacker_pos_y > diff_y then attacker_pos_y = diff_y end
113        end
114
115        attacker:SetXLocation(attacker_pos_x);
116        attacker:SetYLocation(attacker_pos_y);
117
118        -- half-jump done
119        if (attacker_pos_x == diff_x and attacker_pos_y == diff_y) then
120            attack_step = 2;
121        end
122    end
123
124    -- Second half-jump
125    if (attack_step == 2) then
126        if (attacker_pos_x > jump_end_x_position) then
127            attacker_pos_x = attacker_pos_x - distance_moved;
128            if attacker_pos_x < jump_end_x_position then attacker_pos_x = jump_end_x_position end
129        end
130        if (attacker_pos_x < jump_end_x_position) then
131            attacker_pos_x = attacker_pos_x + distance_moved;
132            if attacker_pos_x > jump_end_x_position then attacker_pos_x = jump_end_x_position end
133        end
134
135        if (attacker_pos_y > start_y_position) then
136            attacker_pos_y = attacker_pos_y - distance_moved;
137            if attacker_pos_y < start_y_position then attacker_pos_y = start_y_position end
138        end
139        if (attacker_pos_y < start_y_position) then
140            attacker_pos_y = attacker_pos_y + distance_moved;
141            if attacker_pos_y > start_y_position then attacker_pos_y = start_y_position end
142        end
143
144        attacker:SetXLocation(attacker_pos_x);
145        attacker:SetYLocation(attacker_pos_y);
146
147        -- half-jump done
148        if (attacker_pos_y == start_y_position) then
149            Battle:TriggerBattleParticleEffect("data/visuals/particle_effects/dust.lua", attacker_pos_x, attacker_pos_y);
150
151            -- Init the slash effect life time
152            slash_effect_time = 0;
153            slash_effect_started = false;
154
155            attack_step = 3;
156        end
157    end
158
159    -- Wait for it to finish
160    if (attack_step == 3) then
161        slash_effect_time = slash_effect_time + SystemManager:GetUpdateTime()
162        if (slash_effect_started == false) then
163            slash_effect_started = true
164
165            for index, target_info in pairs(targets) do
166              target_info.slash_anim:SetXLocation(target_info.actor:GetXLocation())
167              target_info.slash_anim:SetYLocation(target_info.actor:GetYLocation() + 0.1) -- To see the effect
168              target_info.slash_anim:SetVisible(true)
169              target_info.slash_anim:Reset()
170            end
171
172            -- Triggers the damage in the middle of the attack animation
173            skill:ExecuteBattleFunction(attacker, target)
174            -- Remove the skill points at the end of the attack
175            attacker:SubtractSkillPoints(skill:GetSPRequired())
176            attack_step = 4
177        end
178    end
179
180    -- Return to start pos
181    if (attack_step == 4) then
182        slash_effect_time = slash_effect_time + SystemManager:GetUpdateTime();
183
184        if (attacker_pos_x > start_x_position) then
185            attacker_pos_x = attacker_pos_x - distance_moved;
186            if attacker_pos_x < start_x_position then attacker_pos_x = start_x_position end
187        end
188        if (attacker_pos_x < start_x_position) then
189            attacker_pos_x = attacker_pos_x + distance_moved;
190            if attacker_pos_x > start_x_position then attacker_pos_x = start_x_position end
191        end
192
193        if (attacker_pos_y > start_y_position) then
194            attacker_pos_y = attacker_pos_y - distance_moved;
195            if attacker_pos_y < start_y_position then attacker_pos_y = start_y_position end
196        end
197        if (attacker_pos_y < start_y_position) then
198            attacker_pos_y = attacker_pos_y + distance_moved;
199            if attacker_pos_y > start_y_position then attacker_pos_y = start_y_position end
200        end
201
202        attacker:SetXLocation(attacker_pos_x);
203        attacker:SetYLocation(attacker_pos_y);
204
205        -- Stops once all the animations are done
206        if (slash_effect_time > 75 * 4) then -- 300, 410 + 300 = 710 (< 730).
207
208          local all_anim_are_done = true
209          for index, target_info in pairs(targets) do
210            if (target_info.slash_anim ~= nil) then
211              target_info.slash_anim:SetVisible(false)
212              target_info.slash_anim:Remove()
213              -- The Remove() call will make the engine delete the object, so we set it to nil
214              -- to avoid using it again.
215              target_info.slash_anim = nil
216
217              all_anim_are_done = false
218            end
219          end
220
221          if (all_anim_are_done == false) then
222            return true;
223          end
224        end
225    end
226
227    return false;
228end
229