Based upon basic nade esp by bwarrior.
For all projectiles, it shows 2D ESP with distance and remaining fuse time.
For fused grenades this code shows predicted explosion location in the world (as a red sphere).
When you're throwing a grenade, it shows you the trajectory it will fly (as a curve) and the place it will hit (as a green sphere).
And yes, this code misses 1 line as a c+p protection. Ez to find, though.
Code:
FVector ProjLocation(FVector startPos, FVector velocity, FVector accel, FLOAT tTimeDelta)
{
return startPos + FVector(velocity*tTimeDelta + accel * FLOAT(tTimeDelta*tTimeDelta / 2));
}
FVector DoTrace(FVector& StartLocation, FVector& EndLocation)
{
FVector HitLocation, HitNormal;
FTraceHitInfo HitInfo;
APBR::PlayerController->Trace(&HitLocation, &HitNormal, EndLocation,
StartLocation, true, FVector(0, 0, 0), &HitInfo, 0);
return HitLocation;
}
void Projectiles(UCanvas* pCanvas)
{
static FLOAT g; // storing game's gravity
if (g==0)
g = APBR::PlayerController->Pawn->GetGravityZ();
static TArray<AActor*> Actors;
APBR::PlayerController->Pawn->FindActorsOfClass(AcAPBProjectile::StaticClass(), &Actors);
for (int i=0; i<Actors.Count; i++)
{
if (Actors(i))
{
AcAPBProjectile* proj = reinterpret_cast<AcAPBProjectile*>(Actors(i));
FVector LandPos, Coordinate = Toolkit::WorldToScreen(pCanvas, APBR::PlayerController, proj->Location);
if (Coordinate.Z>100) //fake far-away nades
continue;
APBR::PlayerController->DrawDebugSphere(proj->Location, 50, 4, 255,0,0, false);
// can be seen through walls
Toolkit::DrawString(pCanvas, Coordinate.X, Coordinate.Y, APBR::Colors.Red, L"* %0.0fm/%0.1fs", Coordinate.Z, proj->m_FuseTime);
FLOAT ttl = proj->m_FuseTime;
LandPos = ProjLocation(proj->Location, proj->Velocity, FVector(0, 0, g), ttl);
// drawing predicted hit location works only for fused projectiles
APBR::PlayerController->DrawDebugSphere(LandPos, 400, 8, 255,0,0, false);
}
}
AcItem* item = APBR::PlayerController->m_HoldableItemManager->m_CurrentItem;
if (item && item->IsA(AcGrenadeWeapon::StaticClass()))
{
static const int nPoints = 64;
const FLOAT timeStep = 0.05f;
static FLOAT throwForce = 1600; // TODO: pretty accurate, but must revalidate.
AcGrenadeWeapon* nadeWeap = reinterpret_cast<AcGrenadeWeapon*>(item);
AcAPBProjectile* proj = nadeWeap->m_CookingGrenade;
if (!proj)
return;
FVector dirn = APBR::PlayerController->PlayerCamera->Rotation.Vector();
dirn.Normalize();
FVector prevPos = nadeWeap->m_FireStartLocation;
for (int i = 0; (i < nPoints) && (i*timeStep<proj->m_FuseTime); i++)
{
FVector pos = ProjLocation(nadeWeap->m_FireStartLocation, dirn, FVector(0, 0, g), i*0.1);
FVector hit = DoTrace(prevPos, pos); // checking if line segment is broken = we hit something
pos = (hit.Length()) ? hit : pos;
APBR::PlayerController->DrawDebugLine(prevPos, pos, 255, 50, 255, false); // next line segment
prevPos = pos;
if (hit.Length()) // no more tracing
break;
}
APBR::PlayerController->DrawDebugSphere(prevPos, 100, 8, 0, 255, 50, false); // end of trajectory
}
}
Credits:
Joan
bwarrior