- refactored the remaining pieces in the ai code to use actors.

This commit is contained in:
Christoph Oelckers 2021-05-05 17:25:37 +02:00
parent d4439b879c
commit 0ee81b2bb8
11 changed files with 72 additions and 79 deletions

View file

@ -6533,11 +6533,9 @@ DBloodActor* actSpawnThing(int nSector, int x, int y, int z, int nThingType)
auto actor = actSpawnSprite(nSector, x, y, z, 4, 1); auto actor = actSpawnSprite(nSector, x, y, z, 4, 1);
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
int nType = nThingType - kThingBase; int nType = nThingType - kThingBase;
int nThing = pSprite->index;
int nXThing = pSprite->extra;
pSprite->type = nThingType; pSprite->type = nThingType;
assert(nXThing > 0 && nXThing < kMaxXSprites); assert(actor->hasX());
XSPRITE* pXThing = &xsprite[nXThing]; XSPRITE* pXThing = &actor->x();
const THINGINFO* pThingInfo = &thingInfo[nType]; const THINGINFO* pThingInfo = &thingInfo[nType];
pXThing->health = pThingInfo->startHealth << 4; pXThing->health = pThingInfo->startHealth << 4;
pSprite->clipdist = pThingInfo->clipdist; pSprite->clipdist = pThingInfo->clipdist;
@ -6601,17 +6599,17 @@ DBloodActor* actSpawnThing(int nSector, int x, int y, int z, int nThingType)
break; break;
case kThingArmedTNTStick: case kThingArmedTNTStick:
evPost(nThing, 3, 0, kCallbackFXDynPuff); evPost(actor, 0, kCallbackFXDynPuff);
sfxPlay3DSound(actor, 450, 0, 0); sfxPlay3DSound(actor, 450, 0, 0);
break; break;
case kThingArmedTNTBundle: case kThingArmedTNTBundle:
sfxPlay3DSound(actor, 450, 0, 0); sfxPlay3DSound(actor, 450, 0, 0);
evPost(nThing, 3, 0, kCallbackFXDynPuff); evPost(actor, 0, kCallbackFXDynPuff);
break; break;
case kThingArmedSpray: case kThingArmedSpray:
evPost(nThing, 3, 0, kCallbackFXDynPuff); evPost(actor, 0, kCallbackFXDynPuff);
break; break;
} }
return actor; return actor;

View file

