# HG changeset patch # User unc0rr # Date 1372329423 -14400 # Node ID 76e68c136a110223e59f85f5f5b72000c42539c3 # Parent c3b11f91314578b5858b9ac2d63ed0e20c927889 Refactoring: VGSHandlers.inc -> uVisualGearsHandlers.pas diff -r c3b11f913145 -r 76e68c136a11 hedgewars/VGSHandlers.inc --- a/hedgewars/VGSHandlers.inc Thu Jun 27 14:06:33 2013 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,802 +0,0 @@ -(* - * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - *) - -(* - * This file contains the step handlers for visual gears. - * - * Since the effects of visual gears do not affect the course of the game, - * no "synchronization" between players is required. - * => The usage of safe functions or data types (e.g. GetRandom() or hwFloat) - * is usually not necessary and therefore undesirable. - *) - -procedure doStepFlake(Gear: PVisualGear; Steps: Longword); -var sign: real; - moved: boolean; -begin -if vobCount = 0 then exit; - -sign:= 1; -with Gear^ do - begin - inc(FrameTicks, Steps); - if not SuddenDeathDmg and (FrameTicks > vobFrameTicks) then - begin - dec(FrameTicks, vobFrameTicks); - inc(Frame); - if Frame = vobFramesCount then - Frame:= 0 - end - else if SuddenDeathDmg and (FrameTicks > vobSDFrameTicks) then - begin - dec(FrameTicks, vobSDFrameTicks); - inc(Frame); - if Frame = vobSDFramesCount then - Frame:= 0 - end; - X:= X + (cWindSpeedf * 400 + dX + tdX) * Steps * Gear^.Scale; - if SuddenDeathDmg then - Y:= Y + (dY + tdY + cGravityf * vobSDFallSpeed) * Steps * Gear^.Scale - else - Y:= Y + (dY + tdY + cGravityf * vobFallSpeed) * Steps * Gear^.Scale; - Angle:= Angle + dAngle * Steps; - if Angle > 360 then - Angle:= Angle - 360 - else - if Angle < - 360 then - Angle:= Angle + 360; - - - if (round(X) >= cLeftScreenBorder) - and (round(X) <= cRightScreenBorder) - and (round(Y) - 75 <= LAND_HEIGHT) - and (Timer > 0) and (Timer-Steps > 0) then - begin - if tdX > 0 then - sign := 1 - else - sign:= -1; - tdX:= tdX - 0.005*Steps*sign; - if ((sign < 0) and (tdX > 0)) or ((sign > 0) and (tdX < 0)) then - tdX:= 0; - if tdX > 0 then - sign := 1 - else - sign:= -1; - tdY:= tdY - 0.005*Steps*sign; - if ((sign < 0) and (tdY > 0)) or ((sign > 0) and (tdY < 0)) then - tdY:= 0; - dec(Timer, Steps) - end - else - begin - moved:= false; - if round(X) < cLeftScreenBorder then - begin - X:= X + cScreenSpace; - moved:= true - end - else - if round(X) > cRightScreenBorder then - begin - X:= X - cScreenSpace; - moved:= true - end; - // if round(Y) < (LAND_HEIGHT - 1024 - 75) then Y:= Y + 25.0; // For if flag is set for flakes rising upwards? - if (Gear^.Layer = 2) and (round(Y) - 225 > LAND_HEIGHT) then - begin - X:= cLeftScreenBorder + random(cScreenSpace); - Y:= Y - (1024 + 250 + random(50)); // TODO - configure in theme (jellies for example could use limited range) - moved:= true - end - else if (Gear^.Layer <> 2) and (round(Y) + 50 > LAND_HEIGHT) then - begin - X:= cLeftScreenBorder + random(cScreenSpace); - Y:= Y - (1024 + random(25)); - moved:= true - end; - if moved then - begin - Angle:= random(360); - dx:= 0.0000038654705 * random(10000); - dy:= 0.000003506096 * random(7000); - if random(2) = 0 then dx := -dx - end; - Timer:= 0; - tdX:= 0; - tdY:= 0 - end; - end; - -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepBeeTrace(Gear: PVisualGear; Steps: Longword); -begin -if Gear^.FrameTicks > Steps then - dec(Gear^.FrameTicks, Steps) -else - DeleteVisualGear(Gear); -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepCloud(Gear: PVisualGear; Steps: Longword); -var s: Longword; - t: real; -begin -Gear^.X:= Gear^.X + (cWindSpeedf * 750 * Gear^.dX * Gear^.Scale) * Steps; - -// up-and-down-bounce magic -s := (GameTicks + Gear^.Timer) mod 4096; -t := 8 * Gear^.Scale * hwFloat2Float(AngleSin(s mod 2048)); -if (s < 2048) then t := -t; - -Gear^.Y := LAND_HEIGHT - 1184 + LongInt(Gear^.Timer mod 8) + t; - -if round(Gear^.X) < cLeftScreenBorder then - Gear^.X:= Gear^.X + cScreenSpace -else - if round(Gear^.X) > cRightScreenBorder then - Gear^.X:= Gear^.X - cScreenSpace -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepExpl(Gear: PVisualGear; Steps: Longword); -var s: LongInt; -begin -s:= min(Steps, cExplFrameTicks); - -Gear^.X:= Gear^.X + Gear^.dX * s; -Gear^.Y:= Gear^.Y + Gear^.dY * s; -//Gear^.dY:= Gear^.dY + cGravityf; - -if Gear^.FrameTicks <= Steps then - if Gear^.Frame = 0 then - DeleteVisualGear(Gear) - else - begin - dec(Gear^.Frame); - Gear^.FrameTicks:= cExplFrameTicks - end - else dec(Gear^.FrameTicks, Steps) -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepNote(Gear: PVisualGear; Steps: Longword); -begin -Gear^.X:= Gear^.X + Gear^.dX * Steps; - -Gear^.Y:= Gear^.Y + Gear^.dY * Steps; -Gear^.dY:= Gear^.dY + cGravityf * Steps / 2; - -Gear^.Angle:= Gear^.Angle + (Gear^.Frame + 1) * Steps / 10; -while Gear^.Angle > cMaxAngle do - Gear^.Angle:= Gear^.Angle - cMaxAngle; - -if Gear^.FrameTicks <= Steps then - DeleteVisualGear(Gear) -else - dec(Gear^.FrameTicks, Steps) -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepLineTrail(Gear: PVisualGear; Steps: Longword); -begin -Steps := Steps; -if Gear^.Timer <= Steps then - DeleteVisualGear(Gear) -else - dec(Gear^.Timer, Steps) -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepEgg(Gear: PVisualGear; Steps: Longword); -begin -Gear^.X:= Gear^.X + Gear^.dX * Steps; - -Gear^.Y:= Gear^.Y + Gear^.dY * Steps; -Gear^.dY:= Gear^.dY + cGravityf * Steps; - -Gear^.Angle:= round(Gear^.Angle + Steps) mod cMaxAngle; - -if Gear^.FrameTicks <= Steps then - begin - DeleteVisualGear(Gear); - exit - end -else - dec(Gear^.FrameTicks, Steps); - -if Gear^.FrameTicks < $FF then - Gear^.Tint:= (Gear^.Tint and $FFFFFF00) or Gear^.FrameTicks -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepFire(Gear: PVisualGear; Steps: Longword); -var vgt: PVisualGear; -begin -Gear^.X:= Gear^.X + Gear^.dX * Steps; - -Gear^.Y:= Gear^.Y + Gear^.dY * Steps;// + cGravityf * (Steps * Steps); -if (Gear^.State and gstTmpFlag) = 0 then - begin - Gear^.dY:= Gear^.dY + cGravityf * Steps; - if ((GameTicks mod 200) < Steps + 1) then - begin - vgt:= AddVisualGear(round(Gear^.X), round(Gear^.Y), vgtFire); - if vgt <> nil then - begin - vgt^.dx:= 0; - vgt^.dy:= 0; - vgt^.State:= gstTmpFlag; - end; - end - end -else - inc(Steps, Steps); - -if Gear^.FrameTicks <= Steps then - DeleteVisualGear(Gear) -else - dec(Gear^.FrameTicks, Steps) -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepShell(Gear: PVisualGear; Steps: Longword); -begin -Gear^.X:= Gear^.X + Gear^.dX * Steps; - -Gear^.Y:= Gear^.Y + Gear^.dY * Steps; -Gear^.dY:= Gear^.dY + cGravityf * Steps; - -Gear^.Angle:= round(Gear^.Angle + Steps) mod cMaxAngle; - -if Gear^.FrameTicks <= Steps then - DeleteVisualGear(Gear) -else - dec(Gear^.FrameTicks, Steps) -end; - -procedure doStepSmallDamage(Gear: PVisualGear; Steps: Longword); -begin -Gear^.Y:= Gear^.Y - 0.02 * Steps; - -if Gear^.FrameTicks <= Steps then - DeleteVisualGear(Gear) -else - dec(Gear^.FrameTicks, Steps) -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepBubble(Gear: PVisualGear; Steps: Longword); -begin -Gear^.X:= Gear^.X + Gear^.dX * Steps; -Gear^.Y:= Gear^.Y + Gear^.dY * Steps; -Gear^.Y:= Gear^.Y - cDrownSpeedf * Steps; -Gear^.dX := Gear^.dX / (1.001 * Steps); -Gear^.dY := Gear^.dY / (1.001 * Steps); - -if (Gear^.FrameTicks <= Steps) or (round(Gear^.Y) < cWaterLine) then - DeleteVisualGear(Gear) -else - dec(Gear^.FrameTicks, Steps) -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepSteam(Gear: PVisualGear; Steps: Longword); -begin -Gear^.X:= Gear^.X + (cWindSpeedf * 100 + Gear^.dX) * Steps; -Gear^.Y:= Gear^.Y - cDrownSpeedf * Steps; - -if Gear^.FrameTicks <= Steps then - if Gear^.Frame = 0 then - DeleteVisualGear(Gear) - else - begin - if Random(2) = 0 then - dec(Gear^.Frame); - Gear^.FrameTicks:= cExplFrameTicks - end -else dec(Gear^.FrameTicks, Steps) -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepAmmo(Gear: PVisualGear; Steps: Longword); -begin -Gear^.Y:= Gear^.Y - cDrownSpeedf * Steps; - -Gear^.scale:= Gear^.scale + 0.0025 * Steps; -Gear^.alpha:= Gear^.alpha - 0.0015 * Steps; - -if Gear^.alpha < 0 then - DeleteVisualGear(Gear) -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepSmoke(Gear: PVisualGear; Steps: Longword); -begin -Gear^.X:= Gear^.X + (cWindSpeedf + Gear^.dX) * Steps; -Gear^.Y:= Gear^.Y - (cDrownSpeedf + Gear^.dY) * Steps; - -Gear^.dX := Gear^.dX + (cWindSpeedf * 0.3 * Steps); -//Gear^.dY := Gear^.dY - (cDrownSpeedf * 0.995); - -if Gear^.FrameTicks <= Steps then - if Gear^.Frame = 0 then - DeleteVisualGear(Gear) - else - begin - if Random(2) = 0 then - dec(Gear^.Frame); - Gear^.FrameTicks:= cExplFrameTicks - end - else dec(Gear^.FrameTicks, Steps) -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepDust(Gear: PVisualGear; Steps: Longword); -begin -Gear^.X:= Gear^.X + (cWindSpeedf + (cWindSpeedf * 0.03 * Steps) + Gear^.dX) * Steps; -Gear^.Y:= Gear^.Y - (Gear^.dY) * Steps; - -Gear^.dX := Gear^.dX - (Gear^.dX * 0.005 * Steps); -Gear^.dY := Gear^.dY - (cDrownSpeedf * 0.001 * Steps); - -if Gear^.FrameTicks <= Steps then - if Gear^.Frame = 0 then - DeleteVisualGear(Gear) - else - begin - dec(Gear^.Frame); - Gear^.FrameTicks:= cExplFrameTicks - end - else dec(Gear^.FrameTicks, Steps) -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepSplash(Gear: PVisualGear; Steps: Longword); -begin -if Gear^.FrameTicks <= Steps then - DeleteVisualGear(Gear) -else - dec(Gear^.FrameTicks, Steps); -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepDroplet(Gear: PVisualGear; Steps: Longword); -begin -Gear^.X:= Gear^.X + Gear^.dX * Steps; - -Gear^.Y:= Gear^.Y + Gear^.dY * Steps; -Gear^.dY:= Gear^.dY + cGravityf * Steps; - -if round(Gear^.Y) > cWaterLine then - begin - DeleteVisualGear(Gear); - PlaySound(TSound(ord(sndDroplet1) + Random(3))); - end; -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepSmokeRing(Gear: PVisualGear; Steps: Longword); -begin -inc(Gear^.Timer, Steps); -if Gear^.Timer >= Gear^.FrameTicks then - DeleteVisualGear(Gear) -else - begin - Gear^.scale := 1.25 * (-power(2, -10 * Int(Gear^.Timer)/Gear^.FrameTicks) + 1) + 0.4; - Gear^.alpha := 1 - power(Gear^.Timer / 350, 4); - if Gear^.alpha < 0 then - Gear^.alpha:= 0; - end; -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepFeather(Gear: PVisualGear; Steps: Longword); -begin -Gear^.X:= Gear^.X + Gear^.dX * Steps; - -Gear^.Y:= Gear^.Y + Gear^.dY * Steps; -Gear^.dY:= Gear^.dY + cGravityf * Steps; - -Gear^.Angle:= round(Gear^.Angle + Steps) mod cMaxAngle; - -if Gear^.FrameTicks <= Steps then - DeleteVisualGear(Gear) -else - dec(Gear^.FrameTicks, Steps) -end; - -//////////////////////////////////////////////////////////////////////////////// -const cSorterWorkTime = 640; -var thexchar: array[0..cMaxTeams] of - record - dy, ny, dw: LongInt; - team: PTeam; - SortFactor: QWord; - end; - currsorter: PVisualGear = nil; - -procedure doStepTeamHealthSorterWork(Gear: PVisualGear; Steps: Longword); -var i, t: LongInt; -begin -for t:= 1 to min(Steps, Gear^.Timer) do - begin - dec(Gear^.Timer); - if (Gear^.Timer and 15) = 0 then - for i:= 0 to Pred(TeamsCount) do - with thexchar[i] do - begin - {$WARNINGS OFF} - team^.DrawHealthY:= ny + dy * LongInt(Gear^.Timer) div cSorterWorkTime; - team^.TeamHealthBarWidth:= team^.NewTeamHealthBarWidth + dw * LongInt(Gear^.Timer) div cSorterWorkTime; - {$WARNINGS ON} - end; - end; - -if (Gear^.Timer = 0) or (currsorter <> Gear) then - begin - if currsorter = Gear then - currsorter:= nil; - DeleteVisualGear(Gear); - exit - end -end; - -procedure doStepTeamHealthSorter(Gear: PVisualGear; Steps: Longword); -var i: Longword; - b: boolean; - t: LongInt; -begin -Steps:= Steps; // avoid compiler hint - -for t:= 0 to Pred(TeamsCount) do - with thexchar[t] do - begin - team:= TeamsArray[t]; - dy:= team^.DrawHealthY; - dw:= team^.TeamHealthBarWidth - team^.NewTeamHealthBarWidth; - if team^.TeamHealth > 0 then - begin - SortFactor:= team^.Clan^.ClanHealth; - SortFactor:= (SortFactor shl 3) + team^.Clan^.ClanIndex; - SortFactor:= (SortFactor shl 30) + team^.TeamHealth; - end - else - SortFactor:= 0; - end; - -if TeamsCount > 1 then - repeat - b:= true; - for t:= 0 to TeamsCount - 2 do - if (thexchar[t].SortFactor > thexchar[Succ(t)].SortFactor) then - begin - thexchar[cMaxTeams]:= thexchar[t]; - thexchar[t]:= thexchar[Succ(t)]; - thexchar[Succ(t)]:= thexchar[cMaxTeams]; - b:= false - end - until b; - -t:= - 4; -for i:= 0 to Pred(TeamsCount) do - with thexchar[i] do - if team^.TeamHealth > 0 then - begin - dec(t, team^.HealthTex^.h + 2); - ny:= t; - dy:= dy - ny - end; - -Gear^.Timer:= cSorterWorkTime; -Gear^.doStep:= @doStepTeamHealthSorterWork; -currsorter:= Gear; -//doStepTeamHealthSorterWork(Gear, Steps) -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepSpeechBubbleWork(Gear: PVisualGear; Steps: Longword); -begin -if Gear^.Timer > Steps then dec(Gear^.Timer, Steps) else Gear^.Timer:= 0; - -if (Gear^.Hedgehog^.Gear <> nil) then - begin - Gear^.X:= hwFloat2Float(Gear^.Hedgehog^.Gear^.X) + (Gear^.Tex^.w div 2 - Gear^.FrameTicks); - Gear^.Y:= hwFloat2Float(Gear^.Hedgehog^.Gear^.Y) - (16 + Gear^.Tex^.h); - end; - -if Gear^.Timer = 0 then - begin - if Gear^.Hedgehog^.SpeechGear = Gear then - Gear^.Hedgehog^.SpeechGear:= nil; - DeleteVisualGear(Gear) - end; -end; - -procedure doStepSpeechBubble(Gear: PVisualGear; Steps: Longword); -begin -Steps:= Steps; // avoid compiler hint - -with Gear^.Hedgehog^ do - if SpeechGear <> nil then - SpeechGear^.Timer:= 0; - -Gear^.Hedgehog^.SpeechGear:= Gear; - -Gear^.Timer:= max(LongInt(Length(Gear^.Text)) * 150, 3000); - -Gear^.Tex:= RenderSpeechBubbleTex(Gear^.Text, Gear^.FrameTicks, fnt16); - -case Gear^.FrameTicks of - 1: Gear^.FrameTicks:= SpritesData[sprSpeechTail].Width-28; - 2: Gear^.FrameTicks:= SpritesData[sprThoughtTail].Width-20; - 3: Gear^.FrameTicks:= SpritesData[sprShoutTail].Width-10; - end; - -Gear^.doStep:= @doStepSpeechBubbleWork; - -Gear^.Y:= Gear^.Y - Gear^.Tex^.h -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepHealthTagWork(Gear: PVisualGear; Steps: Longword); -begin -if Steps > Gear^.Timer then - DeleteVisualGear(Gear) -else - begin - dec(Gear^.Timer, Steps); - Gear^.Y:= Gear^.Y + Gear^.dY * Steps; - Gear^.X:= Gear^.X + Gear^.dX * Steps - end; -end; - -procedure doStepHealthTagWorkUnderWater(Gear: PVisualGear; Steps: Longword); -begin -if round(Gear^.Y) - 10 < cWaterLine then - DeleteVisualGear(Gear) -else - Gear^.Y:= Gear^.Y - 0.08 * Steps; - -end; - -procedure doStepHealthTag(Gear: PVisualGear; Steps: Longword); -var s: shortstring; -begin -s:= ''; - -str(Gear^.State, s); -if Gear^.Hedgehog <> nil then - Gear^.Tex:= RenderStringTex(s, Gear^.Hedgehog^.Team^.Clan^.Color, fnt16) -else - Gear^.Tex:= RenderStringTex(s, cWhiteColor, fnt16); - -Gear^.doStep:= @doStepHealthTagWork; - -if (round(Gear^.Y) > cWaterLine) and (Gear^.Frame = 0) then - Gear^.doStep:= @doStepHealthTagWorkUnderWater; - -Gear^.Y:= Gear^.Y - Gear^.Tex^.h; - -if Steps > 1 then - Gear^.doStep(Gear, Steps-1); -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepSmokeTrace(Gear: PVisualGear; Steps: Longword); -begin -inc(Gear^.Timer, Steps ); -if Gear^.Timer > 64 then - begin - if Gear^.State = 0 then - begin - DeleteVisualGear(Gear); - exit; - end; - dec(Gear^.State, Gear^.Timer div 65); - Gear^.Timer:= Gear^.Timer mod 65; - end; -Gear^.dX:= Gear^.dX + cWindSpeedf * Steps; -Gear^.X:= Gear^.X + Gear^.dX; -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepExplosionWork(Gear: PVisualGear; Steps: Longword); -begin -inc(Gear^.Timer, Steps); -if Gear^.Timer > 75 then - begin - inc(Gear^.State, Gear^.Timer div 76); - Gear^.Timer:= Gear^.Timer mod 76; - if Gear^.State > 5 then - DeleteVisualGear(Gear); - end; -end; - -procedure doStepExplosion(Gear: PVisualGear; Steps: Longword); -var i: LongWord; - gX,gY: LongInt; - vg: PVisualGear; -begin -gX:= round(Gear^.X); -gY:= round(Gear^.Y); -for i:= 0 to 31 do - begin - vg:= AddVisualGear(gX, gY, vgtFire); - if vg <> nil then - begin - vg^.State:= gstTmpFlag; - inc(vg^.FrameTicks, vg^.FrameTicks) - end - end; -for i:= 0 to 8 do AddVisualGear(gX, gY, vgtExplPart); -for i:= 0 to 8 do AddVisualGear(gX, gY, vgtExplPart2); -Gear^.doStep:= @doStepExplosionWork; -if Steps > 1 then - Gear^.doStep(Gear, Steps-1); -end; - - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepBigExplosionWork(Gear: PVisualGear; Steps: Longword); -var maxMovement: LongInt; -begin - -inc(Gear^.Timer, Steps); -if (Gear^.Timer and 5) = 0 then - begin - maxMovement := max(1, 13 - ((Gear^.Timer * 15) div 250)); - ShakeCamera(maxMovement); - end; - -if Gear^.Timer > 250 then - DeleteVisualGear(Gear); -end; - -procedure doStepBigExplosion(Gear: PVisualGear; Steps: Longword); -var i: LongWord; - gX,gY: LongInt; - vg: PVisualGear; -begin -//ScreenFade:= sfFromWhite; -//ScreenFadeValue:= round(60 * zoom * zoom); -//ScreenFadeSpeed:= 5; -gX:= round(Gear^.X); -gY:= round(Gear^.Y); -AddVisualGear(gX, gY, vgtSmokeRing); -for i:= 0 to 46 do - begin - vg:= AddVisualGear(gX, gY, vgtFire); - if vg <> nil then - begin - vg^.State:= gstTmpFlag; - inc(vg^.FrameTicks, vg^.FrameTicks) - end - end; -for i:= 0 to 15 do - AddVisualGear(gX, gY, vgtExplPart); -for i:= 0 to 15 do - AddVisualGear(gX, gY, vgtExplPart2); -Gear^.doStep:= @doStepBigExplosionWork; -if Steps > 1 then - Gear^.doStep(Gear, Steps-1); -with mobileRecord do - if (performRumble <> nil) and (not fastUntilLag) then - performRumble(kSystemSoundID_Vibrate); -end; - -procedure doStepChunk(Gear: PVisualGear; Steps: Longword); -begin -Gear^.X:= Gear^.X + Gear^.dX * Steps; - -Gear^.Y:= Gear^.Y + Gear^.dY * Steps; -Gear^.dY:= Gear^.dY + cGravityf * Steps; - -Gear^.Angle:= round(Gear^.Angle + Steps) mod cMaxAngle; - -if (round(Gear^.Y) > cWaterLine) and ((cReducedQuality and rqPlainSplash) = 0) then - begin - AddVisualGear(round(Gear^.X), round(Gear^.Y), vgtDroplet); - DeleteVisualGear(Gear); - end -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepBulletHit(Gear: PVisualGear; Steps: Longword); -begin -if Gear^.FrameTicks <= Steps then - DeleteVisualGear(Gear) -else - dec(Gear^.FrameTicks, Steps); -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepCircle(Gear: PVisualGear; Steps: Longword); -var tmp: LongInt; - i: LongWord; -begin -with Gear^ do - if Frame <> 0 then - for i:= 1 to Steps do - begin - inc(FrameTicks); - if (FrameTicks mod Frame) = 0 then - begin - tmp:= Gear^.Tint and $FF; - if tdY >= 0 then - inc(tmp) - else - dec(tmp); - if tmp < round(dX) then - tdY:= 1; - if tmp > round(dY) then - tdY:= -1; - if tmp > 255 then - tmp := 255; - if tmp < 0 then - tmp := 0; - Gear^.Tint:= (Gear^.Tint and $FFFFFF00) or Longword(tmp) - end - end -end; - -//////////////////////////////////////////////////////////////////////////////// -procedure doStepSmoothWindBar(Gear: PVisualGear; Steps: Longword); -begin -inc(Gear^.Timer, Steps); - -while Gear^.Timer >= 10 do - begin - dec(Gear^.Timer, 10); - if WindBarWidth < Gear^.Tag then - inc(WindBarWidth) - else if WindBarWidth > Gear^.Tag then - dec(WindBarWidth); - end; -if cWindspeedf > Gear^.dAngle then - begin - cWindspeedf := cWindspeedf - Gear^.Angle*Steps; - if cWindspeedf < Gear^.dAngle then cWindspeedf:= Gear^.dAngle; - end -else if cWindspeedf < Gear^.dAngle then - begin - cWindspeedf := cWindspeedf + Gear^.Angle*Steps; - if cWindspeedf > Gear^.dAngle then cWindspeedf:= Gear^.dAngle; - end; - -if (WindBarWidth = Gear^.Tag) and (cWindspeedf = Gear^.dAngle) then - DeleteVisualGear(Gear) -end; -//////////////////////////////////////////////////////////////////////////////// -procedure doStepStraightShot(Gear: PVisualGear; Steps: Longword); -begin -Gear^.X:= Gear^.X + Gear^.dX * Steps; -Gear^.Y:= Gear^.Y - Gear^.dY * Steps; - -if Gear^.FrameTicks <= Steps then - DeleteVisualGear(Gear) -else - begin - dec(Gear^.FrameTicks, Steps); - if (Gear^.FrameTicks < 501) and (Gear^.FrameTicks mod 5 = 0) then - Gear^.Tint:= (Gear^.Tint and $FFFFFF00) or (((Gear^.Tint and $000000FF) * Gear^.FrameTicks) div 500) - end -end; - diff -r c3b11f913145 -r 76e68c136a11 hedgewars/hwengine.pas --- a/hedgewars/hwengine.pas Thu Jun 27 14:06:33 2013 +0400 +++ b/hedgewars/hwengine.pas Thu Jun 27 14:37:03 2013 +0400 @@ -32,7 +32,7 @@ uses SDLh, uMisc, uConsole, uGame, uConsts, uLand, uAmmos, uVisualGears, uGears, uStore, uWorld, uInputHandler , uSound, uScript, uTeams, uStats, uIO, uLocale, uChat, uAI, uAIMisc, uAILandMarks, uLandTexture, uCollisions , SysUtils, uTypes, uVariables, uCommands, uUtils, uCaptions, uDebug, uCommandHandlers, uLandPainted - , uPhysFSLayer, uCursor, uRandom, ArgParsers + , uPhysFSLayer, uCursor, uRandom, ArgParsers, uVisualGearsHandlers {$IFDEF USE_VIDEO_RECORDING}, uVideoRec {$ENDIF} {$IFDEF USE_TOUCH_INTERFACE}, uTouch {$ENDIF} {$IFDEF ANDROID}, GLUnit{$ENDIF} @@ -457,6 +457,7 @@ uStore.initModule; uTeams.initModule; uVisualGears.initModule; + uVisualGearsHandlers.initModule; uWorld.initModule; end; end; diff -r c3b11f913145 -r 76e68c136a11 hedgewars/uGame.pas --- a/hedgewars/uGame.pas Thu Jun 27 14:06:33 2013 +0400 +++ b/hedgewars/uGame.pas Thu Jun 27 14:37:03 2013 +0400 @@ -27,7 +27,7 @@ implementation //////////////////// uses uInputHandler, uTeams, uIO, uAI, uGears, uSound, uLocale, uCaptions, - uVisualGears, uTypes, uVariables, uCommands, uConsts + uVisualGears, uTypes, uVariables, uCommands, uConsts, uVisualGearsList {$IFDEF USE_TOUCH_INTERFACE}, uTouch{$ENDIF}; procedure DoGameTick(Lag: LongInt); diff -r c3b11f913145 -r 76e68c136a11 hedgewars/uGears.pas --- a/hedgewars/uGears.pas Thu Jun 27 14:06:33 2013 +0400 +++ b/hedgewars/uGears.pas Thu Jun 27 14:37:03 2013 +0400 @@ -59,7 +59,8 @@ uses uStore, uSound, uTeams, uRandom, uCollisions, uIO, uLandGraphics, {$IFDEF SDL13}uTouch,{$ENDIF} uLocale, uAI, uAmmos, uStats, uVisualGears, uScript, GLunit, uVariables, uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uLandTexture, - uGearsHedgehog, uGearsUtils, uGearsList, uGearsHandlers, uGearsHandlersRope; + uGearsHedgehog, uGearsUtils, uGearsList, uGearsHandlers, uGearsHandlersRope + , uVisualGearsList; var skipFlag: boolean; diff -r c3b11f913145 -r 76e68c136a11 hedgewars/uGearsHedgehog.pas --- a/hedgewars/uGearsHedgehog.pas Thu Jun 27 14:06:33 2013 +0400 +++ b/hedgewars/uGearsHedgehog.pas Thu Jun 27 14:37:03 2013 +0400 @@ -35,7 +35,7 @@ uses uConsts, uVariables, uFloat, uAmmos, uSound, uCaptions, uCommands, uLocale, uUtils, uVisualGears, uStats, uIO, uScript, uGearsList, uGears, uCollisions, uRandom, uStore, uTeams, - uGearsUtils; + uGearsUtils, uVisualGearsList; var GHStepTicks: LongWord = 0; diff -r c3b11f913145 -r 76e68c136a11 hedgewars/uGearsRender.pas --- a/hedgewars/uGearsRender.pas Thu Jun 27 14:06:33 2013 +0400 +++ b/hedgewars/uGearsRender.pas Thu Jun 27 14:37:03 2013 +0400 @@ -38,7 +38,7 @@ end; implementation -uses uRender, uUtils, uVariables, uAmmos, Math, uVisualGears; +uses uRender, uUtils, uVariables, uAmmos, Math, uVisualGears, uVisualGearsList; procedure DrawRopeLinesRQ(Gear: PGear); begin diff -r c3b11f913145 -r 76e68c136a11 hedgewars/uGearsUtils.pas --- a/hedgewars/uGearsUtils.pas Thu Jun 27 14:06:33 2013 +0400 +++ b/hedgewars/uGearsUtils.pas Thu Jun 27 14:37:03 2013 +0400 @@ -50,7 +50,7 @@ uses uFloat, uSound, uCollisions, uUtils, uConsts, uVisualGears, uAIMisc, uVariables, uLandGraphics, uScript, uStats, uCaptions, uTeams, uStore, uLocale, uTextures, uRenderUtils, uRandom, SDLh, uDebug, uGears, - uGearsList, Math; + uGearsList, Math, uVisualGearsList; procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword); inline; begin diff -r c3b11f913145 -r 76e68c136a11 hedgewars/uScript.pas --- a/hedgewars/uScript.pas Thu Jun 27 14:06:33 2013 +0400 +++ b/hedgewars/uScript.pas Thu Jun 27 14:37:03 2013 +0400 @@ -84,6 +84,7 @@ SDLh, SysUtils, uIO, + uVisualGearsList, uPhysFSLayer, typinfo ; diff -r c3b11f913145 -r 76e68c136a11 hedgewars/uTeams.pas --- a/hedgewars/uTeams.pas Thu Jun 27 14:06:33 2013 +0400 +++ b/hedgewars/uTeams.pas Thu Jun 27 14:37:03 2013 +0400 @@ -43,7 +43,7 @@ implementation uses uLocale, uAmmos, uChat, uVariables, uUtils, uIO, uCaptions, uCommands, uDebug, - uGearsUtils, uGearsList + uGearsUtils, uGearsList, uVisualGearsList {$IFDEF USE_TOUCH_INTERFACE}, uTouch{$ENDIF}; var MaxTeamHealth: LongInt; diff -r c3b11f913145 -r 76e68c136a11 hedgewars/uVisualGears.pas --- a/hedgewars/uVisualGears.pas Thu Jun 27 14:06:33 2013 +0400 +++ b/hedgewars/uVisualGears.pas Thu Jun 27 14:37:03 2013 +0400 @@ -34,14 +34,8 @@ procedure initModule; procedure freeModule; -function AddVisualGear(X, Y: LongInt; Kind: TVisualGearType): PVisualGear; inline; -function AddVisualGear(X, Y: LongInt; Kind: TVisualGearType; State: LongWord): PVisualGear; inline; -function AddVisualGear(X, Y: LongInt; Kind: TVisualGearType; State: LongWord; Critical: Boolean): PVisualGear; - procedure ProcessVisualGears(Steps: Longword); procedure DrawVisualGears(Layer: LongWord); -procedure DeleteVisualGear(Gear: PVisualGear); -function VisualGearByUID(uid : Longword) : PVisualGear; procedure AddClouds; procedure AddFlakes; @@ -53,17 +47,8 @@ procedure KickFlakes(Radius, X, Y: LongInt); implementation -uses uSound, uVariables, uTextures, uRender, Math, uRenderUtils, uStore, uUtils; - -const - cExplFrameTicks = 110; - //cSmokeZ = 499; -var VGCounter: LongWord; - VisualGearLayers: array[0..6] of PVisualGear; - -// For better maintainability the step handlers of visual gears are stored -// in a separate file. -{$INCLUDE "VGSHandlers.inc"} +uses uSound, uVariables, uTextures, uRender, Math, uRenderUtils, uStore, uUtils + , uVisualGearsHandlers, uVisualGearsList; procedure AddDamageTag(X, Y, Damage, Color: LongWord); var s: shortstring; @@ -84,436 +69,6 @@ // ================================================================== -// ================================================================== -const doStepHandlers: array[TVisualGearType] of TVGearStepProcedure = - ( - @doStepFlake, - @doStepCloud, - @doStepExpl, - @doStepExpl, - @doStepFire, - @doStepSmallDamage, - @doStepTeamHealthSorter, - @doStepSpeechBubble, - @doStepBubble, - @doStepSteam, - @doStepAmmo, - @doStepSmoke, - @doStepSmoke, - @doStepShell, - @doStepDust, - @doStepSplash, - @doStepDroplet, - @doStepSmokeRing, - @doStepBeeTrace, - @doStepEgg, - @doStepFeather, - @doStepHealthTag, - @doStepSmokeTrace, - @doStepSmokeTrace, - @doStepExplosion, - @doStepBigExplosion, - @doStepChunk, - @doStepNote, - @doStepLineTrail, - @doStepBulletHit, - @doStepCircle, - @doStepSmoothWindBar, - @doStepStraightShot - ); - -function AddVisualGear(X, Y: LongInt; Kind: TVisualGearType): PVisualGear; inline; -begin - AddVisualGear:= AddVisualGear(X, Y, Kind, 0, false); -end; - -function AddVisualGear(X, Y: LongInt; Kind: TVisualGearType; State: LongWord): PVisualGear; inline; -begin - AddVisualGear:= AddVisualGear(X, Y, Kind, State, false); -end; - -function AddVisualGear(X, Y: LongInt; Kind: TVisualGearType; State: LongWord; Critical: Boolean): PVisualGear; -var gear: PVisualGear; - t: Longword; - sp: real; -begin -AddVisualGear:= nil; -if ((GameType = gmtSave) or (fastUntilLag and (GameType = gmtNet)) or fastScrolling) and // we are scrolling now - ((Kind <> vgtCloud) and (not Critical)) then - exit; - -if ((cReducedQuality and rqAntiBoom) <> 0) and - (not Critical) and - (not (Kind in - [vgtTeamHealthSorter, - vgtSmallDamageTag, - vgtSpeechBubble, - vgtHealthTag, - vgtExplosion, - vgtSmokeTrace, - vgtEvilTrace, - vgtNote, - vgtSmoothWindBar])) then - - exit; - -inc(VGCounter); -New(gear); -FillChar(gear^, sizeof(TVisualGear), 0); -gear^.X:= real(X); -gear^.Y:= real(Y); -gear^.Kind := Kind; -gear^.doStep:= doStepHandlers[Kind]; -gear^.State:= 0; -gear^.Tint:= $FFFFFFFF; -gear^.uid:= VGCounter; -gear^.Layer:= 0; - -with gear^ do - case Kind of - vgtFlake: - begin - Timer:= 0; - tdX:= 0; - tdY:= 0; - Scale:= 1.0; - if SuddenDeathDmg then - begin - FrameTicks:= random(vobSDFrameTicks); - Frame:= random(vobSDFramesCount); - end - else - begin - FrameTicks:= random(vobFrameTicks); - Frame:= random(vobFramesCount); - end; - Angle:= random(360); - dx:= 0.0000038654705 * random(10000); - dy:= 0.000003506096 * random(7000); - if random(2) = 0 then - dx := -dx; - if SuddenDeathDmg then - dAngle:= (random(2) * 2 - 1) * (vobSDVelocity + random(vobSDVelocity)) / 1000 - else - dAngle:= (random(2) * 2 - 1) * (vobVelocity + random(vobVelocity)) / 1000 - end; - vgtCloud: - begin - Frame:= random(4); - dx:= 0.5 + 0.1 * random(5); // how much the cloud will be affected by wind - timer:= random(4096); - Scale:= 1.0 - end; - vgtExplPart, - vgtExplPart2: - begin - t:= random(1024); - sp:= 0.001 * (random(95) + 70); - dx:= hwFloat2Float(AngleSin(t)) * sp; - dy:= hwFloat2Float(AngleCos(t)) * sp; - if random(2) = 0 then - dx := -dx; - if random(2) = 0 then - dy := -dy; - Frame:= 7 - random(3); - FrameTicks:= cExplFrameTicks - end; - vgtFire: - begin - t:= random(1024); - sp:= 0.001 * (random(85) + 95); - dx:= hwFloat2Float(AngleSin(t)) * sp; - dy:= hwFloat2Float(AngleCos(t)) * sp; - if random(2) = 0 then - dx := -dx; - if random(2) = 0 then - dy := -dy; - FrameTicks:= 650 + random(250); - Frame:= random(8) - end; - vgtEgg: - begin - t:= random(1024); - sp:= 0.001 * (random(85) + 95); - dx:= hwFloat2Float(AngleSin(t)) * sp; - dy:= hwFloat2Float(AngleCos(t)) * sp; - if random(2) = 0 then - dx := -dx; - if random(2) = 0 then - dy := -dy; - FrameTicks:= 650 + random(250); - Frame:= 1 - end; - vgtShell: FrameTicks:= 500; - vgtSmallDamageTag: - begin - gear^.FrameTicks:= 1100 - end; - vgtBubble: - begin - dx:= 0.0000038654705 * random(10000); - dy:= 0; - if random(2) = 0 then - dx := -dx; - FrameTicks:= 250 + random(1751); - Frame:= random(5) - end; - vgtSteam: - begin - dx:= 0.0000038654705 * random(10000); - dy:= 0.001 * (random(85) + 95); - if random(2) = 0 then - dx := -dx; - Frame:= 7 - random(3); - FrameTicks:= cExplFrameTicks * 2; - end; - vgtAmmo: - begin - alpha:= 1.0; - scale:= 1.0 - end; - vgtSmokeWhite, - vgtSmoke: - begin - Scale:= 1.0; - dx:= 0.0002 * (random(45) + 10); - dy:= 0.0002 * (random(45) + 10); - if random(2) = 0 then - dx := -dx; - Frame:= 7 - random(2); - FrameTicks:= cExplFrameTicks * 2; - end; - vgtDust: - begin - dx:= 0.005 * (random(15) + 10); - dy:= 0.001 * (random(40) + 20); - if random(2) = 0 then dx := -dx; - if random(2) = 0 then Tag:= 1 - else Tag:= -1; - Frame:= 7 - random(2); - FrameTicks:= random(20) + 15; - end; - vgtSplash: - begin - dx:= 0; - dy:= 0; - FrameTicks:= 740; - Frame:= 19; - Scale:= 0.75; - Timer:= 1; - end; - vgtDroplet: - begin - dx:= 0.001 * (random(180) - 90); - dy:= -0.001 * (random(160) + 40); - FrameTicks:= 250 + random(1751); - Frame:= random(3) - end; - vgtBeeTrace: - begin - FrameTicks:= 1000; - Frame:= random(16); - end; - vgtSmokeRing: - begin - dx:= 0; - dy:= 0; - FrameTicks:= 600; - Timer:= 0; - Frame:= 0; - scale:= 0.6; - alpha:= 1; - angle:= random(360); - end; - vgtFeather: - begin - t:= random(1024); - sp:= 0.001 * (random(85) + 95); - dx:= hwFloat2Float(AngleSin(t)) * sp; - dy:= hwFloat2Float(AngleCos(t)) * sp; - if random(2) = 0 then - dx := -dx; - if random(2) = 0 then - dy := -dy; - FrameTicks:= 650 + random(250); - Frame:= 1 - end; - vgtHealthTag: - begin - Frame:= 0; - Timer:= 1500; - dY:= -0.08; - dX:= 0; - //gear^.Z:= 2002; - end; - vgtSmokeTrace, - vgtEvilTrace: - begin - gear^.X:= gear^.X - 16; - gear^.Y:= gear^.Y - 16; - gear^.State:= 8; - //gear^.Z:= cSmokeZ - end; -vgtBigExplosion: - begin - gear^.Angle:= random(360); - end; - vgtChunk: - begin - gear^.Frame:= random(4); - t:= random(1024); - sp:= 0.001 * (random(85) + 47); - dx:= hwFloat2Float(AngleSin(t)) * sp; - dy:= hwFloat2Float(AngleCos(t)) * sp * -2; - if random(2) = 0 then - dx := -dx; - end; - vgtNote: - begin - dx:= 0.005 * (random(15) + 10); - dy:= -0.001 * (random(40) + 20); - if random(2) = 0 then - dx := -dx; - Frame:= random(4); - FrameTicks:= random(2000) + 1500; - end; - vgtBulletHit: - begin - dx:= 0; - dy:= 0; - FrameTicks:= 350; - Frame:= 7; - Angle:= 0; - end; -vgtSmoothWindBar: - begin - Angle:= hwFloat2Float(cMaxWindSpeed)*2 / 1440; // seems rate below is supposed to change wind bar at 1px per 10ms. Max time, 1440ms. This tries to match the rate of change - Tag:= hwRound(cWindSpeed * 72 / cMaxWindSpeed); - end; - vgtStraightShot: - begin - Angle:= 0; - Scale:= 1.0; - dx:= 0.001 * random(45); - dy:= 0.001 * (random(20) + 25); - State:= ord(sprHealth); - if random(2) = 0 then - dx := -dx; - Frame:= 0; - FrameTicks:= random(750) + 1250; - State:= ord(sprSnowDust); - end; - end; - -if State <> 0 then - gear^.State:= State; - -case Gear^.Kind of - vgtFlake: if cFlattenFlakes then - gear^.Layer:= 0 - else if random(3) = 0 then - begin - gear^.Scale:= 0.5; - gear^.Layer:= 0 // 33% - far back - end - else if random(3) = 0 then - begin - gear^.Scale:= 0.8; - gear^.Layer:= 4 // 22% - mid-distance - end - else if random(3) <> 0 then - gear^.Layer:= 5 // 30% - just behind land - else if random(2) = 0 then - gear^.Layer:= 6 // 7% - just in front of land - else - begin - gear^.Scale:= 1.5; - gear^.Layer:= 2; // 7% - close up - end; - - vgtCloud: if cFlattenClouds then gear^.Layer:= 5 - else if random(3) = 0 then - begin - gear^.Scale:= 0.25; - gear^.Layer:= 0 - end - else if random(2) = 0 then - gear^.Layer:= 5 - else - begin - gear^.Scale:= 0.4; - gear^.Layer:= 4 - end; - - // 0: this layer is very distant in the background when in stereo - vgtTeamHealthSorter, - vgtSmoothWindBar: gear^.Layer:= 0; - - - // 1: this layer is on the land level (which is close but behind the screen plane) when stereo - vgtSmokeTrace, - vgtEvilTrace, - vgtLineTrail, - vgtSmoke, - vgtSmokeWhite, - vgtDust, - vgtFire, - vgtSplash, - vgtDroplet, - vgtBubble: gear^.Layer:= 1; - - // 3: this layer is on the screen plane (depth = 0) when stereo - vgtSpeechBubble, - vgtSmallDamageTag, - vgtHealthTag, - vgtStraightShot, - vgtChunk: gear^.Layer:= 3; - - // 2: this layer is outside the screen when stereo - vgtExplosion, - vgtBigExplosion, - vgtExplPart, - vgtExplPart2, - vgtSteam, - vgtAmmo, - vgtShell, - vgtFeather, - vgtEgg, - vgtBeeTrace, - vgtSmokeRing, - vgtNote, - vgtBulletHit, - vgtCircle: gear^.Layer:= 2 -end; - -if VisualGearLayers[gear^.Layer] <> nil then - begin - VisualGearLayers[gear^.Layer]^.PrevGear:= gear; - gear^.NextGear:= VisualGearLayers[gear^.Layer] - end; -VisualGearLayers[gear^.Layer]:= gear; - -AddVisualGear:= gear; -end; - -procedure DeleteVisualGear(Gear: PVisualGear); -begin - FreeTexture(Gear^.Tex); - Gear^.Tex:= nil; - - if Gear^.NextGear <> nil then - Gear^.NextGear^.PrevGear:= Gear^.PrevGear; - if Gear^.PrevGear <> nil then - Gear^.PrevGear^.NextGear:= Gear^.NextGear - else - VisualGearLayers[Gear^.Layer]:= Gear^.NextGear; - - if lastVisualGearByUID = Gear then - lastVisualGearByUID:= nil; - - Dispose(Gear); -end; - procedure ProcessVisualGears(Steps: Longword); var Gear, t: PVisualGear; i: LongWord; @@ -900,35 +455,6 @@ end; end; -function VisualGearByUID(uid : Longword) : PVisualGear; -var vg: PVisualGear; - i: LongWord; -begin -VisualGearByUID:= nil; -if uid = 0 then - exit; -if (lastVisualGearByUID <> nil) and (lastVisualGearByUID^.uid = uid) then - begin - VisualGearByUID:= lastVisualGearByUID; - exit - end; -// search in an order that is more likely to return layers they actually use. Could perhaps track statistically AddVisualGear in uScript, since that is most likely the ones they want -for i:= 2 to 5 do - begin - vg:= VisualGearLayers[i mod 4]; - while vg <> nil do - begin - if vg^.uid = uid then - begin - lastVisualGearByUID:= vg; - VisualGearByUID:= vg; - exit - end; - vg:= vg^.NextGear - end - end -end; - procedure AddClouds; var i: LongInt; begin diff -r c3b11f913145 -r 76e68c136a11 hedgewars/uVisualGearsHandlers.pas --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hedgewars/uVisualGearsHandlers.pas Thu Jun 27 14:37:03 2013 +0400 @@ -0,0 +1,897 @@ +(* + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2013 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + *) + +(* + * This file contains the step handlers for visual gears. + * + * Since the effects of visual gears do not affect the course of the game, + * no "synchronization" between players is required. + * => The usage of safe functions or data types (e.g. GetRandom() or hwFloat) + * is usually not necessary and therefore undesirable. + *) + +{$INCLUDE "options.inc"} + +unit uVisualGearsHandlers; + +interface +uses uTypes; + +var doStepHandlers: array[TVisualGearType] of TVGearStepProcedure; + +procedure doStepFlake(Gear: PVisualGear; Steps: Longword); +procedure doStepBeeTrace(Gear: PVisualGear; Steps: Longword); +procedure doStepCloud(Gear: PVisualGear; Steps: Longword); +procedure doStepExpl(Gear: PVisualGear; Steps: Longword); +procedure doStepNote(Gear: PVisualGear; Steps: Longword); +procedure doStepLineTrail(Gear: PVisualGear; Steps: Longword); +procedure doStepEgg(Gear: PVisualGear; Steps: Longword); +procedure doStepFire(Gear: PVisualGear; Steps: Longword); +procedure doStepShell(Gear: PVisualGear; Steps: Longword); +procedure doStepSmallDamage(Gear: PVisualGear; Steps: Longword); +procedure doStepBubble(Gear: PVisualGear; Steps: Longword); +procedure doStepSteam(Gear: PVisualGear; Steps: Longword); +procedure doStepAmmo(Gear: PVisualGear; Steps: Longword); +procedure doStepSmoke(Gear: PVisualGear; Steps: Longword); +procedure doStepDust(Gear: PVisualGear; Steps: Longword); +procedure doStepSplash(Gear: PVisualGear; Steps: Longword); +procedure doStepDroplet(Gear: PVisualGear; Steps: Longword); +procedure doStepSmokeRing(Gear: PVisualGear; Steps: Longword); +procedure doStepFeather(Gear: PVisualGear; Steps: Longword); +procedure doStepTeamHealthSorterWork(Gear: PVisualGear; Steps: Longword); +procedure doStepTeamHealthSorter(Gear: PVisualGear; Steps: Longword); +procedure doStepSpeechBubbleWork(Gear: PVisualGear; Steps: Longword); +procedure doStepSpeechBubble(Gear: PVisualGear; Steps: Longword); +procedure doStepHealthTagWork(Gear: PVisualGear; Steps: Longword); +procedure doStepHealthTagWorkUnderWater(Gear: PVisualGear; Steps: Longword); +procedure doStepHealthTag(Gear: PVisualGear; Steps: Longword); +procedure doStepSmokeTrace(Gear: PVisualGear; Steps: Longword); +procedure doStepExplosionWork(Gear: PVisualGear; Steps: Longword); +procedure doStepExplosion(Gear: PVisualGear; Steps: Longword); +procedure doStepBigExplosionWork(Gear: PVisualGear; Steps: Longword); +procedure doStepBigExplosion(Gear: PVisualGear; Steps: Longword); +procedure doStepChunk(Gear: PVisualGear; Steps: Longword); +procedure doStepBulletHit(Gear: PVisualGear; Steps: Longword); +procedure doStepCircle(Gear: PVisualGear; Steps: Longword); +procedure doStepSmoothWindBar(Gear: PVisualGear; Steps: Longword); +procedure doStepStraightShot(Gear: PVisualGear; Steps: Longword); + +procedure initModule; + +implementation +uses uVariables, Math, uConsts, uVisualGearsList, uFloat, uSound, uRenderUtils, uWorld; + +procedure doStepFlake(Gear: PVisualGear; Steps: Longword); +var sign: real; + moved: boolean; +begin +if vobCount = 0 then exit; + +sign:= 1; +with Gear^ do + begin + inc(FrameTicks, Steps); + if not SuddenDeathDmg and (FrameTicks > vobFrameTicks) then + begin + dec(FrameTicks, vobFrameTicks); + inc(Frame); + if Frame = vobFramesCount then + Frame:= 0 + end + else if SuddenDeathDmg and (FrameTicks > vobSDFrameTicks) then + begin + dec(FrameTicks, vobSDFrameTicks); + inc(Frame); + if Frame = vobSDFramesCount then + Frame:= 0 + end; + X:= X + (cWindSpeedf * 400 + dX + tdX) * Steps * Gear^.Scale; + if SuddenDeathDmg then + Y:= Y + (dY + tdY + cGravityf * vobSDFallSpeed) * Steps * Gear^.Scale + else + Y:= Y + (dY + tdY + cGravityf * vobFallSpeed) * Steps * Gear^.Scale; + Angle:= Angle + dAngle * Steps; + if Angle > 360 then + Angle:= Angle - 360 + else + if Angle < - 360 then + Angle:= Angle + 360; + + + if (round(X) >= cLeftScreenBorder) + and (round(X) <= cRightScreenBorder) + and (round(Y) - 75 <= LAND_HEIGHT) + and (Timer > 0) and (Timer-Steps > 0) then + begin + if tdX > 0 then + sign := 1 + else + sign:= -1; + tdX:= tdX - 0.005*Steps*sign; + if ((sign < 0) and (tdX > 0)) or ((sign > 0) and (tdX < 0)) then + tdX:= 0; + if tdX > 0 then + sign := 1 + else + sign:= -1; + tdY:= tdY - 0.005*Steps*sign; + if ((sign < 0) and (tdY > 0)) or ((sign > 0) and (tdY < 0)) then + tdY:= 0; + dec(Timer, Steps) + end + else + begin + moved:= false; + if round(X) < cLeftScreenBorder then + begin + X:= X + cScreenSpace; + moved:= true + end + else + if round(X) > cRightScreenBorder then + begin + X:= X - cScreenSpace; + moved:= true + end; + // if round(Y) < (LAND_HEIGHT - 1024 - 75) then Y:= Y + 25.0; // For if flag is set for flakes rising upwards? + if (Gear^.Layer = 2) and (round(Y) - 225 > LAND_HEIGHT) then + begin + X:= cLeftScreenBorder + random(cScreenSpace); + Y:= Y - (1024 + 250 + random(50)); // TODO - configure in theme (jellies for example could use limited range) + moved:= true + end + else if (Gear^.Layer <> 2) and (round(Y) + 50 > LAND_HEIGHT) then + begin + X:= cLeftScreenBorder + random(cScreenSpace); + Y:= Y - (1024 + random(25)); + moved:= true + end; + if moved then + begin + Angle:= random(360); + dx:= 0.0000038654705 * random(10000); + dy:= 0.000003506096 * random(7000); + if random(2) = 0 then dx := -dx + end; + Timer:= 0; + tdX:= 0; + tdY:= 0 + end; + end; + +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepBeeTrace(Gear: PVisualGear; Steps: Longword); +begin +if Gear^.FrameTicks > Steps then + dec(Gear^.FrameTicks, Steps) +else + DeleteVisualGear(Gear); +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepCloud(Gear: PVisualGear; Steps: Longword); +var s: Longword; + t: real; +begin +Gear^.X:= Gear^.X + (cWindSpeedf * 750 * Gear^.dX * Gear^.Scale) * Steps; + +// up-and-down-bounce magic +s := (GameTicks + Gear^.Timer) mod 4096; +t := 8 * Gear^.Scale * hwFloat2Float(AngleSin(s mod 2048)); +if (s < 2048) then t := -t; + +Gear^.Y := LAND_HEIGHT - 1184 + LongInt(Gear^.Timer mod 8) + t; + +if round(Gear^.X) < cLeftScreenBorder then + Gear^.X:= Gear^.X + cScreenSpace +else + if round(Gear^.X) > cRightScreenBorder then + Gear^.X:= Gear^.X - cScreenSpace +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepExpl(Gear: PVisualGear; Steps: Longword); +var s: LongInt; +begin +s:= min(Steps, cExplFrameTicks); + +Gear^.X:= Gear^.X + Gear^.dX * s; +Gear^.Y:= Gear^.Y + Gear^.dY * s; +//Gear^.dY:= Gear^.dY + cGravityf; + +if Gear^.FrameTicks <= Steps then + if Gear^.Frame = 0 then + DeleteVisualGear(Gear) + else + begin + dec(Gear^.Frame); + Gear^.FrameTicks:= cExplFrameTicks + end + else dec(Gear^.FrameTicks, Steps) +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepNote(Gear: PVisualGear; Steps: Longword); +begin +Gear^.X:= Gear^.X + Gear^.dX * Steps; + +Gear^.Y:= Gear^.Y + Gear^.dY * Steps; +Gear^.dY:= Gear^.dY + cGravityf * Steps / 2; + +Gear^.Angle:= Gear^.Angle + (Gear^.Frame + 1) * Steps / 10; +while Gear^.Angle > cMaxAngle do + Gear^.Angle:= Gear^.Angle - cMaxAngle; + +if Gear^.FrameTicks <= Steps then + DeleteVisualGear(Gear) +else + dec(Gear^.FrameTicks, Steps) +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepLineTrail(Gear: PVisualGear; Steps: Longword); +begin +Steps := Steps; +if Gear^.Timer <= Steps then + DeleteVisualGear(Gear) +else + dec(Gear^.Timer, Steps) +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepEgg(Gear: PVisualGear; Steps: Longword); +begin +Gear^.X:= Gear^.X + Gear^.dX * Steps; + +Gear^.Y:= Gear^.Y + Gear^.dY * Steps; +Gear^.dY:= Gear^.dY + cGravityf * Steps; + +Gear^.Angle:= round(Gear^.Angle + Steps) mod cMaxAngle; + +if Gear^.FrameTicks <= Steps then + begin + DeleteVisualGear(Gear); + exit + end +else + dec(Gear^.FrameTicks, Steps); + +if Gear^.FrameTicks < $FF then + Gear^.Tint:= (Gear^.Tint and $FFFFFF00) or Gear^.FrameTicks +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepFire(Gear: PVisualGear; Steps: Longword); +var vgt: PVisualGear; +begin +Gear^.X:= Gear^.X + Gear^.dX * Steps; + +Gear^.Y:= Gear^.Y + Gear^.dY * Steps;// + cGravityf * (Steps * Steps); +if (Gear^.State and gstTmpFlag) = 0 then + begin + Gear^.dY:= Gear^.dY + cGravityf * Steps; + if ((GameTicks mod 200) < Steps + 1) then + begin + vgt:= AddVisualGear(round(Gear^.X), round(Gear^.Y), vgtFire); + if vgt <> nil then + begin + vgt^.dx:= 0; + vgt^.dy:= 0; + vgt^.State:= gstTmpFlag; + end; + end + end +else + inc(Steps, Steps); + +if Gear^.FrameTicks <= Steps then + DeleteVisualGear(Gear) +else + dec(Gear^.FrameTicks, Steps) +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepShell(Gear: PVisualGear; Steps: Longword); +begin +Gear^.X:= Gear^.X + Gear^.dX * Steps; + +Gear^.Y:= Gear^.Y + Gear^.dY * Steps; +Gear^.dY:= Gear^.dY + cGravityf * Steps; + +Gear^.Angle:= round(Gear^.Angle + Steps) mod cMaxAngle; + +if Gear^.FrameTicks <= Steps then + DeleteVisualGear(Gear) +else + dec(Gear^.FrameTicks, Steps) +end; + +procedure doStepSmallDamage(Gear: PVisualGear; Steps: Longword); +begin +Gear^.Y:= Gear^.Y - 0.02 * Steps; + +if Gear^.FrameTicks <= Steps then + DeleteVisualGear(Gear) +else + dec(Gear^.FrameTicks, Steps) +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepBubble(Gear: PVisualGear; Steps: Longword); +begin +Gear^.X:= Gear^.X + Gear^.dX * Steps; +Gear^.Y:= Gear^.Y + Gear^.dY * Steps; +Gear^.Y:= Gear^.Y - cDrownSpeedf * Steps; +Gear^.dX := Gear^.dX / (1.001 * Steps); +Gear^.dY := Gear^.dY / (1.001 * Steps); + +if (Gear^.FrameTicks <= Steps) or (round(Gear^.Y) < cWaterLine) then + DeleteVisualGear(Gear) +else + dec(Gear^.FrameTicks, Steps) +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepSteam(Gear: PVisualGear; Steps: Longword); +begin +Gear^.X:= Gear^.X + (cWindSpeedf * 100 + Gear^.dX) * Steps; +Gear^.Y:= Gear^.Y - cDrownSpeedf * Steps; + +if Gear^.FrameTicks <= Steps then + if Gear^.Frame = 0 then + DeleteVisualGear(Gear) + else + begin + if Random(2) = 0 then + dec(Gear^.Frame); + Gear^.FrameTicks:= cExplFrameTicks + end +else dec(Gear^.FrameTicks, Steps) +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepAmmo(Gear: PVisualGear; Steps: Longword); +begin +Gear^.Y:= Gear^.Y - cDrownSpeedf * Steps; + +Gear^.scale:= Gear^.scale + 0.0025 * Steps; +Gear^.alpha:= Gear^.alpha - 0.0015 * Steps; + +if Gear^.alpha < 0 then + DeleteVisualGear(Gear) +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepSmoke(Gear: PVisualGear; Steps: Longword); +begin +Gear^.X:= Gear^.X + (cWindSpeedf + Gear^.dX) * Steps; +Gear^.Y:= Gear^.Y - (cDrownSpeedf + Gear^.dY) * Steps; + +Gear^.dX := Gear^.dX + (cWindSpeedf * 0.3 * Steps); +//Gear^.dY := Gear^.dY - (cDrownSpeedf * 0.995); + +if Gear^.FrameTicks <= Steps then + if Gear^.Frame = 0 then + DeleteVisualGear(Gear) + else + begin + if Random(2) = 0 then + dec(Gear^.Frame); + Gear^.FrameTicks:= cExplFrameTicks + end + else dec(Gear^.FrameTicks, Steps) +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepDust(Gear: PVisualGear; Steps: Longword); +begin +Gear^.X:= Gear^.X + (cWindSpeedf + (cWindSpeedf * 0.03 * Steps) + Gear^.dX) * Steps; +Gear^.Y:= Gear^.Y - (Gear^.dY) * Steps; + +Gear^.dX := Gear^.dX - (Gear^.dX * 0.005 * Steps); +Gear^.dY := Gear^.dY - (cDrownSpeedf * 0.001 * Steps); + +if Gear^.FrameTicks <= Steps then + if Gear^.Frame = 0 then + DeleteVisualGear(Gear) + else + begin + dec(Gear^.Frame); + Gear^.FrameTicks:= cExplFrameTicks + end + else dec(Gear^.FrameTicks, Steps) +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepSplash(Gear: PVisualGear; Steps: Longword); +begin +if Gear^.FrameTicks <= Steps then + DeleteVisualGear(Gear) +else + dec(Gear^.FrameTicks, Steps); +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepDroplet(Gear: PVisualGear; Steps: Longword); +begin +Gear^.X:= Gear^.X + Gear^.dX * Steps; + +Gear^.Y:= Gear^.Y + Gear^.dY * Steps; +Gear^.dY:= Gear^.dY + cGravityf * Steps; + +if round(Gear^.Y) > cWaterLine then + begin + DeleteVisualGear(Gear); + PlaySound(TSound(ord(sndDroplet1) + Random(3))); + end; +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepSmokeRing(Gear: PVisualGear; Steps: Longword); +begin +inc(Gear^.Timer, Steps); +if Gear^.Timer >= Gear^.FrameTicks then + DeleteVisualGear(Gear) +else + begin + Gear^.scale := 1.25 * (-power(2, -10 * Int(Gear^.Timer)/Gear^.FrameTicks) + 1) + 0.4; + Gear^.alpha := 1 - power(Gear^.Timer / 350, 4); + if Gear^.alpha < 0 then + Gear^.alpha:= 0; + end; +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepFeather(Gear: PVisualGear; Steps: Longword); +begin +Gear^.X:= Gear^.X + Gear^.dX * Steps; + +Gear^.Y:= Gear^.Y + Gear^.dY * Steps; +Gear^.dY:= Gear^.dY + cGravityf * Steps; + +Gear^.Angle:= round(Gear^.Angle + Steps) mod cMaxAngle; + +if Gear^.FrameTicks <= Steps then + DeleteVisualGear(Gear) +else + dec(Gear^.FrameTicks, Steps) +end; + +//////////////////////////////////////////////////////////////////////////////// +const cSorterWorkTime = 640; +var thexchar: array[0..cMaxTeams] of + record + dy, ny, dw: LongInt; + team: PTeam; + SortFactor: QWord; + end; + currsorter: PVisualGear = nil; + +procedure doStepTeamHealthSorterWork(Gear: PVisualGear; Steps: Longword); +var i, t: LongInt; +begin +for t:= 1 to min(Steps, Gear^.Timer) do + begin + dec(Gear^.Timer); + if (Gear^.Timer and 15) = 0 then + for i:= 0 to Pred(TeamsCount) do + with thexchar[i] do + begin + {$WARNINGS OFF} + team^.DrawHealthY:= ny + dy * LongInt(Gear^.Timer) div cSorterWorkTime; + team^.TeamHealthBarWidth:= team^.NewTeamHealthBarWidth + dw * LongInt(Gear^.Timer) div cSorterWorkTime; + {$WARNINGS ON} + end; + end; + +if (Gear^.Timer = 0) or (currsorter <> Gear) then + begin + if currsorter = Gear then + currsorter:= nil; + DeleteVisualGear(Gear); + exit + end +end; + +procedure doStepTeamHealthSorter(Gear: PVisualGear; Steps: Longword); +var i: Longword; + b: boolean; + t: LongInt; +begin +Steps:= Steps; // avoid compiler hint + +for t:= 0 to Pred(TeamsCount) do + with thexchar[t] do + begin + team:= TeamsArray[t]; + dy:= team^.DrawHealthY; + dw:= team^.TeamHealthBarWidth - team^.NewTeamHealthBarWidth; + if team^.TeamHealth > 0 then + begin + SortFactor:= team^.Clan^.ClanHealth; + SortFactor:= (SortFactor shl 3) + team^.Clan^.ClanIndex; + SortFactor:= (SortFactor shl 30) + team^.TeamHealth; + end + else + SortFactor:= 0; + end; + +if TeamsCount > 1 then + repeat + b:= true; + for t:= 0 to TeamsCount - 2 do + if (thexchar[t].SortFactor > thexchar[Succ(t)].SortFactor) then + begin + thexchar[cMaxTeams]:= thexchar[t]; + thexchar[t]:= thexchar[Succ(t)]; + thexchar[Succ(t)]:= thexchar[cMaxTeams]; + b:= false + end + until b; + +t:= - 4; +for i:= 0 to Pred(TeamsCount) do + with thexchar[i] do + if team^.TeamHealth > 0 then + begin + dec(t, team^.HealthTex^.h + 2); + ny:= t; + dy:= dy - ny + end; + +Gear^.Timer:= cSorterWorkTime; +Gear^.doStep:= @doStepTeamHealthSorterWork; +currsorter:= Gear; +//doStepTeamHealthSorterWork(Gear, Steps) +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepSpeechBubbleWork(Gear: PVisualGear; Steps: Longword); +begin +if Gear^.Timer > Steps then dec(Gear^.Timer, Steps) else Gear^.Timer:= 0; + +if (Gear^.Hedgehog^.Gear <> nil) then + begin + Gear^.X:= hwFloat2Float(Gear^.Hedgehog^.Gear^.X) + (Gear^.Tex^.w div 2 - Gear^.FrameTicks); + Gear^.Y:= hwFloat2Float(Gear^.Hedgehog^.Gear^.Y) - (16 + Gear^.Tex^.h); + end; + +if Gear^.Timer = 0 then + begin + if Gear^.Hedgehog^.SpeechGear = Gear then + Gear^.Hedgehog^.SpeechGear:= nil; + DeleteVisualGear(Gear) + end; +end; + +procedure doStepSpeechBubble(Gear: PVisualGear; Steps: Longword); +begin +Steps:= Steps; // avoid compiler hint + +with Gear^.Hedgehog^ do + if SpeechGear <> nil then + SpeechGear^.Timer:= 0; + +Gear^.Hedgehog^.SpeechGear:= Gear; + +Gear^.Timer:= max(LongInt(Length(Gear^.Text)) * 150, 3000); + +Gear^.Tex:= RenderSpeechBubbleTex(Gear^.Text, Gear^.FrameTicks, fnt16); + +case Gear^.FrameTicks of + 1: Gear^.FrameTicks:= SpritesData[sprSpeechTail].Width-28; + 2: Gear^.FrameTicks:= SpritesData[sprThoughtTail].Width-20; + 3: Gear^.FrameTicks:= SpritesData[sprShoutTail].Width-10; + end; + +Gear^.doStep:= @doStepSpeechBubbleWork; + +Gear^.Y:= Gear^.Y - Gear^.Tex^.h +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepHealthTagWork(Gear: PVisualGear; Steps: Longword); +begin +if Steps > Gear^.Timer then + DeleteVisualGear(Gear) +else + begin + dec(Gear^.Timer, Steps); + Gear^.Y:= Gear^.Y + Gear^.dY * Steps; + Gear^.X:= Gear^.X + Gear^.dX * Steps + end; +end; + +procedure doStepHealthTagWorkUnderWater(Gear: PVisualGear; Steps: Longword); +begin +if round(Gear^.Y) - 10 < cWaterLine then + DeleteVisualGear(Gear) +else + Gear^.Y:= Gear^.Y - 0.08 * Steps; + +end; + +procedure doStepHealthTag(Gear: PVisualGear; Steps: Longword); +var s: shortstring; +begin +s:= ''; + +str(Gear^.State, s); +if Gear^.Hedgehog <> nil then + Gear^.Tex:= RenderStringTex(s, Gear^.Hedgehog^.Team^.Clan^.Color, fnt16) +else + Gear^.Tex:= RenderStringTex(s, cWhiteColor, fnt16); + +Gear^.doStep:= @doStepHealthTagWork; + +if (round(Gear^.Y) > cWaterLine) and (Gear^.Frame = 0) then + Gear^.doStep:= @doStepHealthTagWorkUnderWater; + +Gear^.Y:= Gear^.Y - Gear^.Tex^.h; + +if Steps > 1 then + Gear^.doStep(Gear, Steps-1); +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepSmokeTrace(Gear: PVisualGear; Steps: Longword); +begin +inc(Gear^.Timer, Steps ); +if Gear^.Timer > 64 then + begin + if Gear^.State = 0 then + begin + DeleteVisualGear(Gear); + exit; + end; + dec(Gear^.State, Gear^.Timer div 65); + Gear^.Timer:= Gear^.Timer mod 65; + end; +Gear^.dX:= Gear^.dX + cWindSpeedf * Steps; +Gear^.X:= Gear^.X + Gear^.dX; +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepExplosionWork(Gear: PVisualGear; Steps: Longword); +begin +inc(Gear^.Timer, Steps); +if Gear^.Timer > 75 then + begin + inc(Gear^.State, Gear^.Timer div 76); + Gear^.Timer:= Gear^.Timer mod 76; + if Gear^.State > 5 then + DeleteVisualGear(Gear); + end; +end; + +procedure doStepExplosion(Gear: PVisualGear; Steps: Longword); +var i: LongWord; + gX,gY: LongInt; + vg: PVisualGear; +begin +gX:= round(Gear^.X); +gY:= round(Gear^.Y); +for i:= 0 to 31 do + begin + vg:= AddVisualGear(gX, gY, vgtFire); + if vg <> nil then + begin + vg^.State:= gstTmpFlag; + inc(vg^.FrameTicks, vg^.FrameTicks) + end + end; +for i:= 0 to 8 do AddVisualGear(gX, gY, vgtExplPart); +for i:= 0 to 8 do AddVisualGear(gX, gY, vgtExplPart2); +Gear^.doStep:= @doStepExplosionWork; +if Steps > 1 then + Gear^.doStep(Gear, Steps-1); +end; + + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepBigExplosionWork(Gear: PVisualGear; Steps: Longword); +var maxMovement: LongInt; +begin + +inc(Gear^.Timer, Steps); +if (Gear^.Timer and 5) = 0 then + begin + maxMovement := max(1, 13 - ((Gear^.Timer * 15) div 250)); + ShakeCamera(maxMovement); + end; + +if Gear^.Timer > 250 then + DeleteVisualGear(Gear); +end; + +procedure doStepBigExplosion(Gear: PVisualGear; Steps: Longword); +var i: LongWord; + gX,gY: LongInt; + vg: PVisualGear; +begin +//ScreenFade:= sfFromWhite; +//ScreenFadeValue:= round(60 * zoom * zoom); +//ScreenFadeSpeed:= 5; +gX:= round(Gear^.X); +gY:= round(Gear^.Y); +AddVisualGear(gX, gY, vgtSmokeRing); +for i:= 0 to 46 do + begin + vg:= AddVisualGear(gX, gY, vgtFire); + if vg <> nil then + begin + vg^.State:= gstTmpFlag; + inc(vg^.FrameTicks, vg^.FrameTicks) + end + end; +for i:= 0 to 15 do + AddVisualGear(gX, gY, vgtExplPart); +for i:= 0 to 15 do + AddVisualGear(gX, gY, vgtExplPart2); +Gear^.doStep:= @doStepBigExplosionWork; +if Steps > 1 then + Gear^.doStep(Gear, Steps-1); +with mobileRecord do + if (performRumble <> nil) and (not fastUntilLag) then + performRumble(kSystemSoundID_Vibrate); +end; + +procedure doStepChunk(Gear: PVisualGear; Steps: Longword); +begin +Gear^.X:= Gear^.X + Gear^.dX * Steps; + +Gear^.Y:= Gear^.Y + Gear^.dY * Steps; +Gear^.dY:= Gear^.dY + cGravityf * Steps; + +Gear^.Angle:= round(Gear^.Angle + Steps) mod cMaxAngle; + +if (round(Gear^.Y) > cWaterLine) and ((cReducedQuality and rqPlainSplash) = 0) then + begin + AddVisualGear(round(Gear^.X), round(Gear^.Y), vgtDroplet); + DeleteVisualGear(Gear); + end +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepBulletHit(Gear: PVisualGear; Steps: Longword); +begin +if Gear^.FrameTicks <= Steps then + DeleteVisualGear(Gear) +else + dec(Gear^.FrameTicks, Steps); +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepCircle(Gear: PVisualGear; Steps: Longword); +var tmp: LongInt; + i: LongWord; +begin +with Gear^ do + if Frame <> 0 then + for i:= 1 to Steps do + begin + inc(FrameTicks); + if (FrameTicks mod Frame) = 0 then + begin + tmp:= Gear^.Tint and $FF; + if tdY >= 0 then + inc(tmp) + else + dec(tmp); + if tmp < round(dX) then + tdY:= 1; + if tmp > round(dY) then + tdY:= -1; + if tmp > 255 then + tmp := 255; + if tmp < 0 then + tmp := 0; + Gear^.Tint:= (Gear^.Tint and $FFFFFF00) or Longword(tmp) + end + end +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepSmoothWindBar(Gear: PVisualGear; Steps: Longword); +begin +inc(Gear^.Timer, Steps); + +while Gear^.Timer >= 10 do + begin + dec(Gear^.Timer, 10); + if WindBarWidth < Gear^.Tag then + inc(WindBarWidth) + else if WindBarWidth > Gear^.Tag then + dec(WindBarWidth); + end; +if cWindspeedf > Gear^.dAngle then + begin + cWindspeedf := cWindspeedf - Gear^.Angle*Steps; + if cWindspeedf < Gear^.dAngle then cWindspeedf:= Gear^.dAngle; + end +else if cWindspeedf < Gear^.dAngle then + begin + cWindspeedf := cWindspeedf + Gear^.Angle*Steps; + if cWindspeedf > Gear^.dAngle then cWindspeedf:= Gear^.dAngle; + end; + +if (WindBarWidth = Gear^.Tag) and (cWindspeedf = Gear^.dAngle) then + DeleteVisualGear(Gear) +end; +//////////////////////////////////////////////////////////////////////////////// +procedure doStepStraightShot(Gear: PVisualGear; Steps: Longword); +begin +Gear^.X:= Gear^.X + Gear^.dX * Steps; +Gear^.Y:= Gear^.Y - Gear^.dY * Steps; + +if Gear^.FrameTicks <= Steps then + DeleteVisualGear(Gear) +else + begin + dec(Gear^.FrameTicks, Steps); + if (Gear^.FrameTicks < 501) and (Gear^.FrameTicks mod 5 = 0) then + Gear^.Tint:= (Gear^.Tint and $FFFFFF00) or (((Gear^.Tint and $000000FF) * Gear^.FrameTicks) div 500) + end +end; + + +const handlers: array[TVisualGearType] of TVGearStepProcedure = + ( + @doStepFlake, + @doStepCloud, + @doStepExpl, + @doStepExpl, + @doStepFire, + @doStepSmallDamage, + @doStepTeamHealthSorter, + @doStepSpeechBubble, + @doStepBubble, + @doStepSteam, + @doStepAmmo, + @doStepSmoke, + @doStepSmoke, + @doStepShell, + @doStepDust, + @doStepSplash, + @doStepDroplet, + @doStepSmokeRing, + @doStepBeeTrace, + @doStepEgg, + @doStepFeather, + @doStepHealthTag, + @doStepSmokeTrace, + @doStepSmokeTrace, + @doStepExplosion, + @doStepBigExplosion, + @doStepChunk, + @doStepNote, + @doStepLineTrail, + @doStepBulletHit, + @doStepCircle, + @doStepSmoothWindBar, + @doStepStraightShot + ); + +procedure initModule; +begin + doStepHandlers:= handlers +end; + +end.