branch | ios-develop |
changeset 13418 | ba39a1d396c0 |
parent 13413 | 419c5eab88eb |
child 13468 | f1d349a52bc7 |
13416:6e8b807bda4b | 13418:ba39a1d396c0 |
---|---|
45 procedure doStepGrave(Gear: PGear); |
45 procedure doStepGrave(Gear: PGear); |
46 procedure doStepBeeWork(Gear: PGear); |
46 procedure doStepBeeWork(Gear: PGear); |
47 procedure doStepBee(Gear: PGear); |
47 procedure doStepBee(Gear: PGear); |
48 procedure doStepShotIdle(Gear: PGear); |
48 procedure doStepShotIdle(Gear: PGear); |
49 procedure doStepShotgunShot(Gear: PGear); |
49 procedure doStepShotgunShot(Gear: PGear); |
50 procedure spawnBulletTrail(Bullet: PGear; bulletX, bulletY: hwFloat); |
50 procedure spawnBulletTrail(Bullet: PGear; bulletX, bulletY: hwFloat; fadeIn: Boolean); |
51 procedure doStepBulletWork(Gear: PGear); |
51 procedure doStepBulletWork(Gear: PGear); |
52 procedure doStepDEagleShot(Gear: PGear); |
52 procedure doStepDEagleShot(Gear: PGear); |
53 procedure doStepSniperRifleShot(Gear: PGear); |
53 procedure doStepSniperRifleShot(Gear: PGear); |
54 procedure doStepActionTimer(Gear: PGear); |
54 procedure doStepActionTimer(Gear: PGear); |
55 procedure doStepPickHammerWork(Gear: PGear); |
55 procedure doStepPickHammerWork(Gear: PGear); |
137 procedure doStepAddAmmo(Gear: PGear); |
137 procedure doStepAddAmmo(Gear: PGear); |
138 procedure doStepGenericFaller(Gear: PGear); |
138 procedure doStepGenericFaller(Gear: PGear); |
139 //procedure doStepCreeper(Gear: PGear); |
139 //procedure doStepCreeper(Gear: PGear); |
140 procedure doStepKnife(Gear: PGear); |
140 procedure doStepKnife(Gear: PGear); |
141 procedure doStepDuck(Gear: PGear); |
141 procedure doStepDuck(Gear: PGear); |
142 procedure doStepMinigunWork(Gear: PGear); |
|
143 procedure doStepMinigun(Gear: PGear); |
|
144 procedure doStepMinigunBullet(Gear: PGear); |
|
142 |
145 |
143 var |
146 var |
144 upd: Longword; |
147 upd: Longword; |
145 snowLeft,snowRight: LongInt; |
148 snowLeft,snowRight: LongInt; |
146 |
149 |
252 HH^.Gear^.Active:= false; |
255 HH^.Gear^.Active:= false; |
253 State:= State and (not (gstHHDriven or gstAttacking or gstAttacked)); |
256 State:= State and (not (gstHHDriven or gstAttacking or gstAttacked)); |
254 Message := Message and (not gmAttack); |
257 Message := Message and (not gmAttack); |
255 end; |
258 end; |
256 HH^.GearHidden:= HH^.Gear; |
259 HH^.GearHidden:= HH^.Gear; |
257 HH^.Gear:= nil |
260 HH^.Gear:= nil; |
261 AddVisualGear(0, 0, vgtTeamHealthSorter); |
|
258 end; |
262 end; |
259 |
263 |
260 |
264 |
261 //////////////////////////////////////////////////////////////////////////////// |
265 //////////////////////////////////////////////////////////////////////////////// |
262 procedure doStepDrowningGear(Gear: PGear); |
266 procedure doStepDrowningGear(Gear: PGear); |
1124 |
1128 |
1125 //////////////////////////////////////////////////////////////////////////////// |
1129 //////////////////////////////////////////////////////////////////////////////// |
1126 procedure doStepShotIdle(Gear: PGear); |
1130 procedure doStepShotIdle(Gear: PGear); |
1127 begin |
1131 begin |
1128 AllInactive := false; |
1132 AllInactive := false; |
1129 inc(Gear^.Timer); |
1133 if (Gear^.Kind <> gtMinigunBullet) then |
1130 if Gear^.Timer > 75 then |
1134 begin |
1135 inc(Gear^.Timer); |
|
1136 if Gear^.Timer > 75 then |
|
1137 begin |
|
1138 DeleteGear(Gear); |
|
1139 AfterAttack |
|
1140 end |
|
1141 end |
|
1142 else |
|
1131 begin |
1143 begin |
1132 DeleteGear(Gear); |
1144 DeleteGear(Gear); |
1133 AfterAttack |
1145 end |
1134 end |
1146 end; |
1147 |
|
1148 procedure CreateShellForGear(Gear: PGear; startFrame: Longword); |
|
1149 var |
|
1150 shell: PVisualGear; |
|
1151 begin |
|
1152 shell := AddVisualGear(hwRound(Gear^.x), hwRound(Gear^.y), vgtShell); |
|
1153 if shell <> nil then |
|
1154 begin |
|
1155 shell^.dX := gear^.dX.QWordValue / -17179869184; |
|
1156 if (gear^.dX.isNegative) then |
|
1157 shell^.dX := -shell^.dX; |
|
1158 shell^.dY := gear^.dY.QWordValue / -17179869184; |
|
1159 shell^.Frame := startFrame; |
|
1160 end; |
|
1161 end; |
|
1162 |
|
1163 function ShotgunLineHitHelp(Gear: PGear; oX, oY, tX, tY: hwFloat): Boolean; |
|
1164 var i: LongInt; |
|
1165 Collisions: PGearArray; |
|
1166 begin |
|
1167 ShotgunLineHitHelp := false; |
|
1168 Collisions := CheckAllGearsLineCollision(Gear, oX, oY, tX, tY); |
|
1169 i := Collisions^.Count; |
|
1170 while i > 0 do |
|
1171 begin |
|
1172 dec(i); |
|
1173 if Collisions^.ar[i]^.Kind in |
|
1174 [gtMine, gtSMine, gtAirMine, gtKnife, gtCase, gtTarget, gtExplosives] then |
|
1175 begin |
|
1176 Gear^.X := Collisions^.ar[i]^.X; |
|
1177 Gear^.Y := Collisions^.ar[i]^.Y; |
|
1178 ShotgunShot(Gear); |
|
1179 Gear^.doStep := @doStepShotIdle; |
|
1180 ShotgunLineHitHelp := true; |
|
1181 exit; |
|
1182 end; |
|
1183 end; |
|
1135 end; |
1184 end; |
1136 |
1185 |
1137 procedure doStepShotgunShot(Gear: PGear); |
1186 procedure doStepShotgunShot(Gear: PGear); |
1138 var |
1187 var |
1139 i: LongWord; |
1188 i: LongWord; |
1140 shell: PVisualGear; |
1189 oX, oY, tmpX, tmpY: hwFloat; |
1141 begin |
1190 begin |
1142 AllInactive := false; |
1191 AllInactive := false; |
1143 |
1192 |
1144 if ((Gear^.State and gstAnimation) = 0) then |
1193 if ((Gear^.State and gstAnimation) = 0) then |
1145 begin |
1194 begin |
1146 dec(Gear^.Timer); |
1195 dec(Gear^.Timer); |
1147 if Gear^.Timer = 0 then |
1196 if Gear^.Timer = 0 then |
1148 begin |
1197 begin |
1149 PlaySound(sndShotgunFire); |
1198 PlaySound(sndShotgunFire); |
1150 shell := AddVisualGear(hwRound(Gear^.x), hwRound(Gear^.y), vgtShell); |
1199 CreateShellForGear(Gear, 0); |
1151 if shell <> nil then |
|
1152 begin |
|
1153 shell^.dX := gear^.dX.QWordValue / -17179869184; |
|
1154 shell^.dY := gear^.dY.QWordValue / -17179869184; |
|
1155 shell^.Frame := 0 |
|
1156 end; |
|
1157 Gear^.State := Gear^.State or gstAnimation |
1200 Gear^.State := Gear^.State or gstAnimation |
1158 end; |
1201 end; |
1159 exit |
1202 exit |
1160 end else |
1203 end else |
1161 if(Gear^.Hedgehog^.Gear = nil) or ((Gear^.Hedgehog^.Gear^.State and gstMoving) <> 0) then |
1204 if(Gear^.Hedgehog^.Gear = nil) or ((Gear^.Hedgehog^.Gear^.State and gstMoving) <> 0) then |
1165 exit |
1208 exit |
1166 end |
1209 end |
1167 else |
1210 else |
1168 inc(Gear^.Timer); |
1211 inc(Gear^.Timer); |
1169 |
1212 |
1170 i := 200; |
1213 i := 100; |
1214 oX := Gear^.X; |
|
1215 oY := Gear^.Y; |
|
1171 repeat |
1216 repeat |
1172 Gear^.X := Gear^.X + Gear^.dX; |
1217 if Gear^.Tag = 0 then |
1173 Gear^.Y := Gear^.Y + Gear^.dY; |
1218 begin |
1174 WorldWrap(Gear); |
1219 Gear^.X := Gear^.X + Gear^.dX; |
1220 Gear^.Y := Gear^.Y + Gear^.dY; |
|
1221 end; |
|
1222 |
|
1223 tmpX := Gear^.X; |
|
1224 tmpY := Gear^.Y; |
|
1225 if (Gear^.PortalCounter < 30) and WorldWrap(Gear) then |
|
1226 begin |
|
1227 inc(Gear^.PortalCounter); |
|
1228 if ShotgunLineHitHelp(Gear, oX, oY, tmpX, tmpY) then |
|
1229 exit; |
|
1230 oX := Gear^.X; |
|
1231 oY := Gear^.Y; |
|
1232 end; |
|
1175 CheckCollision(Gear); |
1233 CheckCollision(Gear); |
1176 if (Gear^.State and gstCollision) <> 0 then |
1234 |
1177 begin |
1235 if ((Gear^.State and gstCollision) <> 0) then |
1178 Gear^.X := Gear^.X + Gear^.dX * 8; |
1236 begin |
1179 Gear^.Y := Gear^.Y + Gear^.dY * 8; |
1237 if Gear^.Tag = 0 then |
1180 ShotgunShot(Gear); |
1238 begin |
1181 Gear^.doStep := @doStepShotIdle; |
1239 //Try to align the shot with the land to give portals a chance to catch it |
1182 exit |
1240 Gear^.X := Gear^.X + Gear^.dX * 2; |
1183 end; |
1241 Gear^.Y := Gear^.Y + Gear^.dY * 2; |
1242 Gear^.Tag := 1 |
|
1243 end |
|
1244 else |
|
1245 begin |
|
1246 Gear^.X := Gear^.X + Gear^.dX * 6; |
|
1247 Gear^.Y := Gear^.Y + Gear^.dY * 6; |
|
1248 ShotgunShot(Gear); |
|
1249 Gear^.doStep := @doStepShotIdle; |
|
1250 end; |
|
1251 exit |
|
1252 end |
|
1253 else |
|
1254 Gear^.Tag := 0; |
|
1184 |
1255 |
1185 CheckGearDrowning(Gear); |
1256 CheckGearDrowning(Gear); |
1186 if (Gear^.State and gstDrowning) <> 0 then |
1257 if (Gear^.State and gstDrowning) <> 0 then |
1187 begin |
1258 begin |
1188 Gear^.doStep := @doStepShotIdle; |
1259 Gear^.doStep := @doStepShotIdle; |
1189 exit |
1260 break; |
1190 end; |
1261 end; |
1191 dec(i) |
1262 dec(i) |
1192 until i = 0; |
1263 until i = 0; |
1264 |
|
1265 ShotgunLineHitHelp(Gear, oX, oY, Gear^.X, Gear^.Y); |
|
1266 |
|
1193 if (hwRound(Gear^.X) and LAND_WIDTH_MASK <> 0) or (hwRound(Gear^.Y) and LAND_HEIGHT_MASK <> 0) then |
1267 if (hwRound(Gear^.X) and LAND_WIDTH_MASK <> 0) or (hwRound(Gear^.Y) and LAND_HEIGHT_MASK <> 0) then |
1194 Gear^.doStep := @doStepShotIdle |
1268 Gear^.doStep := @doStepShotIdle |
1195 end; |
1269 end; |
1196 |
1270 |
1197 //////////////////////////////////////////////////////////////////////////////// |
1271 //////////////////////////////////////////////////////////////////////////////// |
1198 procedure spawnBulletTrail(Bullet: PGear; bulletX, bulletY: hwFloat); |
1272 procedure spawnBulletTrail(Bullet: PGear; bulletX, bulletY: hwFloat; fadeIn: Boolean); |
1199 var oX, oY: hwFloat; |
1273 var oX, oY: hwFloat; |
1274 fromX, fromY, toX, toY, dX, dY, bLength, stepLength: real; |
|
1200 VGear: PVisualGear; |
1275 VGear: PVisualGear; |
1276 i, steps: LongWord; |
|
1201 begin |
1277 begin |
1202 if Bullet^.PortalCounter = 0 then |
1278 if Bullet^.PortalCounter = 0 then |
1203 begin |
1279 begin |
1204 ox:= CurrentHedgehog^.Gear^.X + Int2hwFloat(GetLaunchX(CurrentHedgehog^.CurAmmoType, hwSign(CurrentHedgehog^.Gear^.dX), CurrentHedgehog^.Gear^.Angle)); |
1280 ox:= CurrentHedgehog^.Gear^.X + Int2hwFloat(GetLaunchX(CurrentHedgehog^.CurAmmoType, hwSign(CurrentHedgehog^.Gear^.dX), CurrentHedgehog^.Gear^.Angle)); |
1205 oy:= CurrentHedgehog^.Gear^.Y + Int2hwFloat(GetLaunchY(CurrentHedgehog^.CurAmmoType, CurrentHedgehog^.Gear^.Angle)); |
1281 oy:= CurrentHedgehog^.Gear^.Y + Int2hwFloat(GetLaunchY(CurrentHedgehog^.CurAmmoType, CurrentHedgehog^.Gear^.Angle)); |
1208 begin |
1284 begin |
1209 ox:= Bullet^.Elasticity; |
1285 ox:= Bullet^.Elasticity; |
1210 oy:= Bullet^.Friction; |
1286 oy:= Bullet^.Friction; |
1211 end; |
1287 end; |
1212 |
1288 |
1213 // Bullet trail |
1289 fromX:= hwFloat2Float(ox); |
1214 VGear := AddVisualGear(hwRound(ox), hwRound(oy), vgtLineTrail); |
1290 fromY:= hwFloat2Float(oy); |
1215 |
1291 toX:= hwFloat2Float(bulletX); |
1216 if VGear <> nil then |
1292 toY:= hwFloat2Float(bulletY); |
1217 begin |
1293 |
1218 VGear^.X:= hwFloat2Float(ox); |
1294 dX:= toX - fromX; |
1219 VGear^.Y:= hwFloat2Float(oy); |
1295 dY:= toY - fromY; |
1220 VGear^.dX:= hwFloat2Float(bulletX); |
1296 bLength:= sqrt(dX * dX + dY * dY); |
1221 VGear^.dY:= hwFloat2Float(bulletY); |
1297 dX:= dX / bLength; |
1222 |
1298 dY:= dY / bLength; |
1223 // reached edge of land. assume infinite beam. Extend it way out past camera |
1299 |
1224 if (hwRound(bulletX) and LAND_WIDTH_MASK <> 0) |
1300 if fadeIn then |
1225 or (hwRound(bulletY) and LAND_HEIGHT_MASK <> 0) then |
1301 begin |
1226 // only extend if not under water |
1302 steps:= 10; |
1227 if not CheckCoordInWater(hwRound(bulletX), hwRound(bulletY)) then |
1303 stepLength:= 12; |
1304 fromX:= fromX + dX * 45; |
|
1305 fromY:= fromY + dY * 45; |
|
1306 bLength:= bLength - 45; |
|
1307 end |
|
1308 else steps:= 1; |
|
1309 |
|
1310 for i:= 0 to steps - 1 do |
|
1311 begin |
|
1312 if i < steps - 1 then |
|
1313 begin |
|
1314 toX:= fromX + dX * minD(stepLength, bLength); |
|
1315 toY:= fromY + dY * minD(stepLength, bLength); |
|
1316 end |
|
1317 else if steps > 1 then |
|
1318 begin |
|
1319 toX:= fromX + dX * bLength; |
|
1320 toY:= fromY + dY * bLength; |
|
1321 end; |
|
1322 |
|
1323 if bLength > 0 then |
|
1324 begin |
|
1325 VGear := AddVisualGear(round(fromX), round(fromY), vgtLineTrail); |
|
1326 if VGear <> nil then |
|
1327 begin |
|
1328 VGear^.X:= fromX; |
|
1329 VGear^.Y:= fromY; |
|
1330 VGear^.dX:= toX; |
|
1331 VGear^.dY:= toY; |
|
1332 VGear^.Tint:= $FFFFFF00 or ($FF * (i + 1) div (steps)); |
|
1333 |
|
1334 // reached edge of land. assume infinite beam. Extend it way out past camera |
|
1335 if ((round(toX) and LAND_WIDTH_MASK <> 0) and (not (WorldEdge in [weBounce, weWrap]))) |
|
1336 or (round(toY) and LAND_HEIGHT_MASK <> 0) then |
|
1337 // only extend if not under water |
|
1338 if not CheckCoordInWater(round(toX), round(toY)) then |
|
1228 begin |
1339 begin |
1229 VGear^.dX := VGear^.dX + max(LAND_WIDTH,4096) * (VGear^.dX - VGear^.X); |
1340 VGear^.dX := VGear^.dX + max(LAND_WIDTH,4096) * (VGear^.dX - VGear^.X); |
1230 VGear^.dY := VGear^.dY + max(LAND_WIDTH,4096) * (VGear^.dY - VGear^.Y); |
1341 VGear^.dY := VGear^.dY + max(LAND_WIDTH,4096) * (VGear^.dY - VGear^.Y); |
1231 end; |
1342 end; |
1232 |
1343 VGear^.Timer := 200; |
1233 VGear^.Timer := 200; |
1344 end; |
1234 end; |
1345 end; |
1346 |
|
1347 if i < steps - 1 then |
|
1348 begin |
|
1349 fromX:= toX; |
|
1350 fromY:= toY; |
|
1351 bLength:= bLength - stepLength; |
|
1352 end |
|
1353 end; |
|
1354 end; |
|
1355 |
|
1356 procedure LineShoveHelp(Gear: PGear; oX, oY, tX, tY, dX, dY: hwFloat; count: LongWord); |
|
1357 var dmg,power: LongInt; |
|
1358 begin |
|
1359 if hwSqr(tX - oX) + hwSqr(tY - oY) > _0_25 then |
|
1360 begin |
|
1361 if (Gear^.AmmoType = amDEagle) or (Gear^.AmmoType = amMinigun) then |
|
1362 dmg:= Gear^.Boom |
|
1363 else |
|
1364 dmg:= Gear^.Timer * Gear^.Boom div 100000; |
|
1365 if (Gear^.AmmoType = amMinigun) then |
|
1366 power:= 10 |
|
1367 else |
|
1368 power:= 20; |
|
1369 AmmoShoveLine(Gear, dmg, power, oX, oY, tX, tY); |
|
1370 end; |
|
1371 if Gear^.Damage > 0 then |
|
1372 begin |
|
1373 DrawTunnel(oX, oY, dX, dY, count, 1); |
|
1374 dec(Gear^.Health, Gear^.Damage); |
|
1375 Gear^.Damage := 0 |
|
1376 end; |
|
1377 end; |
|
1378 |
|
1379 procedure CheckBulletDrowningHelp(Bullet: PGear); |
|
1380 var dX, dY: hwFloat; |
|
1381 begin |
|
1382 dX := Bullet^.dX; |
|
1383 dY := Bullet^.dY; |
|
1384 CheckGearDrowning(Bullet); |
|
1385 if (dX <> Bullet^.dX) or (dY <> Bullet^.dY) then |
|
1386 begin |
|
1387 SpawnBulletTrail(Bullet, Bullet^.X, Bullet^.Y, Bullet^.FlightTime = 0); |
|
1388 Bullet^.Elasticity := Bullet^.X; |
|
1389 Bullet^.Friction := Bullet^.Y; |
|
1390 Inc(Bullet^.PortalCounter); |
|
1391 Bullet^.FlightTime:= 1; |
|
1392 end; |
|
1393 end; |
|
1394 |
|
1395 procedure CreateBubblesForBullet(Gear: PGear); |
|
1396 var i, iInit: LongWord; |
|
1397 begin |
|
1398 if ((Gear^.State and gstDrowning) <> 0) and (Gear^.Health > 0) then |
|
1399 begin |
|
1400 // draw bubbles |
|
1401 if (not SuddenDeathDmg and (WaterOpacity < $FF)) or (SuddenDeathDmg and (SDWaterOpacity < $FF)) then |
|
1402 begin |
|
1403 case Gear^.Kind of |
|
1404 gtMinigunBullet: iInit:= Gear^.Health * 100; |
|
1405 gtDEagleShot, gtSniperRifleShot: iInit:= Gear^.Health * 4 |
|
1406 end; |
|
1407 for i:=iInit downto 0 do |
|
1408 begin |
|
1409 if Random(6) = 0 then |
|
1410 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble); |
|
1411 Gear^.X := Gear^.X + Gear^.dX; |
|
1412 Gear^.Y := Gear^.Y + Gear^.dY; |
|
1413 end; |
|
1414 end; |
|
1415 // bullet dies underwater |
|
1416 Gear^.Health:= 0; |
|
1417 end; |
|
1235 end; |
1418 end; |
1236 |
1419 |
1237 procedure doStepBulletWork(Gear: PGear); |
1420 procedure doStepBulletWork(Gear: PGear); |
1238 var |
1421 var |
1239 i, x, y, iInit: LongWord; |
1422 i, x, y, iInit: LongWord; |
1240 oX, oY, tX, tY, tDx, tDy: hwFloat; |
1423 oX, oY, tX, tY, tDx, tDy: hwFloat; |
1241 VGear: PVisualGear; |
1424 VGear: PVisualGear; |
1425 LandFlags: Word; |
|
1426 isDigging: Boolean; |
|
1427 isDead: Boolean; |
|
1242 begin |
1428 begin |
1243 AllInactive := false; |
1429 AllInactive := false; |
1244 inc(Gear^.Timer); |
1430 inc(Gear^.Timer); |
1245 iInit := 80; |
1431 iInit := 100; |
1246 i := iInit; |
1432 i := iInit; |
1433 isDigging := false; |
|
1434 isDead := false; |
|
1247 oX := Gear^.X; |
1435 oX := Gear^.X; |
1248 oY := Gear^.Y; |
1436 oY := Gear^.Y; |
1249 repeat |
1437 repeat |
1250 Gear^.X := Gear^.X + Gear^.dX; |
1438 Gear^.X := Gear^.X + Gear^.dX; |
1251 Gear^.Y := Gear^.Y + Gear^.dY; |
1439 Gear^.Y := Gear^.Y + Gear^.dY; |
1253 tY:= Gear^.Y; |
1441 tY:= Gear^.Y; |
1254 tDx:= Gear^.dX; |
1442 tDx:= Gear^.dX; |
1255 tDy:= Gear^.dY; |
1443 tDy:= Gear^.dY; |
1256 if (Gear^.PortalCounter < 30) and WorldWrap(Gear) then |
1444 if (Gear^.PortalCounter < 30) and WorldWrap(Gear) then |
1257 begin |
1445 begin |
1258 DrawTunnel(oX, oY, tDx, tDy, iInit + 2 - i, 1); |
1446 LineShoveHelp(Gear, oX, oY, tX, tY, tDx, tDy, iInit + 2 - i); |
1259 SpawnBulletTrail(Gear, tX, tY); |
1447 SpawnBulletTrail(Gear, tX, tY, Gear^.FlightTime = 0); |
1448 Gear^.FlightTime:= 1; |
|
1260 iInit:= i; |
1449 iInit:= i; |
1261 oX:= Gear^.X; |
1450 oX:= Gear^.X; |
1262 oY:= Gear^.Y; |
1451 oY:= Gear^.Y; |
1263 inc(Gear^.PortalCounter); |
1452 inc(Gear^.PortalCounter); |
1264 Gear^.Elasticity:= Gear^.X; |
1453 Gear^.Elasticity:= Gear^.X; |
1265 Gear^.Friction:= Gear^.Y; |
1454 Gear^.Friction:= Gear^.Y; |
1266 SpawnBulletTrail(Gear, Gear^.X, Gear^.Y); |
1455 SpawnBulletTrail(Gear, Gear^.X, Gear^.Y, false); |
1456 |
|
1457 // bullets can now hurt the hog that fired them |
|
1458 if WorldEdge <> weSea then Gear^.Data:= nil; |
|
1267 end; |
1459 end; |
1268 x := hwRound(Gear^.X); |
1460 x := hwRound(Gear^.X); |
1269 y := hwRound(Gear^.Y); |
1461 y := hwRound(Gear^.Y); |
1270 |
1462 |
1271 if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] <> 0) then |
1463 if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) then |
1272 inc(Gear^.Damage); |
1464 begin |
1273 // let's interrupt before a collision to give portals a chance to catch the bullet |
1465 LandFlags:= Land[y, x]; |
1274 if (Gear^.Damage = 1) and (Gear^.Tag = 0) and (not CheckLandValue(x, y, lfLandMask)) then |
1466 if LandFlags <> 0 then inc(Gear^.Damage); |
1467 isDigging:= (LandFlags and lfLandMask) <> 0; |
|
1468 end; |
|
1469 // let's interrupt before a collision with land to give portals a chance to catch the bullet |
|
1470 if isDigging and (Gear^.Tag = 0) then |
|
1275 begin |
1471 begin |
1276 Gear^.Tag := 1; |
1472 Gear^.Tag := 1; |
1277 Gear^.Damage := 0; |
1473 dec(Gear^.Damage); |
1278 Gear^.X := Gear^.X - Gear^.dX; |
1474 Gear^.X := Gear^.X - Gear^.dX; |
1279 Gear^.Y := Gear^.Y - Gear^.dY; |
1475 Gear^.Y := Gear^.Y - Gear^.dY; |
1280 CheckGearDrowning(Gear); |
1476 CheckBulletDrowningHelp(Gear); |
1281 break; |
1477 break; |
1282 end |
1478 end |
1283 else |
1479 else if (not isDigging) then |
1284 Gear^.Tag := 0; |
1480 Gear^.Tag := 0; |
1285 |
1481 |
1286 if Gear^.Damage > 5 then |
1482 //Shove static gears to remove the mask and stop damaging the bullet |
1287 begin |
1483 if (not isDigging) and (Gear^.Damage > 5) and (Gear^.Kind <> gtMinigunBullet) then |
1288 if Gear^.AmmoType = amDEagle then |
1484 begin |
1289 AmmoShove(Gear, Gear^.Boom, 20) |
1485 LineShoveHelp(Gear, oX, oY, tX, tY, tDx, tDy, iInit + 2 - i); |
1486 SpawnBulletTrail(Gear, tX, tY, Gear^.FlightTime = 0); |
|
1487 Gear^.FlightTime:= 1; |
|
1488 iInit:= i; |
|
1489 oX:= Gear^.X; |
|
1490 oY:= Gear^.Y; |
|
1491 end; |
|
1492 |
|
1493 CheckBulletDrowningHelp(Gear); |
|
1494 case Gear^.Kind of |
|
1495 gtMinigunBullet: isDead:= isDigging or ((Gear^.State and gstDrowning) <> 0); |
|
1496 gtDEagleShot, gtSniperRifleShot: isDead:= (Gear^.Damage >= Gear^.Health) or ((Gear^.State and gstDrowning) <> 0) |
|
1497 end; |
|
1498 dec(i) |
|
1499 until (i = 0) or (isDead); |
|
1500 |
|
1501 LineShoveHelp(Gear, oX, oY, Gear^.X, Gear^.Y, |
|
1502 Gear^.dX, Gear^.dY, iInit + 2 - i); |
|
1503 |
|
1504 CreateBubblesForBullet(Gear); |
|
1505 |
|
1506 x := hwRound(Gear^.X); |
|
1507 y := hwRound(Gear^.Y); |
|
1508 if (isDead) or (x and LAND_WIDTH_MASK <> 0) or (y and LAND_HEIGHT_MASK <> 0) then |
|
1509 begin |
|
1510 if (Gear^.Kind = gtSniperRifleShot) then |
|
1511 cLaserSightingSniper := false; |
|
1512 if (Ammoz[Gear^.AmmoType].Ammo.NumPerTurn <= CurrentHedgehog^.MultiShootAttacks) and (CurrentHedgehog^.Effects[heArtillery] = 2) then |
|
1513 CurrentHedgehog^.Effects[heArtillery]:= 0; |
|
1514 |
|
1515 // Bullet Hit |
|
1516 if ((Gear^.State and gstDrowning) = 0) and (x and LAND_WIDTH_MASK = 0) and (y and LAND_HEIGHT_MASK = 0) then |
|
1517 begin |
|
1518 if Gear^.Kind = gtMinigunBullet then |
|
1519 begin |
|
1520 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 5, |
|
1521 Gear^.Hedgehog, EXPLNoDamage{ or EXPLDontDraw or EXPLNoGfx}); |
|
1522 VGear := AddVisualGear(hwRound(Gear^.X + Gear^.dX * 5), hwRound(Gear^.Y + Gear^.dY * 5), vgtBulletHit); |
|
1523 end |
|
1290 else |
1524 else |
1291 AmmoShove(Gear, Gear^.Timer * Gear^.Boom div 100000, 20); |
1525 VGear := AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBulletHit); |
1292 end; |
1526 |
1293 CheckGearDrowning(Gear); |
1527 if VGear <> nil then |
1294 dec(i) |
1528 begin |
1295 until (i = 0) or (Gear^.Damage > Gear^.Health) or ((Gear^.State and gstDrowning) <> 0); |
1529 VGear^.Angle := DxDy2Angle(-Gear^.dX, Gear^.dY); |
1296 |
|
1297 if Gear^.Damage > 0 then |
|
1298 begin |
|
1299 DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, iInit + 2 - i, 1); |
|
1300 dec(Gear^.Health, Gear^.Damage); |
|
1301 Gear^.Damage := 0 |
|
1302 end; |
|
1303 |
|
1304 if ((Gear^.State and gstDrowning) <> 0) and (Gear^.Health > 0) then |
|
1305 begin |
|
1306 // draw bubbles |
|
1307 if (not SuddenDeathDmg and (WaterOpacity < $FF)) or (SuddenDeathDmg and (SDWaterOpacity < $FF)) then |
|
1308 begin |
|
1309 for i:=(Gear^.Health * 4) downto 0 do |
|
1310 begin |
|
1311 if Random(6) = 0 then |
|
1312 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble); |
|
1313 Gear^.X := Gear^.X + Gear^.dX; |
|
1314 Gear^.Y := Gear^.Y + Gear^.dY; |
|
1315 end; |
1530 end; |
1316 end; |
1531 end; |
1317 // bullet dies underwater |
1532 |
1318 Gear^.Health:= 0; |
1533 spawnBulletTrail(Gear, Gear^.X, Gear^.Y, Gear^.FlightTime = 0); |
1319 end; |
1534 Gear^.FlightTime:= 1; |
1320 |
1535 if Gear^.Kind = gtMinigunBullet then |
1321 if (Gear^.Health <= 0) |
1536 ClearHitOrderLeq(Gear^.Tag); |
1322 or (hwRound(Gear^.X) and LAND_WIDTH_MASK <> 0) |
1537 |
1323 or (hwRound(Gear^.Y) and LAND_HEIGHT_MASK <> 0) then |
1538 if (worldEdge = weSea) and (Gear^.Kind = gtMinigunBullet) |
1324 begin |
1539 and Gear^.Y.isNegative and Gear^.dY.isNegative |
1325 if (Gear^.Kind = gtSniperRifleShot) then |
1540 and (Gear^.Health > 0) and (not isZero(Gear^.dX)) then |
1326 cLaserSightingSniper := false; |
1541 begin |
1327 if (Ammoz[Gear^.AmmoType].Ammo.NumPerTurn <= CurrentHedgehog^.MultiShootAttacks) and ((GameFlags and gfArtillery) = 0) then |
1542 if Gear^.dX.isNegative then |
1328 cArtillery := false; |
1543 begin |
1329 |
1544 |
1330 // Bullet Hit |
1545 Gear^.X:= int2hwFloat(-1); |
1331 if ((Gear^.State and gstDrowning) = 0) and (hwRound(Gear^.X) and LAND_WIDTH_MASK = 0) and (hwRound(Gear^.Y) and LAND_HEIGHT_MASK = 0) then |
1546 iInit:= x - leftX; |
1332 begin |
1547 end |
1333 VGear := AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBulletHit); |
1548 else |
1334 if VGear <> nil then |
1549 begin |
1335 begin |
1550 Gear^.X:= int2hwFloat(LAND_WIDTH); |
1336 VGear^.Angle := DxDy2Angle(-Gear^.dX, Gear^.dY); |
1551 iInit:= rightX - x - 1; |
1337 end; |
|
1338 end; |
1552 end; |
1339 |
1553 Gear^.Y:= Gear^.Y + Gear^.dY * hwAbs(int2hwFloat(iInit) / Gear^.dX); |
1340 spawnBulletTrail(Gear, Gear^.X, Gear^.Y); |
1554 CheckGearDrowning(Gear); |
1341 Gear^.doStep := @doStepShotIdle |
1555 CreateBubblesForBullet(Gear); |
1342 end; |
1556 end; |
1557 Gear^.doStep := @doStepShotIdle |
|
1558 end; |
|
1343 end; |
1559 end; |
1344 |
1560 |
1345 procedure doStepDEagleShot(Gear: PGear); |
1561 procedure doStepDEagleShot(Gear: PGear); |
1346 begin |
1562 begin |
1347 Gear^.Data:= nil; |
1563 Gear^.Data:= nil; |
1348 // remember who fired this |
1564 // remember who fired this |
1349 if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) then |
1565 if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) then |
1350 Gear^.Data:= Pointer(Gear^.Hedgehog^.Gear); |
1566 Gear^.Data:= Pointer(Gear^.Hedgehog^.Gear); |
1351 |
1567 |
1352 PlaySound(sndGun); |
1568 PlaySound(sndGun); |
1569 ClearHitOrder(); |
|
1353 // add 2 initial steps to avoid problem with ammoshove related to calculation of radius + 1 radius as gear widths, and also just plain old weird angles |
1570 // add 2 initial steps to avoid problem with ammoshove related to calculation of radius + 1 radius as gear widths, and also just plain old weird angles |
1354 Gear^.X := Gear^.X + Gear^.dX * 2; |
1571 Gear^.X := Gear^.X + Gear^.dX * 2; |
1355 Gear^.Y := Gear^.Y + Gear^.dY * 2; |
1572 Gear^.Y := Gear^.Y + Gear^.dY * 2; |
1573 Gear^.FlightTime := 0; |
|
1356 Gear^.doStep := @doStepBulletWork |
1574 Gear^.doStep := @doStepBulletWork |
1357 end; |
1575 end; |
1358 |
1576 |
1359 procedure doStepSniperRifleShot(Gear: PGear); |
1577 procedure doStepSniperRifleShot(Gear: PGear); |
1360 var |
1578 var HHGear: PGear; |
1361 HHGear: PGear; |
1579 begin |
1362 shell: PVisualGear; |
1580 |
1363 begin |
|
1364 |
|
1365 cArtillery := true; |
|
1366 HHGear := Gear^.Hedgehog^.Gear; |
1581 HHGear := Gear^.Hedgehog^.Gear; |
1582 if (Gear^.Hedgehog^.Effects[heArtillery] <> 1) then |
|
1583 Gear^.Hedgehog^.Effects[heArtillery]:= 2; |
|
1367 |
1584 |
1368 if HHGear = nil then |
1585 if HHGear = nil then |
1369 begin |
1586 begin |
1370 DeleteGear(gear); |
1587 DeleteGear(gear); |
1371 exit |
1588 exit |
1385 dec(HHGear^.Angle,32) |
1602 dec(HHGear^.Angle,32) |
1386 end; |
1603 end; |
1387 |
1604 |
1388 if (HHGear^.Message and gmAttack) <> 0 then |
1605 if (HHGear^.Message and gmAttack) <> 0 then |
1389 begin |
1606 begin |
1390 shell := AddVisualGear(hwRound(Gear^.x), hwRound(Gear^.y), vgtShell); |
1607 CreateShellForGear(Gear, 1); |
1391 if shell <> nil then |
|
1392 begin |
|
1393 shell^.dX := gear^.dX.QWordValue / -8589934592; |
|
1394 shell^.dY := gear^.dY.QWordValue / -8589934592; |
|
1395 shell^.Frame := 1 |
|
1396 end; |
|
1397 Gear^.State := Gear^.State or gstAnimation; |
1608 Gear^.State := Gear^.State or gstAnimation; |
1398 Gear^.dX := SignAs(AngleSin(HHGear^.Angle), HHGear^.dX) * _0_5; |
1609 Gear^.dX := SignAs(AngleSin(HHGear^.Angle), HHGear^.dX) * _0_5; |
1399 Gear^.dY := -AngleCos(HHGear^.Angle) * _0_5; |
1610 Gear^.dY := -AngleCos(HHGear^.Angle) * _0_5; |
1400 PlaySound(sndGun); |
1611 PlaySound(sndGun); |
1612 ClearHitOrder(); |
|
1401 // add 2 initial steps to avoid problem with ammoshove related to calculation of radius + 1 radius as gear widths, and also just weird angles |
1613 // add 2 initial steps to avoid problem with ammoshove related to calculation of radius + 1 radius as gear widths, and also just weird angles |
1402 Gear^.X := Gear^.X + Gear^.dX * 2; |
1614 Gear^.X := Gear^.X + Gear^.dX * 2; |
1403 Gear^.Y := Gear^.Y + Gear^.dY * 2; |
1615 Gear^.Y := Gear^.Y + Gear^.dY * 2; |
1616 Gear^.FlightTime := 0; |
|
1404 Gear^.doStep := @doStepBulletWork; |
1617 Gear^.doStep := @doStepBulletWork; |
1405 end |
1618 end |
1406 else |
1619 else |
1407 if (GameTicks mod 32) = 0 then |
1620 if (GameTicks mod 32) = 0 then |
1408 if (GameTicks mod 4096) < 2048 then |
1621 if (GameTicks mod 4096) < 2048 then |
1803 var i,t,targDist,tmpDist: LongWord; |
2016 var i,t,targDist,tmpDist: LongWord; |
1804 targ, tmpG: PGear; |
2017 targ, tmpG: PGear; |
1805 trackSpeed, airFriction, tX, tY: hwFloat; |
2018 trackSpeed, airFriction, tX, tY: hwFloat; |
1806 isUnderwater: Boolean; |
2019 isUnderwater: Boolean; |
1807 begin |
2020 begin |
2021 if (Gear^.State and gstFrozen) <> 0 then |
|
2022 begin |
|
2023 if Gear^.Damage > 0 then |
|
2024 begin |
|
2025 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
|
2026 DeleteGear(Gear) |
|
2027 end; |
|
2028 exit |
|
2029 end; |
|
1808 isUnderwater:= CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y) + Gear^.Radius); |
2030 isUnderwater:= CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y) + Gear^.Radius); |
1809 if Gear^.Pos > 0 then |
2031 if Gear^.Pos > 0 then |
1810 begin |
2032 begin |
1811 airFriction:= _1; |
2033 airFriction:= _1; |
1812 if isUnderwater then |
2034 if isUnderwater then |
1912 begin |
2134 begin |
1913 if targ <> nil then |
2135 if targ <> nil then |
1914 begin |
2136 begin |
1915 tX:=Gear^.X-targ^.X; |
2137 tX:=Gear^.X-targ^.X; |
1916 tY:=Gear^.Y-targ^.Y; |
2138 tY:=Gear^.Y-targ^.Y; |
1917 if (tX.Round+tY.Round < Gear^.Karma) and |
2139 if (tX.Round+tY.Round < Gear^.Boom) and |
1918 (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Karma)) then |
2140 (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Boom)) then |
1919 Gear^.State := Gear^.State or gstAttacking |
2141 Gear^.State := Gear^.State or gstAttacking |
1920 end |
2142 end |
1921 else if (Gear^.Angle > 0) and (CheckGearNear(Gear, gtHedgehog, Gear^.Karma, Gear^.Karma) <> nil) then |
2143 else if (Gear^.Angle > 0) and (CheckGearNear(Gear, gtHedgehog, Gear^.Boom, Gear^.Boom) <> nil) then |
1922 Gear^.State := Gear^.State or gstAttacking |
2144 Gear^.State := Gear^.State or gstAttacking |
1923 end |
2145 end |
1924 end |
2146 end |
1925 else // gstAttacking <> 0 |
2147 else // gstAttacking <> 0 |
1926 begin |
2148 begin |
1932 // recheck |
2154 // recheck |
1933 if targ <> nil then |
2155 if targ <> nil then |
1934 begin |
2156 begin |
1935 tX:=Gear^.X-targ^.X; |
2157 tX:=Gear^.X-targ^.X; |
1936 tY:=Gear^.Y-targ^.Y; |
2158 tY:=Gear^.Y-targ^.Y; |
1937 if (tX.Round+tY.Round < Gear^.Karma) and |
2159 if (tX.Round+tY.Round < Gear^.Boom) and |
1938 (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Karma)) then |
2160 (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Boom)) then |
1939 begin |
2161 begin |
1940 Gear^.Hedgehog:= CurrentHedgehog; |
2162 Gear^.Hedgehog:= CurrentHedgehog; |
1941 tmpG:= FollowGear; |
2163 tmpG:= FollowGear; |
1942 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Karma, Gear^.Hedgehog, EXPLAutoSound); |
2164 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
1943 FollowGear:= tmpG; |
2165 FollowGear:= tmpG; |
1944 DeleteGear(Gear); |
2166 DeleteGear(Gear); |
1945 exit |
2167 exit |
1946 end |
2168 end |
1947 end |
2169 end |
1948 else if (Gear^.Angle > 0) and (CheckGearNear(Gear, gtHedgehog, Gear^.Karma, Gear^.Karma) <> nil) then |
2170 else if (Gear^.Angle > 0) and (CheckGearNear(Gear, gtHedgehog, Gear^.Boom, Gear^.Boom) <> nil) then |
1949 begin |
2171 begin |
1950 Gear^.Hedgehog:= CurrentHedgehog; |
2172 Gear^.Hedgehog:= CurrentHedgehog; |
1951 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Karma, Gear^.Hedgehog, EXPLAutoSound); |
2173 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
1952 DeleteGear(Gear); |
2174 DeleteGear(Gear); |
1953 exit |
2175 exit |
1954 end; |
2176 end; |
1955 Gear^.State:= Gear^.State and (not gstAttacking); |
2177 Gear^.State:= Gear^.State and (not gstAttacking); |
1956 Gear^.Timer:= Gear^.WDTimer |
2178 Gear^.Timer:= Gear^.WDTimer |
3437 dX:= _50 * cGravity * (Gear^.X - X) / _25 |
3659 dX:= _50 * cGravity * (Gear^.X - X) / _25 |
3438 else if (not (hwAbs(Gear^.X + int2hwFloat(RightX-LeftX) - X) > int2hwFloat(Gear^.Radius))) then |
3660 else if (not (hwAbs(Gear^.X + int2hwFloat(RightX-LeftX) - X) > int2hwFloat(Gear^.Radius))) then |
3439 dX:= _50 * cGravity * ((Gear^.X + int2hwFloat(RightX-LeftX)) - X) / _25 |
3661 dX:= _50 * cGravity * ((Gear^.X + int2hwFloat(RightX-LeftX)) - X) / _25 |
3440 else |
3662 else |
3441 dX:= _50 * cGravity * ((Gear^.X - int2hwFloat(RightX-LeftX)) - X) / _25; |
3663 dX:= _50 * cGravity * ((Gear^.X - int2hwFloat(RightX-LeftX)) - X) / _25; |
3442 dY:= -_450 * cGravity; |
3664 dY:= -_450 * cMaxWindSpeed * 2; |
3443 Active:= true; |
3665 Active:= true; |
3444 end |
3666 end |
3445 else if Hedgehog^.Effects[heFrozen] > 255 then |
3667 else if Hedgehog^.Effects[heFrozen] > 255 then |
3446 Hedgehog^.Effects[heFrozen]:= 255 |
3668 Hedgehog^.Effects[heFrozen]:= 255 |
3447 end ; |
3669 end ; |
3762 |
3984 |
3763 const cAngleSpeed = 3; |
3985 const cAngleSpeed = 3; |
3764 var |
3986 var |
3765 HHGear: PGear; |
3987 HHGear: PGear; |
3766 i: LongInt; |
3988 i: LongInt; |
3989 s: ansistring; |
|
3767 dX, dY : hwFloat; |
3990 dX, dY : hwFloat; |
3768 fChanged: boolean; |
3991 fChanged: boolean; |
3769 trueAngle: Longword; |
3992 trueAngle: Longword; |
3770 t: PGear; |
3993 t: PGear; |
3771 begin |
3994 begin |
3840 if Gear^.Timer < 3500 then |
4063 if Gear^.Timer < 3500 then |
3841 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtEvilTrace) |
4064 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtEvilTrace) |
3842 else |
4065 else |
3843 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace); |
4066 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace); |
3844 |
4067 |
3845 if (HHGear <> nil) and ((HHGear^.Message and gmAttack) <> 0) and (Gear^.Health <> 0) then |
4068 if (HHGear <> nil) and ((HHGear^.Message and gmAttack) <> 0) then |
3846 begin |
4069 begin |
3847 HHGear^.Message := HHGear^.Message and (not gmAttack); |
4070 if (Gear^.Health) <> 0 then |
3848 AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, Gear^.dX * _0_5, Gear^.dY * |
4071 begin |
3849 _0_5, 0); |
4072 HHGear^.Message := HHGear^.Message and (not gmAttack); |
3850 dec(Gear^.Health) |
4073 AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, Gear^.dX * _0_5, Gear^.dY * |
4074 _0_5, 0); |
|
4075 dec(Gear^.Health) |
|
4076 end; |
|
4077 s:= ansistring(inttostr(Gear^.Health)); |
|
4078 AddCaption(formatA(trmsg[sidRemaining], s), cWhiteColor, capgrpAmmostate); |
|
3851 end; |
4079 end; |
3852 |
4080 |
3853 if (HHGear <> nil) and ((HHGear^.Message and gmLJump) <> 0) and ((Gear^.State and gsttmpFlag) = 0) then |
4081 if (HHGear <> nil) and ((HHGear^.Message and gmLJump) <> 0) and ((Gear^.State and gsttmpFlag) = 0) then |
3854 begin |
4082 begin |
3855 Gear^.State := Gear^.State or gsttmpFlag; |
4083 Gear^.State := Gear^.State or gsttmpFlag; |
4083 Message := Message and (not (gmAttack or gmUp or gmPrecise or gmLeft or gmRight)); |
4311 Message := Message and (not (gmAttack or gmUp or gmPrecise or gmLeft or gmRight)); |
4084 |
4312 |
4085 if (dY < _0_1) and (dY > -_0_1) then |
4313 if (dY < _0_1) and (dY > -_0_1) then |
4086 begin |
4314 begin |
4087 Gear^.State := Gear^.State or gsttmpFlag; |
4315 Gear^.State := Gear^.State or gsttmpFlag; |
4316 dX := SignAs(_0, dX); |
|
4088 dY := dY - _0_2 |
4317 dY := dY - _0_2 |
4089 end |
4318 end |
4090 end |
4319 end |
4091 end; |
4320 end; |
4092 |
4321 |
4106 procedure doStepBirdyFly(Gear: PGear); |
4335 procedure doStepBirdyFly(Gear: PGear); |
4107 var |
4336 var |
4108 HHGear: PGear; |
4337 HHGear: PGear; |
4109 fuel, i: LongInt; |
4338 fuel, i: LongInt; |
4110 move: hwFloat; |
4339 move: hwFloat; |
4340 s: ansistring; |
|
4111 begin |
4341 begin |
4112 HHGear := Gear^.Hedgehog^.Gear; |
4342 HHGear := Gear^.Hedgehog^.Gear; |
4113 if HHGear = nil then |
4343 if HHGear = nil then |
4114 begin |
4344 begin |
4115 Gear^.Timer := 0; |
4345 Gear^.Timer := 0; |
4167 begin |
4397 begin |
4168 AddGear(hwRound(Gear^.X), hwRound(Gear^.Y) + 32, gtEgg, 0, Gear^.dX * _0_5, Gear^.dY, 0); |
4398 AddGear(hwRound(Gear^.X), hwRound(Gear^.Y) + 32, gtEgg, 0, Gear^.dX * _0_5, Gear^.dY, 0); |
4169 PlaySound(sndBirdyLay); |
4399 PlaySound(sndBirdyLay); |
4170 dec(Gear^.FlightTime) |
4400 dec(Gear^.FlightTime) |
4171 end; |
4401 end; |
4402 s:= ansistring(inttostr(Gear^.FlightTime)); |
|
4403 AddCaption(formatA(trmsg[sidRemaining], s), cWhiteColor, capgrpAmmostate); |
|
4172 end; |
4404 end; |
4173 |
4405 |
4174 if HHGear^.Message and (gmUp or gmPrecise or gmLeft or gmRight) <> 0 then |
4406 if HHGear^.Message and (gmUp or gmPrecise or gmLeft or gmRight) <> 0 then |
4175 Gear^.State := Gear^.State and (not gsttmpFlag); |
4407 Gear^.State := Gear^.State and (not gsttmpFlag); |
4176 |
4408 |
4452 |
4684 |
4453 if iterator^.Kind = gtDuck then |
4685 if iterator^.Kind = gtDuck then |
4454 // Make duck go into “falling” mode again |
4686 // Make duck go into “falling” mode again |
4455 iterator^.Pos:= 0; |
4687 iterator^.Pos:= 0; |
4456 |
4688 |
4457 isbullet:= (iterator^.Kind in [gtShotgunShot, gtDEagleShot, gtSniperRifleShot, gtSineGunShot]); |
4689 isbullet:= (iterator^.Kind in [gtShotgunShot, gtDEagleShot, gtSniperRifleShot, gtSineGunShot, gtMinigunBullet]); |
4458 |
4690 |
4459 r:= int2hwFloat(iterator^.Radius); |
4691 r:= int2hwFloat(iterator^.Radius); |
4460 |
4692 |
4461 if not (isbullet or iscake) then |
4693 if not (isbullet or iscake) then |
4462 begin |
4694 begin |
4479 |
4711 |
4480 if (hwRound(Distance(Gear^.X-ox,Gear^.Y-oy)) > Gear^.Radius + 1 ) then |
4712 if (hwRound(Distance(Gear^.X-ox,Gear^.Y-oy)) > Gear^.Radius + 1 ) then |
4481 continue; |
4713 continue; |
4482 end; |
4714 end; |
4483 |
4715 |
4484 if (iterator^.Kind = gtDEagleShot) or (iterator^.Kind = gtSniperRifleShot) then |
4716 if (iterator^.Kind in [gtDEagleShot, gtSniperRifleShot, gtMinigunBullet]) then |
4485 begin |
4717 begin |
4486 // draw bullet trail |
4718 // draw bullet trail |
4487 spawnBulletTrail(iterator, iterator^.X, iterator^.Y); |
4719 spawnBulletTrail(iterator, iterator^.X, iterator^.Y, iterator^.FlightTime = 0); |
4720 iterator^.FlightTime := 1; |
|
4488 // the bullet can now hurt the hog that fired it |
4721 // the bullet can now hurt the hog that fired it |
4489 iterator^.Data:= nil; |
4722 iterator^.Data:= nil; |
4490 end; |
4723 end; |
4491 |
4724 |
4492 // calc gear offset in portal vector direction |
4725 // calc gear offset in portal vector direction |
4801 begin |
5034 begin |
4802 CurWeapon:= GetCurAmmoEntry(CurrentHedgehog^); |
5035 CurWeapon:= GetCurAmmoEntry(CurrentHedgehog^); |
4803 // let's save the HH's dX's direction so we can decide where the "top" of the portal hole |
5036 // let's save the HH's dX's direction so we can decide where the "top" of the portal hole |
4804 newPortal^.Elasticity.isNegative := CurrentHedgehog^.Gear^.dX.isNegative; |
5037 newPortal^.Elasticity.isNegative := CurrentHedgehog^.Gear^.dX.isNegative; |
4805 // when doing a backjump the dx is the opposite of the facing direction |
5038 // when doing a backjump the dx is the opposite of the facing direction |
4806 if ((Gear^.State and gstHHHJump) <> 0) and (not cArtillery) then |
5039 if ((Gear^.State and gstHHHJump) <> 0) and (Effects[heArtillery] = 0) then |
4807 newPortal^.Elasticity.isNegative := not newPortal^.Elasticity.isNegative; |
5040 newPortal^.Elasticity.isNegative := not newPortal^.Elasticity.isNegative; |
4808 |
5041 |
4809 // make portal gun look unloaded |
5042 // make portal gun look unloaded |
4810 if (CurWeapon <> nil) and (CurAmmoType = amPortalGun) then |
5043 if (CurWeapon <> nil) and (CurAmmoType = amPortalGun) then |
4811 CurWeapon^.Timer := CurWeapon^.Timer or 2; |
5044 CurWeapon^.Timer := CurWeapon^.Timer or 2; |
6000 begin |
6233 begin |
6001 HedgehogChAngle(HHGear); |
6234 HedgehogChAngle(HHGear); |
6002 ndX:= SignAs(AngleSin(HHGear^.Angle), HHGear^.dX) * _4; |
6235 ndX:= SignAs(AngleSin(HHGear^.Angle), HHGear^.dX) * _4; |
6003 ndY:= -AngleCos(HHGear^.Angle) * _4; |
6236 ndY:= -AngleCos(HHGear^.Angle) * _4; |
6004 if (ndX <> dX) or (ndY <> dY) or |
6237 if (ndX <> dX) or (ndY <> dY) or |
6005 ((Target.X <> NoPointX) and (Target.X and LAND_WIDTH_MASK = 0) and |
6238 (((Target.X <> NoPointX) and (Target.X and LAND_WIDTH_MASK = 0) and |
6006 (Target.Y and LAND_HEIGHT_MASK = 0) and ((Land[Target.Y, Target.X] = 0)) and |
6239 (Target.Y and LAND_HEIGHT_MASK = 0) and ((Land[Target.Y, Target.X] = 0)) and |
6007 (not CheckCoordInWater(Target.X, Target.Y))) then |
6240 (not CheckCoordInWater(Target.X, Target.Y))) and (CheckGearNear(gtAirMine, int2hwFloat(Target.X),int2hwFloat(Target.Y), Gear^.Radius*3, Gear^.Radius*3) = nil)) then |
6008 begin |
6241 begin |
6009 updateTarget(Gear, ndX, ndY); |
6242 updateTarget(Gear, ndX, ndY); |
6010 Timer := iceWaitCollision; |
6243 Timer := iceWaitCollision; |
6011 end |
6244 end |
6012 else |
6245 else |
6018 if Target.X = NoPointX then t:= hwRound(hwSqr(X-HHGear^.X)+hwSqr(Y-HHGear^.Y)); |
6251 if Target.X = NoPointX then t:= hwRound(hwSqr(X-HHGear^.X)+hwSqr(Y-HHGear^.Y)); |
6019 |
6252 |
6020 if Target.X <> NoPointX then |
6253 if Target.X <> NoPointX then |
6021 begin |
6254 begin |
6022 CheckCollision(Gear); |
6255 CheckCollision(Gear); |
6023 if (State and gstCollision) <> 0 then |
6256 if ((State and gstCollision) <> 0) or (CheckGearNear(gtAirMine, int2hwFloat(Target.X),int2hwFloat(Target.Y), Gear^.Radius*4, Gear^.Radius*4) <> nil) then |
6024 begin |
6257 begin |
6025 if Timer = iceWaitCollision then |
6258 if Timer = iceWaitCollision then |
6026 begin |
6259 begin |
6027 Timer := iceCollideWithGround; |
6260 Timer := iceCollideWithGround; |
6028 Power := GameTicks; |
6261 Power := GameTicks; |
6063 // Freeze nearby mines/explosives/cases too |
6296 // Freeze nearby mines/explosives/cases too |
6064 iter := GearsList; |
6297 iter := GearsList; |
6065 while iter <> nil do |
6298 while iter <> nil do |
6066 begin |
6299 begin |
6067 if (iter^.State and gstFrozen = 0) and |
6300 if (iter^.State and gstFrozen = 0) and |
6068 ((iter^.Kind = gtExplosives) or (iter^.Kind = gtCase) or (iter^.Kind = gtMine) or (iter^.Kind = gtSMine)) and |
6301 ((iter^.Kind = gtExplosives) or (iter^.Kind = gtAirMine) or (iter^.Kind = gtCase) or (iter^.Kind = gtMine) or (iter^.Kind = gtSMine)) and |
6069 (abs(LongInt(iter^.X.Round) - target.x) + abs(LongInt(iter^.Y.Round) - target.y) + 2 < 2 * iceRadius) |
6302 (abs(LongInt(iter^.X.Round) - target.x) + abs(LongInt(iter^.Y.Round) - target.y) + 2 < 2 * iceRadius) |
6070 and (Distance(iter^.X - int2hwFloat(target.x), iter^.Y - int2hwFloat(target.y)) < int2hwFloat(iceRadius * 2)) then |
6303 and (Distance(iter^.X - int2hwFloat(target.x), iter^.Y - int2hwFloat(target.y)) < int2hwFloat(iceRadius * 2)) then |
6071 begin |
6304 begin |
6072 for t:= 0 to 5 do |
6305 for t:= 0 to 5 do |
6073 begin |
6306 begin |
6107 begin |
6340 begin |
6108 DeleteCI(iter); |
6341 DeleteCI(iter); |
6109 iter^.State:= iter^.State or gstFrozen; |
6342 iter^.State:= iter^.State or gstFrozen; |
6110 AddCI(iter) |
6343 AddCI(iter) |
6111 end |
6344 end |
6345 else if iter^.Kind = gtAirMine then |
|
6346 begin |
|
6347 iter^.Damage:= 0; |
|
6348 iter^.State:= iter^.State or gstFrozen; |
|
6349 if (hwRound(iter^.X) < RightX) and (hwRound(iter^.X) > 0) and |
|
6350 (hwRound(iter^.Y) < LAND_HEIGHT) and (hwRound(iter^.Y) > 0) then |
|
6351 begin |
|
6352 iter^.X:= int2hwFloat(min(RightX-16,max(hwRound(iter^.X), 16))); |
|
6353 iter^.Y:= int2hwFloat(min(LAND_HEIGHT-16,max(hwRound(iter^.Y),16))); |
|
6354 ForcePlaceOnLand(hwRound(iter^.X)-16, hwRound(iter^.Y)-16, sprFrozenAirMine, 0, lfIce, $FFFFFFFF, false, false, false); |
|
6355 iter^.State:= iter^.State or gstInvisible |
|
6356 end |
|
6357 end |
|
6112 else // gtExplosives |
6358 else // gtExplosives |
6113 begin |
6359 begin |
6114 iter^.State:= iter^.State or gstFrozen; |
6360 iter^.State:= iter^.State or gstFrozen; |
6115 iter^.Health:= iter^.Health + cBarrelHealth |
6361 iter^.Health:= iter^.Health + cBarrelHealth |
6116 end |
6362 end |
6119 end; |
6365 end; |
6120 |
6366 |
6121 // FillRoundInLandWithIce(Target.X, Target.Y, iceRadius); |
6367 // FillRoundInLandWithIce(Target.X, Target.Y, iceRadius); |
6122 SetAllHHToActive; |
6368 SetAllHHToActive; |
6123 Timer := iceWaitCollision; |
6369 Timer := iceWaitCollision; |
6370 Power:= GameTicks |
|
6124 end; |
6371 end; |
6125 |
6372 |
6126 if (Timer = iceCollideWithWater) and ((GameTicks - Power) > groundFreezingTime div 2) then |
6373 if (Timer = iceCollideWithWater) and ((GameTicks - Power) > groundFreezingTime div 2) then |
6127 begin |
6374 begin |
6128 PlaySound(sndHogFreeze); |
6375 PlaySound(sndHogFreeze); |
6177 begin |
6424 begin |
6178 Target.X:= gX; |
6425 Target.X:= gX; |
6179 Target.Y:= gY; |
6426 Target.Y:= gY; |
6180 X:= HHGear^.X; |
6427 X:= HHGear^.X; |
6181 Y:= HHGear^.Y |
6428 Y:= HHGear^.Y |
6182 end; |
6429 end |
6430 else |
|
6431 begin |
|
6432 iter:= CheckGearNear(Gear, gtAirMine, Gear^.Radius*2, Gear^.Radius*2); |
|
6433 if (iter <> nil) and (iter^.State <> gstFrozen) then |
|
6434 begin |
|
6435 Target.X:= gX; |
|
6436 Target.Y:= gY; |
|
6437 X:= HHGear^.X; |
|
6438 Y:= HHGear^.Y |
|
6439 end |
|
6440 end; |
|
6183 if (gX > max(LAND_WIDTH,4096)*2) or |
6441 if (gX > max(LAND_WIDTH,4096)*2) or |
6184 (gX < -max(LAND_WIDTH,4096)) or |
6442 (gX < -max(LAND_WIDTH,4096)) or |
6185 (gY < -max(LAND_HEIGHT,4096)) or |
6443 (gY < -max(LAND_HEIGHT,4096)) or |
6186 (gY > max(LAND_HEIGHT,4096)+512) then |
6444 (gY > max(LAND_HEIGHT,4096)+512) then |
6187 begin |
6445 begin |
6199 gi: PGear; |
6457 gi: PGear; |
6200 begin |
6458 begin |
6201 if Gear^.Timer > 0 then dec(Gear^.Timer) |
6459 if Gear^.Timer > 0 then dec(Gear^.Timer) |
6202 else |
6460 else |
6203 begin |
6461 begin |
6204 if Gear^.Pos = posCaseUtility then |
|
6205 a:= GetUtility(Gear^.Hedgehog) |
|
6206 else |
|
6207 a:= GetAmmo(Gear^.Hedgehog); |
|
6208 CheckSum:= CheckSum xor GameTicks; |
6462 CheckSum:= CheckSum xor GameTicks; |
6209 gi := GearsList; |
6463 gi := GearsList; |
6210 while gi <> nil do |
6464 while gi <> nil do |
6211 begin |
6465 begin |
6212 with gi^ do CheckSum:= CheckSum xor X.round xor X.frac xor dX.round xor dX.frac xor Y.round xor Y.frac xor dY.round xor dY.frac; |
6466 with gi^ do CheckSum:= CheckSum xor X.round xor X.frac xor dX.round xor dX.frac xor Y.round xor Y.frac xor dY.round xor dY.frac; |
6213 AddRandomness(CheckSum); |
6467 AddRandomness(CheckSum); |
6214 if gi^.Kind = gtGenericFaller then gi^.State:= gi^.State and (not gstTmpFlag); |
6468 if (gi^.Kind = gtGenericFaller) and (gi^.Tag = 1) then |
6469 gi^.State:= gi^.State and (not gstTmpFlag); |
|
6215 gi := gi^.NextGear |
6470 gi := gi^.NextGear |
6216 end; |
6471 end; |
6472 if Gear^.Pos = posCaseUtility then |
|
6473 a:= GetUtility(Gear^.Hedgehog) |
|
6474 else a:= GetAmmo(Gear^.Hedgehog); |
|
6217 AddPickup(Gear^.Hedgehog^, a, Gear^.Power, hwRound(Gear^.X), hwRound(Gear^.Y)); |
6475 AddPickup(Gear^.Hedgehog^, a, Gear^.Power, hwRound(Gear^.X), hwRound(Gear^.Y)); |
6218 DeleteGear(Gear) |
6476 DeleteGear(Gear) |
6219 end; |
6477 end; |
6220 end; |
6478 end; |
6221 |
6479 |
6230 exit |
6488 exit |
6231 end; |
6489 end; |
6232 if (Gear^.State and gstTmpFlag <> 0) or (GameTicks and $7 = 0) then |
6490 if (Gear^.State and gstTmpFlag <> 0) or (GameTicks and $7 = 0) then |
6233 begin |
6491 begin |
6234 doStepFallingGear(Gear); |
6492 doStepFallingGear(Gear); |
6235 if (Gear^.State and gstInvisible <> 0) and (GameTicks and $FF = 0) and (hwRound(Gear^.X) < LongInt(leftX)) or (hwRound(Gear^.X) > LongInt(rightX)) or (hwRound(Gear^.Y) < LongInt(topY)) then |
6493 if (Gear^.Tag = 1) and (GameTicks and $FF = 0) and (hwRound(Gear^.X) < LongInt(leftX)) or (hwRound(Gear^.X) > LongInt(rightX)) or (hwRound(Gear^.Y) < LongInt(topY)) then |
6236 begin |
6494 begin |
6237 Gear^.X:= int2hwFloat(GetRandom(rightX-leftX)+leftX); |
6495 Gear^.X:= int2hwFloat(GetRandom(rightX-leftX)+leftX); |
6238 Gear^.Y:= int2hwFloat(GetRandom(LAND_HEIGHT-topY)+topY); |
6496 Gear^.Y:= int2hwFloat(GetRandom(LAND_HEIGHT-topY)+topY); |
6239 Gear^.dX:= _90-(GetRandomf*_360); |
6497 Gear^.dX:= _90-(GetRandomf*_360); |
6240 Gear^.dY:= _90-(GetRandomf*_360) |
6498 Gear^.dY:= _90-(GetRandomf*_360) |
6560 Gear^.RenderTimer:= true |
6818 Gear^.RenderTimer:= true |
6561 else |
6819 else |
6562 Gear^.RenderTimer:= false; |
6820 Gear^.RenderTimer:= false; |
6563 |
6821 |
6564 dec(Gear^.Timer); |
6822 dec(Gear^.Timer); |
6823 end; |
|
6824 |
|
6825 //////////////////////////////////////////////////////////////////////////////// |
|
6826 procedure doStepMinigunWork(Gear: PGear); |
|
6827 var HHGear: PGear; |
|
6828 bullet: PGear; |
|
6829 rx, ry: hwFloat; |
|
6830 gX, gY: LongInt; |
|
6831 begin |
|
6832 AllInactive:= false; |
|
6833 HHGear := Gear^.Hedgehog^.Gear; |
|
6834 if HHGear = nil then |
|
6835 begin |
|
6836 ClearHitOrder(); |
|
6837 DeleteGear(gear); |
|
6838 exit |
|
6839 end; |
|
6840 |
|
6841 HedgehogChAngle(HHGear); |
|
6842 |
|
6843 dec(Gear^.Timer); |
|
6844 if (Gear^.Timer mod 50) = 0 then |
|
6845 begin |
|
6846 Gear^.Tag := ((Gear^.Tag - 1) and 1) + 2; |
|
6847 |
|
6848 gX := hwRound(Gear^.X) + GetLaunchX(amMinigun, hwSign(HHGear^.dX), HHGear^.Angle); |
|
6849 gY := hwRound(Gear^.Y) + GetLaunchY(amMinigun, HHGear^.Angle); |
|
6850 rx := rndSign(getRandomf * _0_2); |
|
6851 ry := rndSign(getRandomf * _0_2); |
|
6852 |
|
6853 bullet:= AddGear(gx, gy, gtMinigunBullet, 0, SignAs(AngleSin(HHGear^.Angle) * _0_8, HHGear^.dX) + rx, AngleCos(HHGear^.Angle) * ( - _0_8) + ry, 0); |
|
6854 bullet^.CollisionMask:= lfNotCurrentMask; |
|
6855 bullet^.WDTimer := Gear^.WDTimer; |
|
6856 Inc(Gear^.WDTimer); |
|
6857 |
|
6858 CreateShellForGear(Gear, Gear^.Tag and 1); |
|
6859 end; |
|
6860 |
|
6861 if (Gear^.Timer = 0) or ((HHGear^.State and gstHHDriven) = 0) then |
|
6862 begin |
|
6863 if (HHGear^.State and gstHHDriven) = 0 then |
|
6864 StopSound(sndMinigun); |
|
6865 HHGear^.State := HHGear^.State and (not gstNotKickable); |
|
6866 ClearHitOrder(); |
|
6867 DeleteGear(Gear); |
|
6868 AfterAttack |
|
6869 end |
|
6870 end; |
|
6871 |
|
6872 procedure doStepMinigun(Gear: PGear); |
|
6873 var HHGear: PGear; |
|
6874 begin |
|
6875 dec(Gear^.Timer); |
|
6876 if (Gear^.Timer mod 100) = 0 then |
|
6877 Gear^.Tag := (Gear^.Tag + 1) and 1; |
|
6878 |
|
6879 if Gear^.Timer = 0 then |
|
6880 begin |
|
6881 Gear^.Tag := 2; |
|
6882 HHGear := Gear^.Hedgehog^.Gear; |
|
6883 HHGear^.Message := HHGear^.Message and (not (gmUp or gmDown)); |
|
6884 HHGear^.State := HHGear^.State or gstNotKickable; |
|
6885 |
|
6886 Gear^.Timer := Gear^.Karma; |
|
6887 Gear^.WDTimer := 0; // Order of the next bullet; |
|
6888 ClearHitOrder(); |
|
6889 Gear^.doStep := @doStepMinigunWork |
|
6890 end; |
|
6891 end; |
|
6892 |
|
6893 //////////////////////////////////////////////////////////////////////////////// |
|
6894 |
|
6895 procedure doStepMinigunBullet(Gear: PGear); |
|
6896 begin |
|
6897 Gear^.Data:= nil; |
|
6898 // remember who fired this |
|
6899 if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) then |
|
6900 Gear^.Data:= Pointer(Gear^.Hedgehog^.Gear); |
|
6901 |
|
6902 Gear^.X := Gear^.X + Gear^.dX * 2; |
|
6903 Gear^.Y := Gear^.Y + Gear^.dY * 2; |
|
6904 Gear^.FlightTime := 0; |
|
6905 Gear^.doStep := @doStepBulletWork |
|
6565 end; |
6906 end; |
6566 |
6907 |
6567 (* |
6908 (* |
6568 This didn't end up getting used, but, who knows, might be reasonable for javellin or something |
6909 This didn't end up getting used, but, who knows, might be reasonable for javellin or something |
6569 // Make the knife initial angle based on the hog attack angle, or is that too hard? |
6910 // Make the knife initial angle based on the hog attack angle, or is that too hard? |