@ -91,7 +91,7 @@ static void batThinkTarget(DBloodActor* actor)
{ {
pDudeExtraE->thinkTime = 0; pDudeExtraE->thinkTime = 0;
pXSprite->goalAng += 256; pXSprite->goalAng += 256;
POINT3D *pTarget = &baseSprite[pSprite->index]; POINT3D *pTarget = &actor->basePoint();
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z); aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
aiNewState(actor, &batTurn); aiNewState(actor, &batTurn);
return; return;

View file

@ -152,7 +152,7 @@ void StompSeqCallback(int, DBloodActor* actor1)
continue; continue;
if (TestBitString(sectmap, pSprite2->sectnum) && CheckProximity(pSprite2, x, y, z, nSector, vc)) if (TestBitString(sectmap, pSprite2->sectnum) && CheckProximity(pSprite2, x, y, z, nSector, vc))
{ {
XSPRITE *pXSprite = &xsprite[pSprite2->extra]; XSPRITE *pXSprite = &actor2->x();
if (pXSprite->locked) if (pXSprite->locked)
continue; continue;
int dx = abs(pSprite->x-pSprite2->x); int dx = abs(pSprite->x-pSprite2->x);

View file

@ -103,7 +103,7 @@ static void eelThinkTarget(DBloodActor* actor)
{ {
pDudeExtraE->thinkTime = 0; pDudeExtraE->thinkTime = 0;
pXSprite->goalAng += 256; pXSprite->goalAng += 256;
POINT3D *pTarget = &baseSprite[pSprite->index]; POINT3D* pTarget = &actor->basePoint();
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z); aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
aiNewState(actor, &eelTurn); aiNewState(actor, &eelTurn);
return; return;

View file

@ -92,11 +92,10 @@ void cerberusBurnSeqCallback(int, DBloodActor* actor)
aim.dy = SinScale16(pSprite->ang); aim.dy = SinScale16(pSprite->ang);
aim.dz = actor->dudeSlope; aim.dz = actor->dudeSlope;
int nClosest = 0x7fffffff; int nClosest = 0x7fffffff;
int nSprite2; BloodStatIterator it(kStatDude);
StatIterator it(kStatDude); while (auto actor2 = it.Next())
while ((nSprite2 = it.NextIndex()) >= 0)
{ {
spritetype *pSprite2 = &sprite[nSprite2]; spritetype *pSprite2 = &actor2->s();
if (pSprite == pSprite2 || !(pSprite2->flags&8)) if (pSprite == pSprite2 || !(pSprite2->flags&8))
continue; continue;
int x2 = pSprite2->x; int x2 = pSprite2->x;
@ -108,9 +107,9 @@ void cerberusBurnSeqCallback(int, DBloodActor* actor)
if (tt1.at10) if (tt1.at10)
{ {
int t = DivScale(nDist, tt1.at10, 12); int t = DivScale(nDist, tt1.at10, 12);
x2 += (xvel[nSprite2]*t)>>12; x2 += (actor2->xvel() * t) >> 12;
y2 += (yvel[nSprite2]*t)>>12; y2 += (actor2->yvel() * t) >> 12;
z2 += (zvel[nSprite2]*t)>>8; z2 += (actor2->zvel() * t) >> 8;
} }
int tx = x+MulScale(Cos(pSprite->ang), nDist, 30); int tx = x+MulScale(Cos(pSprite->ang), nDist, 30);
int ty = y+MulScale(Sin(pSprite->ang), nDist, 30); int ty = y+MulScale(Sin(pSprite->ang), nDist, 30);
@ -173,11 +172,10 @@ void cerberusBurnSeqCallback2(int, DBloodActor* actor)
aim.dz = actor->dudeSlope; aim.dz = actor->dudeSlope;
az = 0; az = 0;
int nClosest = 0x7fffffff; int nClosest = 0x7fffffff;
int nSprite2; BloodStatIterator it(kStatDude);
StatIterator it(kStatDude); while (auto actor2 = it.Next())
while ((nSprite2 = it.NextIndex()) >= 0)
{ {
spritetype *pSprite2 = &sprite[nSprite2]; spritetype *pSprite2 = &actor2->s();
if (pSprite == pSprite2 || !(pSprite2->flags&8)) if (pSprite == pSprite2 || !(pSprite2->flags&8))
continue; continue;
int x2 = pSprite2->x; int x2 = pSprite2->x;
@ -189,16 +187,16 @@ void cerberusBurnSeqCallback2(int, DBloodActor* actor)
if (tt1.at10) if (tt1.at10)
{ {
int t = DivScale(nDist, tt1.at10, 12); int t = DivScale(nDist, tt1.at10, 12);
x2 += (xvel[nSprite2]*t)>>12; x2 += (actor->xvel() * t) >> 12;
y2 += (yvel[nSprite2]*t)>>12; y2 += (actor->yvel() * t) >> 12;
z2 += (zvel[nSprite2]*t)>>8; z2 += (actor->zvel() * t) >> 8;
} }
int tx = x+MulScale(Cos(pSprite->ang), nDist, 30); int tx = x+MulScale(Cos(pSprite->ang), nDist, 30);
int ty = y+MulScale(Sin(pSprite->ang), nDist, 30); int ty = y+MulScale(Sin(pSprite->ang), nDist, 30);
int tz = z+MulScale(actor->dudeSlope, nDist, 10); int tz = z+MulScale(actor->dudeSlope, nDist, 10);
int tsr = MulScale(9460, nDist, 10); int tsr = MulScale(9460, nDist, 10);
int top, bottom; int top, bottom;
GetSpriteExtents(pSprite2, &top, &bottom); GetActorExtents(actor2, &top, &bottom);
if (tz-tsr > bottom || tz+tsr < top) if (tz-tsr > bottom || tz+tsr < top)
continue; continue;
int dx = (tx-x2)>>4; int dx = (tx-x2)>>4;
@ -261,7 +259,7 @@ static void cerberusThinkTarget(DBloodActor* actor)
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active) else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
{ {
pXSprite->goalAng += 256; pXSprite->goalAng += 256;
POINT3D *pTarget = &baseSprite[pSprite->index]; POINT3D* pTarget = &actor->basePoint();
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z); aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
if (pSprite->type == kDudeCerberusTwoHead) if (pSprite->type == kDudeCerberusTwoHead)
aiNewState(actor, &cerberus139890); aiNewState(actor, &cerberus139890);

View file

@ -187,11 +187,10 @@ void sub_68230(int, DBloodActor* actor)
static char TargetNearExplosion(spritetype *pSprite) static char TargetNearExplosion(spritetype *pSprite)
{ {
int nSprite; BloodSectIterator it(pSprite->sectnum);
SectIterator it(pSprite->sectnum); while (auto actor = it.Next())
while ((nSprite = it.NextIndex()) >= 0)
{ {
if (sprite[nSprite].type == kThingArmedTNTStick || sprite[nSprite].statnum == kStatExplosion) if (actor->s().type == kThingArmedTNTStick || actor->s().statnum == kStatExplosion)
return 1; return 1;
} }
return 0; return 0;

View file

@ -125,12 +125,10 @@ void BlastSSeqCallback(int, DBloodActor* actor)
aim.dy = SinScale16(pSprite->ang); aim.dy = SinScale16(pSprite->ang);
aim.dz = actor->dudeSlope; aim.dz = actor->dudeSlope;
int nClosest = 0x7fffffff; int nClosest = 0x7fffffff;
int nSprite2; BloodStatIterator it(kStatDude);
StatIterator it(kStatDude); while (auto actor2 = it.Next())
while ((nSprite2 = it.NextIndex()) >= 0)
{ {
auto actor2 = &bloodActors[nSprite2]; spritetype* pSprite2 = &actor2->s();
spritetype *pSprite2 = &sprite[nSprite2];
if (pSprite == pSprite2 || !(pSprite2->flags&8)) if (pSprite == pSprite2 || !(pSprite2->flags&8))
continue; continue;
int x2 = pSprite2->x; int x2 = pSprite2->x;
@ -142,9 +140,9 @@ void BlastSSeqCallback(int, DBloodActor* actor)
if (tt.at10) if (tt.at10)
{ {
int t = DivScale(nDist, tt.at10, 12); int t = DivScale(nDist, tt.at10, 12);
x2 += (xvel[nSprite2]*t)>>12; x2 += (actor->xvel() * t) >> 12;
y2 += (yvel[nSprite2]*t)>>12; y2 += (actor->yvel() * t) >> 12;
z2 += (zvel[nSprite2]*t)>>8; z2 += (actor->zvel() * t) >> 8;
} }
int tx = x+MulScale(Cos(pSprite->ang), nDist, 30); int tx = x+MulScale(Cos(pSprite->ang), nDist, 30);
int ty = y+MulScale(Sin(pSprite->ang), nDist, 30); int ty = y+MulScale(Sin(pSprite->ang), nDist, 30);
@ -223,7 +221,7 @@ static void gargThinkTarget(DBloodActor* actor)
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active) else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
{ {
pXSprite->goalAng += 256; pXSprite->goalAng += 256;
POINT3D *pTarget = &baseSprite[pSprite->index]; POINT3D* pTarget = &actor->basePoint();
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z); aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
aiNewState(actor, &gargoyleTurn); aiNewState(actor, &gargoyleTurn);
return; return;

View file

@ -108,11 +108,10 @@ void ghostBlastSeqCallback(int, DBloodActor* actor)
aim.dy = SinScale16(pSprite->ang); aim.dy = SinScale16(pSprite->ang);
aim.dz = actor->dudeSlope; aim.dz = actor->dudeSlope;
int nClosest = 0x7fffffff; int nClosest = 0x7fffffff;
int nSprite2; BloodStatIterator it(kStatDude);
StatIterator it(kStatDude); while (auto actor2 = it.Next())
while ((nSprite2 = it.NextIndex()) >= 0)
{ {
spritetype *pSprite2 = &sprite[nSprite2]; spritetype* pSprite2 = &actor2->s();
if (pSprite == pSprite2 || !(pSprite2->flags&8)) if (pSprite == pSprite2 || !(pSprite2->flags&8))
continue; continue;
int x2 = pSprite2->x; int x2 = pSprite2->x;
@ -124,9 +123,9 @@ void ghostBlastSeqCallback(int, DBloodActor* actor)
if (tt.at10) if (tt.at10)
{ {
int t = DivScale(nDist, tt.at10, 12); int t = DivScale(nDist, tt.at10, 12);
x2 += (xvel[nSprite2]*t)>>12; x2 += (actor->xvel() * t) >> 12;
y2 += (yvel[nSprite2]*t)>>12; y2 += (actor->yvel() * t) >> 12;
z2 += (zvel[nSprite2]*t)>>8; z2 += (actor->zvel() * t) >> 8;
} }
int tx = x+MulScale(Cos(pSprite->ang), nDist, 30); int tx = x+MulScale(Cos(pSprite->ang), nDist, 30);
int ty = y+MulScale(Sin(pSprite->ang), nDist, 30); int ty = y+MulScale(Sin(pSprite->ang), nDist, 30);
@ -199,7 +198,7 @@ static void ghostThinkTarget(DBloodActor* actor)
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active) else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
{ {
pXSprite->goalAng += 256; pXSprite->goalAng += 256;
POINT3D *pTarget = &baseSprite[pSprite->index]; POINT3D* pTarget = &actor->basePoint();
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z); aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
aiNewState(actor, &ghostTurn); aiNewState(actor, &ghostTurn);
return; return;

View file

@ -44,11 +44,9 @@ AISTATE spidBite = { kAiStateChase, 6, nSpidBiteClient, 60, NULL, NULL, NULL, &s
AISTATE spidJump = { kAiStateChase, 8, nSpidJumpClient, 60, NULL, aiMoveForward, NULL, &spidChase }; AISTATE spidJump = { kAiStateChase, 8, nSpidJumpClient, 60, NULL, aiMoveForward, NULL, &spidChase };
AISTATE spidBirth = { kAiStateOther, 0, nSpidBirthClient, 60, NULL, NULL, NULL, &spidIdle }; AISTATE spidBirth = { kAiStateOther, 0, nSpidBirthClient, 60, NULL, NULL, NULL, &spidIdle };
static char SpidPoisonPlayer(XSPRITE *pXDude, int nBlind, int max) static char spidBlindEffect(DBloodActor* dudeactor, int nBlind, int max)
{ {
assert(pXDude != NULL); spritetype *pDude = &dudeactor->s();
int nDude = pXDude->reference;
spritetype *pDude = &sprite[nDude];
if (IsPlayerSprite(pDude)) if (IsPlayerSprite(pDude))
{ {
nBlind <<= 4; nBlind <<= 4;
@ -74,15 +72,19 @@ void SpidBiteSeqCallback(int, DBloodActor* actor)
int dz = Random2(2000); int dz = Random2(2000);
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
if (!actor->ValidateTarget(__FUNCTION__)) return; if (!actor->ValidateTarget(__FUNCTION__)) return;
spritetype *pTarget = &actor->GetTarget()->s();
XSPRITE* pXTarget = &actor->GetTarget()->x();
if (IsPlayerSprite(pTarget)) {
auto const target = actor->GetTarget();
spritetype *pTarget = &target->s();
XSPRITE* pXTarget = &target->x();
if (IsPlayerSprite(pTarget))
{
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
if (hit == 3 && gHitInfo.hitactor->IsPlayerActor()) { if (hit == 3 && gHitInfo.hitactor->IsPlayerActor())
{
dz += pTarget->z - pSprite->z; dz += pTarget->z - pSprite->z;
PLAYER *pPlayer = &gPlayer[pTarget->type - kDudePlayer1]; PLAYER *pPlayer = &gPlayer[pTarget->type - kDudePlayer1];
switch (pSprite->type) { switch (pSprite->type)
{
case kDudeSpiderBrown: case kDudeSpiderBrown:
actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite); actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite);
if (IsPlayerSprite(pTarget) && !pPlayer->godMode && powerupCheck(pPlayer, kPwUpDeathMask) <= 0 && Chance(0x4000)) if (IsPlayerSprite(pTarget) && !pPlayer->godMode && powerupCheck(pPlayer, kPwUpDeathMask) <= 0 && Chance(0x4000))
@ -90,22 +92,21 @@ void SpidBiteSeqCallback(int, DBloodActor* actor)
break; break;
case kDudeSpiderRed: case kDudeSpiderRed:
actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite); actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite);
if (Chance(0x5000)) SpidPoisonPlayer(pXTarget, 4, 16); if (Chance(0x5000)) spidBlindEffect(target, 4, 16);
break; break;
case kDudeSpiderBlack: case kDudeSpiderBlack:
actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite); actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite);
SpidPoisonPlayer(pXTarget, 8, 16); spidBlindEffect(target, 8, 16);
break; break;
case kDudeSpiderMother: { case kDudeSpiderMother:
actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite); actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite);
dx += Random2(2000); dx += Random2(2000);
dy += Random2(2000); dy += Random2(2000);
dz += Random2(2000); dz += Random2(2000);
actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite); actFireVector(actor, 0, 0, dx, dy, dz, kVectorSpiderBite);
SpidPoisonPlayer(pXTarget, 8, 16); spidBlindEffect(target, 8, 16);
break; break;
}
} }
} }

View file

@ -78,11 +78,10 @@ void sub_71BD4(int, DBloodActor* actor)
aim.dy = SinScale16(pSprite->ang); aim.dy = SinScale16(pSprite->ang);
aim.dz = actor->dudeSlope; aim.dz = actor->dudeSlope;
int nClosest = 0x7fffffff; int nClosest = 0x7fffffff;
int nSprite2; BloodStatIterator it(kStatDude);
StatIterator it(kStatDude); while (auto actor2 = it.Next())
while ((nSprite2 = it.NextIndex()) >= 0)
{ {
spritetype *pSprite2 = &sprite[nSprite2]; spritetype* pSprite2 = &actor2->s();
if (pSprite == pSprite2 || !(pSprite2->flags&8)) if (pSprite == pSprite2 || !(pSprite2->flags&8))
continue; continue;
int x2 = pSprite2->x; int x2 = pSprite2->x;
@ -94,9 +93,9 @@ void sub_71BD4(int, DBloodActor* actor)
if (tt.at10) if (tt.at10)
{ {
int t = DivScale(nDist, tt.at10, 12); int t = DivScale(nDist, tt.at10, 12);
x2 += (xvel[nSprite2]*t)>>12; x2 += (actor->xvel() * t) >> 12;
y2 += (yvel[nSprite2]*t)>>12; y2 += (actor->yvel() * t) >> 12;
z2 += (zvel[nSprite2]*t)>>8; z2 += (actor->zvel() * t) >> 8;
} }
int tx = x+MulScale(Cos(pSprite->ang), nDist, 30); int tx = x+MulScale(Cos(pSprite->ang), nDist, 30);
int ty = y+MulScale(Sin(pSprite->ang), nDist, 30); int ty = y+MulScale(Sin(pSprite->ang), nDist, 30);
@ -154,11 +153,10 @@ void sub_720AC(int, DBloodActor* actor)
aim.dz = actor->dudeSlope; aim.dz = actor->dudeSlope;
int nClosest = 0x7fffffff; int nClosest = 0x7fffffff;
az = 0; az = 0;
int nSprite2; BloodStatIterator it(kStatDude);
StatIterator it(kStatDude); while (auto actor2 = it.Next())
while ((nSprite2 = it.NextIndex()) >= 0)
{ {
spritetype *pSprite2 = &sprite[nSprite2]; spritetype* pSprite2 = &actor2->s();
if (pSprite == pSprite2 || !(pSprite2->flags&8)) if (pSprite == pSprite2 || !(pSprite2->flags&8))
continue; continue;
int x2 = pSprite2->x; int x2 = pSprite2->x;
@ -170,9 +168,9 @@ void sub_720AC(int, DBloodActor* actor)
if (tt.at10) if (tt.at10)
{ {
int t = DivScale(nDist, tt.at10, 12); int t = DivScale(nDist, tt.at10, 12);
x2 += (xvel[nSprite2]*t)>>12; x2 += (actor->xvel()*t)>>12;
y2 += (yvel[nSprite2]*t)>>12; y2 += (actor->yvel()*t)>>12;
z2 += (zvel[nSprite2]*t)>>8; z2 += (actor->zvel()*t)>>8;
} }
int tx = x+MulScale(Cos(pSprite->ang), nDist, 30); int tx = x+MulScale(Cos(pSprite->ang), nDist, 30);
int ty = y+MulScale(Sin(pSprite->ang), nDist, 30); int ty = y+MulScale(Sin(pSprite->ang), nDist, 30);
@ -233,7 +231,7 @@ static void sub_725A4(DBloodActor* actor)
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active) else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
{ {
pXSprite->goalAng += 256; pXSprite->goalAng += 256;
POINT3D *pTarget = &baseSprite[pSprite->index]; POINT3D* pTarget = &actor->basePoint();
aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z); aiSetTarget(actor, pTarget->x, pTarget->y, pTarget->z);
aiNewState(actor, &tcherno13AA28); aiNewState(actor, &tcherno13AA28);
return; return;

View file

@ -183,13 +183,15 @@ void punchCallback(int, DBloodActor* actor)
{ {
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor->x();
spritetype* pSprite = &actor->s(); spritetype* pSprite = &actor->s();
if (pXSprite->target_i != -1) auto const target = actor->GetTarget();
if (target != nullptr)
{ {
int nZOffset1 = getDudeInfo(pSprite->type)->eyeHeight * pSprite->yrepeat << 2; int nZOffset1 = getDudeInfo(pSprite->type)->eyeHeight * pSprite->yrepeat << 2;
int nZOffset2 = 0; int nZOffset2 = 0;
spritetype* pTarget = &sprite[pXSprite->target_i];
if(IsDudeSprite(pTarget)) spritetype* pTarget = &target->s();
if(target->IsDudeActor())
nZOffset2 = getDudeInfo(pTarget->type)->eyeHeight * pTarget->yrepeat << 2; nZOffset2 = getDudeInfo(pTarget->type)->eyeHeight * pTarget->yrepeat << 2;
int dx = CosScale16(pSprite->ang); int dx = CosScale16(pSprite->ang);