31 * |
31 * |
32 * Note: Gears that do not have an effect on the game but are just visual |
32 * Note: Gears that do not have an effect on the game but are just visual |
33 * effects are called "Visual Gears" and defined in the respective unit! |
33 * effects are called "Visual Gears" and defined in the respective unit! |
34 *) |
34 *) |
35 interface |
35 interface |
36 uses SDLh, uConsts, uFloat, uTypes; |
36 uses uConsts, uFloat, uTypes; |
37 |
37 |
38 procedure initModule; |
38 procedure initModule; |
39 procedure freeModule; |
39 procedure freeModule; |
40 function SpawnCustomCrateAt(x, y: LongInt; crate: TCrateType; content, cnt: Longword): PGear; |
40 function SpawnCustomCrateAt(x, y: LongInt; crate: TCrateType; content, cnt: Longword): PGear; |
41 function SpawnFakeCrateAt(x, y: LongInt; crate: TCrateType; explode: boolean; poison: boolean ): PGear; |
41 function SpawnFakeCrateAt(x, y: LongInt; crate: TCrateType; explode: boolean; poison: boolean ): PGear; |
42 function GetAmmo(Hedgehog: PHedgehog): TAmmoType; |
|
43 function GetUtility(Hedgehog: PHedgehog): TAmmoType; |
|
44 procedure HideHog(HH: PHedgehog); |
|
45 procedure ProcessGears; |
42 procedure ProcessGears; |
46 procedure EndTurnCleanup; |
43 procedure EndTurnCleanup; |
47 procedure SetAllToActive; |
|
48 procedure SetAllHHToActive; inline; |
|
49 procedure SetAllHHToActive(Ice: boolean); |
|
50 procedure DrawGears; |
44 procedure DrawGears; |
51 procedure FreeGearsList; |
45 procedure FreeGearsList; |
52 procedure AddMiscGears; |
46 procedure AddMiscGears; |
53 procedure AssignHHCoords; |
47 procedure AssignHHCoords; |
54 function GearByUID(uid : Longword) : PGear; |
48 function GearByUID(uid : Longword) : PGear; |
55 procedure doStepDrowningGear(Gear: PGear); |
|
56 |
|
57 |
49 |
58 implementation |
50 implementation |
59 uses uStore, uSound, uTeams, uRandom, uCollisions, uIO, uLandGraphics, {$IFDEF SDL13}uTouch,{$ENDIF} |
51 uses uStore, uSound, uTeams, uRandom, uIO, uLandGraphics, {$IFDEF SDL13}uTouch,{$ENDIF} |
60 uLocale, uAI, uAmmos, uStats, uVisualGears, uScript, GLunit, uVariables, |
52 uLocale, uAI, uAmmos, uStats, uVisualGears, uScript, GLunit, uVariables, |
61 uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uLandTexture, |
53 uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uLandTexture, |
62 uGearsHedgehog, uGearsUtils, uGearsList, uGearsHandlers, uGearsHandlersRope; |
54 uGearsHedgehog, uGearsUtils, uGearsList, uGearsHandlersRope |
|
55 , uVisualGearsList, uGearsHandlersMess; |
63 |
56 |
64 var skipFlag: boolean; |
57 var skipFlag: boolean; |
65 |
|
66 procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt); forward; |
|
67 //procedure AmmoFlameWork(Ammo: PGear); forward; |
|
68 function GearsNear(X, Y: hwFloat; Kind: TGearType; r: LongInt): PGearArrayS; forward; |
|
69 procedure SpawnBoxOfSmth; forward; |
|
70 procedure ShotgunShot(Gear: PGear); forward; |
|
71 procedure doStepCase(Gear: PGear); forward; |
|
72 |
|
73 |
58 |
74 var delay: LongWord; |
59 var delay: LongWord; |
75 delay2: LongWord; |
60 delay2: LongWord; |
76 step: (stDelay, stChDmg, stSweep, stTurnReact, |
61 step: (stDelay, stChDmg, stSweep, stTurnReact, |
77 stAfterDelay, stChWin, stWater, stChWin2, stHealth, |
62 stAfterDelay, stChWin, stWater, stChWin2, stHealth, |
78 stSpawn, stNTurn); |
63 stSpawn, stNTurn); |
79 upd: Longword; |
|
80 snowLeft,snowRight: LongInt; |
|
81 NewTurnTick: LongWord; |
64 NewTurnTick: LongWord; |
82 //SDMusic: shortstring; |
65 //SDMusic: shortstring; |
83 |
|
84 // For better maintainability the step handlers of gears are stored in |
|
85 // separate files. |
|
86 // Note: step handlers of gears that are hedgehogs are in a different file |
|
87 // than the handlers for all other gears. |
|
88 {$INCLUDE "GSHandlers.inc"} |
|
89 |
66 |
90 function CheckNoDamage: boolean; // returns TRUE in case of no damaged hhs |
67 function CheckNoDamage: boolean; // returns TRUE in case of no damaged hhs |
91 var Gear: PGear; |
68 var Gear: PGear; |
92 dmg: LongInt; |
69 dmg: LongInt; |
93 begin |
70 begin |
673 snowLeft:= -(snowRight-LAND_WIDTH); |
617 snowLeft:= -(snowRight-LAND_WIDTH); |
674 |
618 |
675 if (not hasBorder) and ((Theme = 'Snow') or (Theme = 'Christmas')) then |
619 if (not hasBorder) and ((Theme = 'Snow') or (Theme = 'Christmas')) then |
676 for i:= vobCount * Longword(max(LAND_WIDTH,4096)) div 2048 downto 1 do |
620 for i:= vobCount * Longword(max(LAND_WIDTH,4096)) div 2048 downto 1 do |
677 AddGear(LongInt(GetRandom(snowRight - snowLeft)) + snowLeft, LAND_HEIGHT + LongInt(GetRandom(750)) - 1300, gtFlake, 0, _0, _0, 0); |
621 AddGear(LongInt(GetRandom(snowRight - snowLeft)) + snowLeft, LAND_HEIGHT + LongInt(GetRandom(750)) - 1300, gtFlake, 0, _0, _0, 0); |
678 end; |
|
679 |
|
680 |
|
681 procedure ShotgunShot(Gear: PGear); |
|
682 var t: PGear; |
|
683 dmg, r, dist: LongInt; |
|
684 dx, dy: hwFloat; |
|
685 begin |
|
686 Gear^.Radius:= cShotgunRadius; |
|
687 t:= GearsList; |
|
688 while t <> nil do |
|
689 begin |
|
690 case t^.Kind of |
|
691 gtHedgehog, |
|
692 gtMine, |
|
693 gtSMine, |
|
694 gtKnife, |
|
695 gtCase, |
|
696 gtTarget, |
|
697 gtExplosives: begin//, |
|
698 // gtStructure: begin |
|
699 //addFileLog('ShotgunShot radius: ' + inttostr(Gear^.Radius) + ', t^.Radius = ' + inttostr(t^.Radius) + ', distance = ' + inttostr(dist) + ', dmg = ' + inttostr(dmg)); |
|
700 dmg:= 0; |
|
701 r:= Gear^.Radius + t^.Radius; |
|
702 dx:= Gear^.X-t^.X; |
|
703 dx.isNegative:= false; |
|
704 dy:= Gear^.Y-t^.Y; |
|
705 dy.isNegative:= false; |
|
706 if r-hwRound(dx+dy) > 0 then |
|
707 begin |
|
708 dist:= hwRound(Distance(dx, dy)); |
|
709 dmg:= ModifyDamage(min(r - dist, 25), t); |
|
710 end; |
|
711 if dmg > 0 then |
|
712 begin |
|
713 if (not t^.Invulnerable) then |
|
714 ApplyDamage(t, Gear^.Hedgehog, dmg, dsBullet) |
|
715 else |
|
716 Gear^.State:= Gear^.State or gstWinner; |
|
717 |
|
718 DeleteCI(t); |
|
719 t^.dX:= t^.dX + Gear^.dX * dmg * _0_01 + SignAs(cHHKick, Gear^.dX); |
|
720 t^.dY:= t^.dY + Gear^.dY * dmg * _0_01; |
|
721 t^.State:= t^.State or gstMoving; |
|
722 if t^.Kind = gtKnife then t^.State:= t^.State and (not gstCollision); |
|
723 t^.Active:= true; |
|
724 FollowGear:= t |
|
725 end |
|
726 end; |
|
727 gtGrave: begin |
|
728 dmg:= 0; |
|
729 r:= Gear^.Radius + t^.Radius; |
|
730 dx:= Gear^.X-t^.X; |
|
731 dx.isNegative:= false; |
|
732 dy:= Gear^.Y-t^.Y; |
|
733 dy.isNegative:= false; |
|
734 if r-hwRound(dx+dy) > 0 then |
|
735 begin |
|
736 dist:= hwRound(Distance(dx, dy)); |
|
737 dmg:= ModifyDamage(min(r - dist, 25), t); |
|
738 end; |
|
739 if dmg > 0 then |
|
740 begin |
|
741 t^.dY:= - _0_1; |
|
742 t^.Active:= true |
|
743 end |
|
744 end; |
|
745 end; |
|
746 t:= t^.NextGear |
|
747 end; |
|
748 if (GameFlags and gfSolidLand) = 0 then |
|
749 DrawExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), cShotgunRadius) |
|
750 end; |
|
751 |
|
752 procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt); |
|
753 var t: PGearArray; |
|
754 Gear: PGear; |
|
755 i, j, tmpDmg: LongInt; |
|
756 VGear: PVisualGear; |
|
757 begin |
|
758 t:= CheckGearsCollision(Ammo); |
|
759 // Just to avoid hogs on rope dodging fire. |
|
760 if (CurAmmoGear <> nil) and ((CurAmmoGear^.Kind = gtRope) or (CurAmmoGear^.Kind = gtJetpack) or (CurAmmoGear^.Kind = gtBirdy)) |
|
761 and (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.Gear^.CollisionIndex = -1) |
|
762 and (sqr(hwRound(Ammo^.X) - hwRound(CurrentHedgehog^.Gear^.X)) + sqr(hwRound(Ammo^.Y) - hwRound(CurrentHedgehog^.Gear^.Y)) <= sqr(cHHRadius + Ammo^.Radius)) then |
|
763 begin |
|
764 t^.ar[t^.Count]:= CurrentHedgehog^.Gear; |
|
765 inc(t^.Count) |
|
766 end; |
|
767 |
|
768 i:= t^.Count; |
|
769 |
|
770 if (Ammo^.Kind = gtFlame) and (i > 0) then |
|
771 Ammo^.Health:= 0; |
|
772 while i > 0 do |
|
773 begin |
|
774 dec(i); |
|
775 Gear:= t^.ar[i]; |
|
776 if ((Ammo^.Kind = gtFlame) or (Ammo^.Kind = gtBlowTorch)) and |
|
777 (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.Effects[heFrozen] > 255) then |
|
778 Gear^.Hedgehog^.Effects[heFrozen]:= max(255,Gear^.Hedgehog^.Effects[heFrozen]-10000); |
|
779 tmpDmg:= ModifyDamage(Damage, Gear); |
|
780 if (Gear^.State and gstNoDamage) = 0 then |
|
781 begin |
|
782 |
|
783 if (Ammo^.Kind = gtDEagleShot) or (Ammo^.Kind = gtSniperRifleShot) then |
|
784 begin |
|
785 VGear := AddVisualGear(hwround(Ammo^.X), hwround(Ammo^.Y), vgtBulletHit); |
|
786 if VGear <> nil then |
|
787 VGear^.Angle := DxDy2Angle(-Ammo^.dX, Ammo^.dY); |
|
788 end; |
|
789 |
|
790 if (Gear^.Kind = gtHedgehog) and (Ammo^.State and gsttmpFlag <> 0) and (Ammo^.Kind = gtShover) then |
|
791 Gear^.FlightTime:= 1; |
|
792 |
|
793 |
|
794 case Gear^.Kind of |
|
795 gtHedgehog, |
|
796 gtMine, |
|
797 gtSMine, |
|
798 gtKnife, |
|
799 gtTarget, |
|
800 gtCase, |
|
801 gtExplosives: //, |
|
802 //gtStructure: |
|
803 begin |
|
804 if (Ammo^.Kind = gtDrill) then |
|
805 begin |
|
806 Ammo^.Timer:= 0; |
|
807 exit; |
|
808 end; |
|
809 if (not Gear^.Invulnerable) then |
|
810 begin |
|
811 if (Ammo^.Kind = gtKnife) and (tmpDmg > 0) then |
|
812 for j:= 1 to max(1,min(3,tmpDmg div 5)) do |
|
813 begin |
|
814 VGear:= AddVisualGear(hwRound(Ammo^.X-((Ammo^.X-Gear^.X)/_2)), hwRound(Ammo^.Y-((Ammo^.Y-Gear^.Y)/_2)), vgtStraightShot); |
|
815 if VGear <> nil then |
|
816 with VGear^ do |
|
817 begin |
|
818 Tint:= $FFCC00FF; |
|
819 Angle:= random(360); |
|
820 dx:= 0.0005 * (random(100)); |
|
821 dy:= 0.0005 * (random(100)); |
|
822 if random(2) = 0 then |
|
823 dx := -dx; |
|
824 if random(2) = 0 then |
|
825 dy := -dy; |
|
826 FrameTicks:= 600+random(200); |
|
827 State:= ord(sprStar) |
|
828 end |
|
829 end; |
|
830 ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg, dsShove) |
|
831 end |
|
832 else |
|
833 Gear^.State:= Gear^.State or gstWinner; |
|
834 if (Gear^.Kind = gtExplosives) and (Ammo^.Kind = gtBlowtorch) then |
|
835 begin |
|
836 if (Ammo^.Hedgehog^.Gear <> nil) then |
|
837 Ammo^.Hedgehog^.Gear^.State:= Ammo^.Hedgehog^.Gear^.State and (not gstNotKickable); |
|
838 ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg * 100, dsUnknown); // crank up damage for explosives + blowtorch |
|
839 end; |
|
840 |
|
841 if (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.King or (Gear^.Hedgehog^.Effects[heFrozen] > 0)) then |
|
842 begin |
|
843 Gear^.dX:= Ammo^.dX * Power * _0_005; |
|
844 Gear^.dY:= Ammo^.dY * Power * _0_005 |
|
845 end |
|
846 else if ((Ammo^.Kind <> gtFlame) or (Gear^.Kind = gtHedgehog)) and (Power <> 0) then |
|
847 begin |
|
848 Gear^.dX:= Ammo^.dX * Power * _0_01; |
|
849 Gear^.dY:= Ammo^.dY * Power * _0_01 |
|
850 end; |
|
851 |
|
852 if (not isZero(Gear^.dX)) or (not isZero(Gear^.dY)) then |
|
853 begin |
|
854 Gear^.Active:= true; |
|
855 DeleteCI(Gear); |
|
856 Gear^.State:= Gear^.State or gstMoving; |
|
857 if Gear^.Kind = gtKnife then Gear^.State:= Gear^.State and (not gstCollision); |
|
858 // move the gear upwards a bit to throw it over tiny obstacles at start |
|
859 if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then |
|
860 begin |
|
861 if not (TestCollisionXwithXYShift(Gear, _0, -3, hwSign(Gear^.dX)) |
|
862 or (TestCollisionYwithGear(Gear, -1) <> 0)) then |
|
863 Gear^.Y:= Gear^.Y - _1; |
|
864 if not (TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) |
|
865 or (TestCollisionYwithGear(Gear, -1) <> 0)) then |
|
866 Gear^.Y:= Gear^.Y - _1; |
|
867 if not (TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)) |
|
868 or (TestCollisionYwithGear(Gear, -1) <> 0)) then |
|
869 Gear^.Y:= Gear^.Y - _1; |
|
870 end |
|
871 end; |
|
872 |
|
873 |
|
874 if (Ammo^.Kind <> gtFlame) or ((Ammo^.State and gsttmpFlag) = 0) then |
|
875 FollowGear:= Gear |
|
876 end; |
|
877 end |
|
878 end; |
|
879 end; |
|
880 if i <> 0 then |
|
881 SetAllToActive |
|
882 end; |
622 end; |
883 |
623 |
884 procedure AssignHHCoords; |
624 procedure AssignHHCoords; |
885 var i, t, p, j: LongInt; |
625 var i, t, p, j: LongInt; |
886 ar: array[0..Pred(cMaxHHs)] of PHedgehog; |
626 ar: array[0..Pred(cMaxHHs)] of PHedgehog; |
1075 |
775 |
1076 if ( (x = 0) and (y = 0) ) then |
776 if ( (x = 0) and (y = 0) ) then |
1077 FindPlace(FollowGear, true, 0, LAND_WIDTH); |
777 FindPlace(FollowGear, true, 0, LAND_WIDTH); |
1078 |
778 |
1079 SpawnFakeCrateAt := FollowGear; |
779 SpawnFakeCrateAt := FollowGear; |
1080 end; |
|
1081 |
|
1082 function GetAmmo(Hedgehog: PHedgehog): TAmmoType; |
|
1083 var t, aTot: LongInt; |
|
1084 i: TAmmoType; |
|
1085 begin |
|
1086 Hedgehog:= Hedgehog; // avoid hint |
|
1087 |
|
1088 aTot:= 0; |
|
1089 for i:= Low(TAmmoType) to High(TAmmoType) do |
|
1090 if (Ammoz[i].Ammo.Propz and ammoprop_Utility) = 0 then |
|
1091 inc(aTot, Ammoz[i].Probability); |
|
1092 |
|
1093 t:= aTot; |
|
1094 i:= Low(TAmmoType); |
|
1095 if (t > 0) then |
|
1096 begin |
|
1097 t:= GetRandom(t); |
|
1098 while t >= 0 do |
|
1099 begin |
|
1100 inc(i); |
|
1101 if (Ammoz[i].Ammo.Propz and ammoprop_Utility) = 0 then |
|
1102 dec(t, Ammoz[i].Probability) |
|
1103 end |
|
1104 end; |
|
1105 GetAmmo:= i |
|
1106 end; |
|
1107 |
|
1108 function GetUtility(Hedgehog: PHedgehog): TAmmoType; |
|
1109 var t, uTot: LongInt; |
|
1110 i: TAmmoType; |
|
1111 begin |
|
1112 |
|
1113 uTot:= 0; |
|
1114 for i:= Low(TAmmoType) to High(TAmmoType) do |
|
1115 if ((Ammoz[i].Ammo.Propz and ammoprop_Utility) <> 0) |
|
1116 and ((Hedgehog^.Team^.HedgehogsNumber > 1) or (Ammoz[i].Ammo.AmmoType <> amSwitch)) then |
|
1117 inc(uTot, Ammoz[i].Probability); |
|
1118 |
|
1119 t:= uTot; |
|
1120 i:= Low(TAmmoType); |
|
1121 if (t > 0) then |
|
1122 begin |
|
1123 t:= GetRandom(t); |
|
1124 while t >= 0 do |
|
1125 begin |
|
1126 inc(i); |
|
1127 if ((Ammoz[i].Ammo.Propz and ammoprop_Utility) <> 0) and ((Hedgehog^.Team^.HedgehogsNumber > 1) |
|
1128 or (Ammoz[i].Ammo.AmmoType <> amSwitch)) then |
|
1129 dec(t, Ammoz[i].Probability) |
|
1130 end |
|
1131 end; |
|
1132 GetUtility:= i |
|
1133 end; |
|
1134 |
|
1135 |
|
1136 |
|
1137 procedure SpawnBoxOfSmth; |
|
1138 var t, aTot, uTot, a, h: LongInt; |
|
1139 i: TAmmoType; |
|
1140 begin |
|
1141 if (PlacingHogs) or |
|
1142 (cCaseFactor = 0) |
|
1143 or (CountGears(gtCase) >= 5) |
|
1144 or (GetRandom(cCaseFactor) <> 0) then |
|
1145 exit; |
|
1146 |
|
1147 FollowGear:= nil; |
|
1148 aTot:= 0; |
|
1149 uTot:= 0; |
|
1150 for i:= Low(TAmmoType) to High(TAmmoType) do |
|
1151 if (Ammoz[i].Ammo.Propz and ammoprop_Utility) = 0 then |
|
1152 inc(aTot, Ammoz[i].Probability) |
|
1153 else |
|
1154 inc(uTot, Ammoz[i].Probability); |
|
1155 |
|
1156 t:=0; |
|
1157 a:=aTot; |
|
1158 h:= 1; |
|
1159 |
|
1160 if (aTot+uTot) <> 0 then |
|
1161 if ((GameFlags and gfInvulnerable) = 0) then |
|
1162 begin |
|
1163 h:= cHealthCaseProb * 100; |
|
1164 t:= GetRandom(10000); |
|
1165 a:= (10000-h)*aTot div (aTot+uTot) |
|
1166 end |
|
1167 else |
|
1168 begin |
|
1169 t:= GetRandom(aTot+uTot); |
|
1170 h:= 0 |
|
1171 end; |
|
1172 |
|
1173 |
|
1174 if t<h then |
|
1175 begin |
|
1176 FollowGear:= AddGear(0, 0, gtCase, 0, _0, _0, 0); |
|
1177 FollowGear^.Health:= cHealthCaseAmount; |
|
1178 FollowGear^.Pos:= posCaseHealth; |
|
1179 AddCaption(GetEventString(eidNewHealthPack), cWhiteColor, capgrpAmmoInfo); |
|
1180 end |
|
1181 else if (t<a+h) then |
|
1182 begin |
|
1183 t:= aTot; |
|
1184 if (t > 0) then |
|
1185 begin |
|
1186 FollowGear:= AddGear(0, 0, gtCase, 0, _0, _0, 0); |
|
1187 t:= GetRandom(t); |
|
1188 i:= Low(TAmmoType); |
|
1189 FollowGear^.Pos:= posCaseAmmo; |
|
1190 FollowGear^.AmmoType:= i; |
|
1191 AddCaption(GetEventString(eidNewAmmoPack), cWhiteColor, capgrpAmmoInfo); |
|
1192 end |
|
1193 end |
|
1194 else |
|
1195 begin |
|
1196 t:= uTot; |
|
1197 if (t > 0) then |
|
1198 begin |
|
1199 FollowGear:= AddGear(0, 0, gtCase, 0, _0, _0, 0); |
|
1200 t:= GetRandom(t); |
|
1201 i:= Low(TAmmoType); |
|
1202 FollowGear^.Pos:= posCaseUtility; |
|
1203 FollowGear^.AmmoType:= i; |
|
1204 AddCaption(GetEventString(eidNewUtilityPack), cWhiteColor, capgrpAmmoInfo); |
|
1205 end |
|
1206 end; |
|
1207 |
|
1208 // handles case of no ammo or utility crates - considered also placing booleans in uAmmos and altering probabilities |
|
1209 if (FollowGear <> nil) then |
|
1210 begin |
|
1211 FindPlace(FollowGear, true, 0, LAND_WIDTH); |
|
1212 |
|
1213 if (FollowGear <> nil) then |
|
1214 AddVoice(sndReinforce, CurrentTeam^.voicepack) |
|
1215 end |
|
1216 end; |
780 end; |
1217 |
781 |
1218 |
782 |
1219 function GearByUID(uid : Longword) : PGear; |
783 function GearByUID(uid : Longword) : PGear; |
1220 var gear: PGear; |
784 var gear: PGear; |