diff -r 92af50454cf2 -r 8054d9d775fd hedgewars/uVisualGears.pas --- a/hedgewars/uVisualGears.pas Fri Oct 11 11:55:31 2013 +0200 +++ b/hedgewars/uVisualGears.pas Fri Oct 11 17:43:13 2013 +0200 @@ -29,19 +29,13 @@ * E.g.: background flakes, visual effects: explosion, smoke trails, etc. *) interface -uses uConsts, uFloat, GLunit, uTypes, uWorld; +uses uConsts, GLunit, uTypes; 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 uVariables, uRender, Math, uRenderUtils, uStore, uUtils + , uVisualGearsList; procedure AddDamageTag(X, Y, Damage, Color: LongWord); var s: shortstring; @@ -84,436 +69,6 @@ // ================================================================== -// ================================================================== -const vdoStepHandlers: 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:= vdoStepHandlers[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