|
This article or section is incomplete. It doesn't have all of the necessary core information on this topic. Please help the SRB2 Wiki by finishing this article.
|
A_PointyThink is an action which is used as the thinker for the Pointy. The actor will first search for the nearest living player which it can see, which it will set as its target. The actor will then move at a speed defined by the Object's Speed
value, mirroring its target player's movements – if the player is moving closer to the actor, the actor will move forwards; if the player is moving away however, the actor will move backwards instead.
This action also handles the position and movement of the Pointy's spikeballs, assuming that there are four of them and that they are all linked in a chain starting with the actor, each of them except the last tracer-ing the next spikeball. As the actor moves, each of the spikeball Objects in turn are rotated vertically accordingly. The actor's ReactionTime
determines the multiple of the actor's radius to use as the distance the spikeball Objects are from the actor, i.e. spikeball distance = ReactionTime
×Radius
.
Damage
determines the spikeballs' speed of rotation around the actor when the player moves – note that this is not directly given in degrees/tic, but in a scale where 8192 is 360°/tic, 4096 is 180°/tic, 2048 is 90°/tic, etc. For example, the Pointy has a Damage
value of 128, which converts to 5.625 °/tic.
Object property
|
Use
|
Speed
|
Sets how fast the actor moves forwards/backwards when the player is moving
|
Radius
|
Sets the distance the spikeballs are from the actor (Radius ×ReactionTime )
|
ReactionTime
|
Sets the distance the spikeballs are from the actor (Radius ×ReactionTime )
|
Damage
|
Sets how fast the spikeballs move around the actor when the player is moving
|
Code – A_PointyThink
|
|
// Function: A_PointyThink
//
// Description: Thinker function for Pointy
//
// var1 = unused
// var2 = unused
//
void A_PointyThink(mobj_t *actor)
{
INT32 i;
player_t *player = NULL;
mobj_t *ball;
TVector v;
TVector *res;
angle_t fa;
fixed_t radius = FixedMul(actor->info->radius*actor->info->reactiontime, actor->scale);
boolean firsttime = true;
INT32 sign;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_PointyThink", actor))
return;
#endif
actor->momx = actor->momy = actor->momz = 0;
// Find nearest player
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
if (!players[i].mo)
continue;
if (!players[i].mo->health)
continue;
if (!P_CheckSight(actor, players[i].mo))
continue;
if (firsttime)
{
firsttime = false;
player = &players[i];
}
else
{
if (P_AproxDistance(players[i].mo->x - actor->x, players[i].mo->y - actor->y) <
P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y))
player = &players[i];
}
}
if (!player)
return;
// Okay, we found the closest player. Let's move based on his movement.
P_SetTarget(&actor->target, player->mo);
A_FaceTarget(actor);
if (P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y) < P_AproxDistance(player->mo->x + player->mo->momx - actor->x, player->mo->y + player->mo->momy - actor->y))
sign = -1; // Player is moving away
else
sign = 1; // Player is moving closer
if (player->mo->momx || player->mo->momy)
{
P_InstaThrust(actor, R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y), FixedMul(actor->info->speed*sign, actor->scale));
// Rotate our spike balls
actor->lastlook += actor->info->damage;
actor->lastlook %= FINEANGLES/4;
}
if (!actor->tracer) // For some reason we do not have spike balls...
return;
// Position spike balls relative to the value of 'lastlook'.
ball = actor->tracer;
i = 0;
while (ball)
{
fa = actor->lastlook+i;
v[0] = FixedMul(FINECOSINE(fa),radius);
v[1] = 0;
v[2] = FixedMul(FINESINE(fa),radius);
v[3] = FRACUNIT;
res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(actor->lastlook+i)));
M_Memcpy(&v, res, sizeof (v));
res = VectorMatrixMultiply(v, *RotateZMatrix(actor->angle+ANGLE_180));
M_Memcpy(&v, res, sizeof (v));
P_UnsetThingPosition(ball);
ball->x = actor->x + v[0];
ball->y = actor->y + v[1];
ball->z = actor->z + (actor->height>>1) + v[2];
P_SetThingPosition(ball);
ball = ball->tracer;
i += ANGLE_90 >> ANGLETOFINESHIFT;
}
}
|
|