1-- This file is scripting Bronann's attack animation, called by attack skills.
2-- The initialize() function is called once, followed by calls to the update function.
3-- When the update function returns true, the attack is finished.
4
5-- Set the namespace
6local ns = {};
7setmetatable(ns, {__index = _G});
8bronann_attack_forward_thrust = ns;
9setfenv(1, ns);
10
11-- local references
12local character = nil
13local target = nil
14local target_actor = nil
15local skill = nil
16
17local character_pos_x = 0.0;
18local character_pos_y = 0.0;
19
20local a_coeff = 0.0;
21local distance_moved_x = 0.0;
22local distance_moved_y = 0.0;
23
24local enemy_pos_x = 0.0;
25local enemy_pos_y = 0.0;
26
27local attack_step = 0;
28local attack_time = 0.0;
29
30local damage_triggered = false;
31
32local Battle = nil
33local sword_slash = nil
34local slash_effect_time = 0
35local slash_effect_started = false
36
37-- Used to trigger dust
38local move_time = 0
39-- Used to set up the Forward thrust counter force
40local forward_thrust_counter_force = 0.0;
41
42-- character, the BattleActor attacking (here Bronann)
43-- target, the BattleEnemy target
44-- The skill id used on target
45function Initialize(_character, _target, _skill)
46    -- Keep the reference in memory
47    character = _character;
48    target = _target;
49    target_actor = _target:GetActor();
50    skill = _skill;
51
52    -- Don't attack if the character isn't alive
53    if (character:IsAlive() == false) then
54        return;
55    end
56
57    -- Get the current characters' positions
58    character_pos_x = character:GetXLocation();
59    character_pos_y = character:GetYLocation();
60
61    enemy_pos_x = target_actor:GetXLocation() - (character:GetSpriteWidth() / 2.0);
62    enemy_pos_y = target_actor:GetYLocation() - 5.0; -- Makes Bronann placed behind the enemy.
63
64    attack_step = 0;
65    attack_time = 0;
66
67    damage_triggered = false;
68
69    distance_moved_x = SystemManager:GetUpdateTime() / vt_map.MapMode.NORMAL_SPEED * 170.0;
70    local x_diff = enemy_pos_x - character_pos_x;
71    local y_diff = character_pos_y - enemy_pos_y;
72    if (y_diff == 0.0) then
73        a_coeff = 0.0;
74        distance_moved_y = 0.0;
75    elseif (x_diff == 0.0) then
76        a_coeff = 0.0;
77        distance_moved_y = distance_moved_x;
78        distance_moved_x = 0.0;
79    else
80        a_coeff = y_diff / x_diff;
81        if (a_coeff < 0) then a_coeff = -a_coeff; end
82        distance_moved_y = a_coeff * distance_moved_x;
83    end
84
85    --print("distance x: ", enemy_pos_x - character_pos_x)
86    --print("distance y: ", character_pos_y - enemy_pos_y)
87    --print (distance_moved_x, a_coeff, distance_moved_y);
88
89    Battle = ModeManager:GetTop();
90    -- A sword slash animation
91    sword_slash = Battle:CreateBattleAnimation("data/entities/battle/effects/sword_forward_slash.lua");
92    slash_effect_time = 0;
93    slash_effect_started = false;
94    move_time = 0;
95    forward_thrust_counter_force = 0;
96end
97
98
99function Update()
100    -- The update time can vary, so update the distance on each update as well.
101    distance_moved_x = SystemManager:GetUpdateTime() / vt_map.MapMode.NORMAL_SPEED * 170.0;
102    if (a_coeff ~= 0.0) then
103        distance_moved_y = a_coeff * distance_moved_x;
104    end
105
106    -- Make the speed the same whatever the angle between the character and the enemy is.
107    -- We deal only with a coefficients > 1.0 for simplification purpose.
108    if (a_coeff > 1.0 and distance_moved_x ~= 0.0 and distance_moved_y ~= 0.0) then
109        distance_moved_x = distance_moved_x * (distance_moved_x / distance_moved_y);
110        if (a_coeff ~= 0.0) then
111            distance_moved_y = a_coeff * distance_moved_x;
112        end
113        --print ("new_ratio: ", a_coeff, distance_moved_x / distance_moved_y)
114    end
115
116    -- Start to run towards the enemy
117    if (attack_step == 0) then
118        character:ChangeSpriteAnimation("jump_forward")
119        AudioManager:PlaySound("data/sounds/footstep_grass1.wav")
120        Battle:TriggerBattleParticleEffect("data/visuals/particle_effects/dust.lua", character_pos_x, character_pos_y);
121
122        attack_step = 1
123    end
124    -- Make the player move till it reaches the enemy
125    if (attack_step == 1) then
126        if (character_pos_x > enemy_pos_x) then
127            character_pos_x = character_pos_x - distance_moved_x;
128            if character_pos_x < enemy_pos_x then character_pos_x = enemy_pos_x end
129        end
130        if (character_pos_x < enemy_pos_x) then
131            character_pos_x = character_pos_x + distance_moved_x;
132            if character_pos_x > enemy_pos_x then character_pos_x = enemy_pos_x end
133        end
134        if (character_pos_y > enemy_pos_y) then
135            character_pos_y = character_pos_y - distance_moved_y;
136            if character_pos_y < enemy_pos_y then character_pos_y = enemy_pos_y end
137        end
138        if (character_pos_y < enemy_pos_y) then
139            character_pos_y = character_pos_y + distance_moved_y;
140            if character_pos_y > enemy_pos_y then character_pos_y = enemy_pos_y end
141        end
142
143        character:SetXLocation(character_pos_x);
144        character:SetYLocation(character_pos_y);
145
146        -- Attack when reaching the enemy
147        if (character_pos_x >= enemy_pos_x and character_pos_y == enemy_pos_y) then
148            attack_step = 2;
149        end
150    end
151
152    -- triggers the attack animation
153    if (attack_step == 2) then
154        AudioManager:PlaySound("data/sounds/footstep_grass2.wav")
155        Battle:TriggerBattleParticleEffect("data/visuals/particle_effects/dust.lua", character_pos_x, character_pos_y);
156        character:ChangeSpriteAnimation("attack_forward_thrust")
157
158        -- Trigger damage a first time
159        skill:ExecuteBattleFunction(character, target)
160        AudioManager:PlaySound("data/sounds/swordslice1.wav")
161
162        -- Init the slash effect life time
163        slash_effect_time = 0;
164        slash_effect_started = false;
165
166        move_time = 0;
167
168        attack_step = 3;
169    end
170
171    -- Wait for it to finish
172    if (attack_step == 3) then
173        attack_time = attack_time + SystemManager:GetUpdateTime();
174
175        if (attack_time > 410) then
176            slash_effect_time = slash_effect_time + SystemManager:GetUpdateTime();
177            if (slash_effect_started == false) then
178                slash_effect_started = true
179
180                sword_slash:SetXLocation(target_actor:GetXLocation());
181                sword_slash:SetYLocation(target_actor:GetYLocation() + 2.0);
182                sword_slash:SetVisible(true);
183                sword_slash:Reset();
184            end
185        end
186
187        if (sword_slash ~= nil and slash_effect_time > 75 * 4) then -- 300, 410 + 300 = 710 (< 730).
188            sword_slash:SetVisible(false);
189            sword_slash:Remove();
190            -- The Remove() call will make the engine delete the object, so we set it to nil
191            -- to avoid using it again.
192            sword_slash = nil;
193        end
194
195        -- Triggers the damage a second time in the middle of the attack animation
196        if (damage_triggered == false and attack_time > 505.0) then
197            skill:ExecuteBattleFunction(character, target)
198            AudioManager:PlaySound("data/sounds/swordslice1.wav")
199            -- Remove the skill points at the end of attack
200            character:SubtractSkillPoints(skill:GetSPRequired())
201            damage_triggered = true;
202        end
203
204        -- Makes the character go through the enemy for the second blow.
205        if (attack_time > 390) then
206            character_pos_x = character_pos_x + distance_moved_x - forward_thrust_counter_force;
207            character:SetXLocation(character_pos_x);
208            forward_thrust_counter_force = forward_thrust_counter_force + (2.0 * SystemManager:GetUpdateTime() / 30.0);
209
210            -- Adds some dust every 15ms
211            move_time = move_time + SystemManager:GetUpdateTime();
212            if (move_time > 15) then
213                Battle:TriggerBattleParticleEffect("data/visuals/particle_effects/dust.lua", character_pos_x, character_pos_y);
214                move_time = 0
215            end
216        end
217
218        if (attack_time > 730.0) then
219            character:ChangeSpriteAnimation("jump_backward")
220            Battle:TriggerBattleParticleEffect("data/visuals/particle_effects/dust.lua", character_pos_x, character_pos_y);
221            AudioManager:PlaySound("data/sounds/footstep_grass1.wav")
222
223            -- Recompute the a coefficient using the character origin position as the angle has changed.
224            distance_moved_x = SystemManager:GetUpdateTime() / vt_map.MapMode.NORMAL_SPEED * 170.0;
225            local x_diff = character:GetXLocation() - character:GetXOrigin();
226            local y_diff = character:GetYOrigin() - character:GetYLocation();
227            if (y_diff == 0.0) then
228                a_coeff = 0.0;
229                distance_moved_y = 0.0;
230            elseif (x_diff == 0.0) then
231                a_coeff = 0.0;
232                distance_moved_y = distance_moved_x;
233                distance_moved_x = 0.0;
234            else
235                a_coeff = y_diff / x_diff;
236                if (a_coeff < 0) then a_coeff = -a_coeff; end
237                distance_moved_y = a_coeff * distance_moved_x;
238            end
239
240            attack_step = 4;
241        end
242    end
243
244    -- triggers skill
245    if (attack_step == 4) then
246        -- Make the character jump back to its place
247        if (character_pos_x > character:GetXOrigin()) then
248            character_pos_x = character_pos_x - distance_moved_x;
249            if character_pos_x < character:GetXOrigin() then character_pos_x = character:GetXOrigin() end
250        end
251        if (character_pos_x < character:GetXOrigin()) then
252            character_pos_x = character_pos_x + distance_moved_x;
253            if character_pos_x > character:GetXOrigin() then character_pos_x = character:GetXOrigin() end
254        end
255        if (character_pos_y > character:GetYOrigin()) then
256            character_pos_y = character_pos_y - distance_moved_y;
257            if character_pos_y < character:GetYOrigin() then character_pos_y = character:GetYOrigin() end
258        end
259        if (character_pos_y < character:GetYOrigin()) then
260            character_pos_y = character_pos_y + distance_moved_y;
261            if character_pos_y > character:GetYOrigin() then character_pos_y = character:GetYOrigin() end
262        end
263
264        character:SetXLocation(character_pos_x);
265        character:SetYLocation(character_pos_y);
266
267        -- Attack when reaching the enemy
268        if (character_pos_x == character:GetXOrigin() and character_pos_y == character:GetYOrigin()) then
269            attack_step = 5;
270        end
271    end
272
273    if (attack_step == 5) then
274        character:ChangeSpriteAnimation("idle")
275        Battle:TriggerBattleParticleEffect("data/visuals/particle_effects/dust.lua", character_pos_x, character_pos_y)
276        AudioManager:PlaySound("data/sounds/footstep_grass2.wav")
277        return true;
278    end
279    return false;
280end
281