3341 |
3341 |
3342 procedure doStepPortal(Gear: PGear); |
3342 procedure doStepPortal(Gear: PGear); |
3343 var |
3343 var |
3344 iterator, conPortal: PGear; |
3344 iterator, conPortal: PGear; |
3345 s, r, nx, ny, ox, oy, poffs, noffs, pspeed, nspeed: hwFloat; |
3345 s, r, nx, ny, ox, oy, poffs, noffs, pspeed, nspeed: hwFloat; |
3346 hasdxy, isbullet: Boolean; |
3346 hasdxy, isbullet, iscake: Boolean; |
3347 begin |
3347 begin |
3348 doPortalColorSwitch(); |
3348 doPortalColorSwitch(); |
3349 |
3349 |
3350 // destroy portal if ground it was attached too is gone |
3350 // destroy portal if ground it was attached too is gone |
3351 if ((Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0) |
3351 if ((Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0) |
3387 if iterator = nil then |
3387 if iterator = nil then |
3388 break; |
3388 break; |
3389 |
3389 |
3390 // don't port portals or other gear that wouldn't make sense |
3390 // don't port portals or other gear that wouldn't make sense |
3391 if (iterator^.Kind in [gtPortal, gtRope, gtRCPlane]) |
3391 if (iterator^.Kind in [gtPortal, gtRope, gtRCPlane]) |
3392 or (iterator^.PortalCounter > 20) then |
3392 or (iterator^.PortalCounter > 32) then |
3393 continue; |
3393 continue; |
3394 |
3394 |
3395 // don't port hogs on rope |
3395 // don't port hogs on rope |
|
3396 // TODO: this will also prevent hogs while falling after rope use from |
|
3397 // falling through portals... fix that! |
3396 if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) |
3398 if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) |
3397 and (iterator = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = |
3399 and (iterator = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = |
3398 gtRope) then |
3400 gtRope) then |
3399 continue; |
3401 continue; |
3400 |
3402 |
3410 or (iterator^.X > Gear^.X + r) |
3412 or (iterator^.X > Gear^.X + r) |
3411 or (iterator^.Y < Gear^.Y - r) |
3413 or (iterator^.Y < Gear^.Y - r) |
3412 or (iterator^.Y > Gear^.Y + r) then |
3414 or (iterator^.Y > Gear^.Y + r) then |
3413 continue; |
3415 continue; |
3414 |
3416 |
3415 hasdxy := ((iterator^.dX.QWordValue <> 0) or (iterator^.dY.QWordValue <> 0)); |
3417 hasdxy := (((iterator^.dX.QWordValue <> 0) or (iterator^.dY.QWordValue <> 0)) |
3416 |
3418 or ((iterator^.State or gstMoving) = 0)); |
3417 // in case the object is not moving, let's asume it's moving towards the portal |
3419 |
|
3420 // in case the object is not moving, let's asume it's falling towards the portal |
3418 if not hasdxy then |
3421 if not hasdxy then |
3419 begin |
3422 begin |
|
3423 if Gear^.Y < iterator^.Y then |
|
3424 continue; |
3420 ox:= Gear^.X - iterator^.X; |
3425 ox:= Gear^.X - iterator^.X; |
3421 oy:= Gear^.Y - iterator^.Y; |
3426 oy:= Gear^.Y - iterator^.Y; |
3422 end |
3427 end |
3423 else |
3428 else |
3424 begin |
3429 begin |
3425 ox:= iterator^.dX; |
3430 ox:= iterator^.dX; |
3426 oy:= iterator^.dY; |
3431 oy:= iterator^.dY; |
3427 end; |
3432 end; |
3428 |
3433 |
|
3434 // cake will need extra treatment... it's so delicious and moist! |
|
3435 iscake:= (iterator^.Kind = gtCake); |
|
3436 |
3429 // won't port stuff that does not move towards the front/portal entrance |
3437 // won't port stuff that does not move towards the front/portal entrance |
3430 if not (Gear^.dX*ox + Gear^.dY*oy).isNegative then |
3438 if iscake then |
|
3439 begin |
|
3440 if not ((iterator^.X - Gear^.X)*ox + (iterator^.Y - Gear^.Y)*oy).isNegative then |
3431 continue; |
3441 continue; |
|
3442 end |
|
3443 else |
|
3444 if not (Gear^.dX*ox + Gear^.dY*oy).isNegative then |
|
3445 continue; |
3432 |
3446 |
3433 isbullet:= (iterator^.Kind in [gtShotgunShot, gtDEagleShot, gtSniperRifleShot, gtSineGunShot]); |
3447 isbullet:= (iterator^.Kind in [gtShotgunShot, gtDEagleShot, gtSniperRifleShot, gtSineGunShot]); |
3434 |
3448 |
3435 r:= int2hwFloat(iterator^.Radius); |
3449 r:= int2hwFloat(iterator^.Radius); |
3436 |
3450 |
3437 if not isbullet and (iterator^.Kind <> gtCake) then |
3451 if not (isbullet or iscake) then |
3438 begin |
3452 begin |
3439 // wow! good candidate there, let's see if the distance and direction is okay! |
3453 // wow! good candidate there, let's see if the distance and direction is okay! |
3440 if hasdxy then |
3454 if hasdxy then |
3441 begin |
3455 begin |
3442 s := r / Distance(iterator^.dX, iterator^.dY); |
3456 s := r / Distance(iterator^.dX, iterator^.dY); |
3451 |
3465 |
3452 if (hwRound(Distance(Gear^.X-ox,Gear^.Y-oy)) > Gear^.Radius + 1 ) then |
3466 if (hwRound(Distance(Gear^.X-ox,Gear^.Y-oy)) > Gear^.Radius + 1 ) then |
3453 continue; |
3467 continue; |
3454 end; |
3468 end; |
3455 |
3469 |
3456 (* |
|
3457 noTrap := ((not Gear^.dY.isNegative or (Gear^.dY.QWordValue = 0)) |
|
3458 // can't be entered from above |
|
3459 or ((conPortal^.dY.isNegative and not (conPortal^.dY.QWordValue = 0)))); |
|
3460 // can't be left downwards; |
|
3461 |
|
3462 // prevent getting stuck in a ground portal loop |
|
3463 if noTrap and (iterator^.dY.QWordValue < _0_08.QWordValue) then |
|
3464 continue; *) |
|
3465 |
|
3466 // calc gear offset in portal vector direction |
3470 // calc gear offset in portal vector direction |
3467 ox := (iterator^.X - Gear^.X); |
3471 ox := (iterator^.X - Gear^.X); |
3468 oy := (iterator^.Y - Gear^.Y); |
3472 oy := (iterator^.Y - Gear^.Y); |
3469 poffs:= (Gear^.dX * ox + Gear^.dY * oy); |
3473 poffs:= (Gear^.dX * ox + Gear^.dY * oy); |
3470 |
3474 |
3488 ny.isNegative := not ny.isNegative; |
3489 ny.isNegative := not ny.isNegative; |
3489 |
3490 |
3490 // calc gear offset in portal normal vector direction |
3491 // calc gear offset in portal normal vector direction |
3491 noffs:= (nx * ox + ny * oy); |
3492 noffs:= (nx * ox + ny * oy); |
3492 |
3493 |
3493 // move stuff with high normal offset close to the portal's center |
3494 // avoid gravity related loops of not really moving gear |
3494 if not isbullet then |
3495 if not iscake and (Gear^.dY.isNegative) and (conPortal^.dY.isNegative) |
3495 begin |
3496 and ((iterator^.dX.QWordValue + iterator^.dY.QWordValue) < _0_08.QWordValue) |
3496 s := hwAbs(noffs) + r - int2hwFloat(Gear^.Radius); |
3497 and (iterator^.PortalCounter > 0) then |
3497 if s > _0 then |
3498 continue; |
3498 noffs:= noffs - SignAs(s,noffs) |
|
3499 end; |
|
3500 |
|
3501 iterator^.Active := true; |
|
3502 iterator^.State := iterator^.State or gstMoving; |
|
3503 DeleteCI(iterator); |
|
3504 |
3499 |
3505 // Until loops are reliably broken |
3500 // Until loops are reliably broken |
3506 inc(iterator^.PortalCounter); |
3501 inc(iterator^.PortalCounter); |
3507 |
3502 |
3508 // calc gear speed along to the vector and the normal vector of the portal |
3503 // calc gear speed along to the vector and the normal vector of the portal |
3509 pspeed:= (Gear^.dX * iterator^.dX + Gear^.dY * iterator^.dY); |
3504 if hasdxy then |
3510 nspeed:= (nx * iterator^.dX + ny * iterator^.dY); |
3505 begin |
|
3506 pspeed:= (Gear^.dX * iterator^.dX + Gear^.dY * iterator^.dY); |
|
3507 nspeed:= (nx * iterator^.dX + ny * iterator^.dY); |
|
3508 end |
|
3509 else |
|
3510 begin |
|
3511 pspeed:= hwAbs(cGravity * oy); |
|
3512 nspeed:= _0; |
|
3513 end; |
3511 |
3514 |
3512 // creating normal vector of connected (exit) portal |
3515 // creating normal vector of connected (exit) portal |
3513 nx := conPortal^.dY; |
3516 nx := conPortal^.dY; |
3514 ny := conPortal^.dX; |
3517 ny := conPortal^.dX; |
3515 if conPortal^.Elasticity.isNegative then |
3518 if conPortal^.Elasticity.isNegative then |
3516 nx.isNegative := not nx.isNegative |
3519 nx.isNegative := not nx.isNegative |
3517 else |
3520 else |
3518 ny.isNegative := not ny.isNegative; |
3521 ny.isNegative := not ny.isNegative; |
3519 |
3522 |
|
3523 // inverse cake's normal movement direction, |
|
3524 // as if it just walked through a hole |
|
3525 if iscake then |
|
3526 nspeed.isNegative:= not nspeed.isNegative; |
|
3527 |
3520 //AddFileLog('poffs:'+cstr(poffs)+' noffs:'+cstr(noffs)+' pspeed:'+cstr(pspeed)+' nspeed:'+cstr(nspeed)); |
3528 //AddFileLog('poffs:'+cstr(poffs)+' noffs:'+cstr(noffs)+' pspeed:'+cstr(pspeed)+' nspeed:'+cstr(nspeed)); |
3521 iterator^.dX := -pspeed * conPortal^.dX + nspeed * nx; |
3529 iterator^.dX := -pspeed * conPortal^.dX + nspeed * nx; |
3522 iterator^.dY := -pspeed * conPortal^.dY + nspeed * ny; |
3530 iterator^.dY := -pspeed * conPortal^.dY + nspeed * ny; |
3523 if iterator^.Kind = gtCake then |
3531 |
3524 poffs := poffs * _0_5 |
3532 // make the gear's exit position close to the portal while |
3525 else |
3533 // still respecting the movement direction |
3526 if poffs < r + _1_5 then |
3534 |
3527 poffs := r + _1_5; |
3535 // determine the distance (in exit vector direction) |
|
3536 // that we want the gear at |
|
3537 if iscake then |
|
3538 ox:= (r - _0_7) |
|
3539 else |
|
3540 ox:= (r + _1_9); |
|
3541 s:= ox / poffs; |
|
3542 poffs:= ox; |
|
3543 if (nspeed.QWordValue <> 0) and (pspeed > _0) then |
|
3544 noffs:= noffs * s * (nspeed / pspeed); |
|
3545 |
|
3546 // move stuff with high normal offset closer to the portal's center |
|
3547 if not isbullet then |
|
3548 begin |
|
3549 s := hwAbs(noffs) + r - int2hwFloat(Gear^.Radius); |
|
3550 if s > _0 then |
|
3551 noffs:= noffs - SignAs(s,noffs) |
|
3552 end; |
|
3553 |
3528 iterator^.X := conPortal^.X + poffs * conPortal^.dX + noffs * nx; |
3554 iterator^.X := conPortal^.X + poffs * conPortal^.dX + noffs * nx; |
3529 iterator^.Y := conPortal^.Y + poffs * conPortal^.dY + noffs * ny; |
3555 iterator^.Y := conPortal^.Y + poffs * conPortal^.dY + noffs * ny; |
|
3556 |
|
3557 if not hasdxy and not (conPortal^.dY.isNegative) then |
|
3558 begin |
|
3559 iterator^.dY:= iterator^.dY + hwAbs(cGravity * (iterator^.Y - conPortal^.Y)) |
|
3560 end; |
3530 |
3561 |
3531 if not isbullet then |
3562 if not isbullet then |
3532 FollowGear := iterator; |
3563 FollowGear := iterator; |
3533 //AddFileLog('portal''d'); |
3564 //AddFileLog('portal''d'); |
3534 |
3565 |