DEFINE_ACTION_FUNCTION(AActor, A_RocketInFlight) { AActor *trail; S_Sound (self, CHAN_VOICE, "misc/missileinflight", 1, ATTN_NORM); P_SpawnPuff (self, PClass::FindClass("MiniMissilePuff"), self->Pos(), self->angle - ANGLE_180, 2, PF_HITTHING); trail = Spawn("RocketTrail", self->Vec3Offset(-self->velx, -self->vely, 0), ALLOW_REPLACE); if (trail != NULL) { trail->velz = FRACUNIT; } }
DEFINE_ACTION_FUNCTION(AActor, A_RocketInFlight) { PARAM_ACTION_PROLOGUE; AActor *trail; S_Sound (self, CHAN_VOICE, "misc/missileinflight", 1, ATTN_NORM); P_SpawnPuff (self, PClass::FindActor("MiniMissilePuff"), self->Pos(), self->Angles.Yaw - 180, self->Angles.Yaw - 180, 2, PF_HITTHING); trail = Spawn("RocketTrail", self->Vec3Offset(-self->Vel.X, -self->Vel.Y, 0.), ALLOW_REPLACE); if (trail != NULL) { trail->Vel.Z = 1; } return 0; }
DEFINE_ACTION_FUNCTION(AActor, A_Tracer) { angle_t exact; fixed_t dist; fixed_t slope; AActor *dest; AActor *smoke; // killough 1/18/98: this is why some missiles do not have smoke // and some do. Also, internal demos start at random gametics, thus // the bug in which revenants cause internal demos to go out of sync. // // killough 3/6/98: fix revenant internal demo bug by subtracting // levelstarttic from gametic: // // [RH] level.time is always 0-based, so nothing special to do here. if (level.time & 3) return; // spawn a puff of smoke behind the rocket P_SpawnPuff (self, PClass::FindClass(NAME_BulletPuff), self->x, self->y, self->z, 0, 3); smoke = Spawn ("RevenantTracerSmoke", self->x - self->velx, self->y - self->vely, self->z, ALLOW_REPLACE); smoke->velz = FRACUNIT; smoke->tics -= pr_tracer()&3; if (smoke->tics < 1) smoke->tics = 1; // adjust direction dest = self->tracer; if (!dest || dest->health <= 0 || self->Speed == 0 || !self->CanSeek(dest)) return; // change angle exact = R_PointToAngle2 (self->x, self->y, dest->x, dest->y); if (exact != self->angle) { if (exact - self->angle > 0x80000000) { self->angle -= TRACEANGLE; if (exact - self->angle < 0x80000000) self->angle = exact; } else { self->angle += TRACEANGLE; if (exact - self->angle > 0x80000000) self->angle = exact; } } exact = self->angle>>ANGLETOFINESHIFT; self->velx = FixedMul (self->Speed, finecosine[exact]); self->vely = FixedMul (self->Speed, finesine[exact]); if (!(self->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER))) { // change slope dist = P_AproxDistance (dest->x - self->x, dest->y - self->y); dist = dist / self->Speed; if (dist < 1) dist = 1; if (dest->height >= 56*FRACUNIT) { slope = (dest->z+40*FRACUNIT - self->z) / dist; } else { slope = (dest->z + self->height*2/3 - self->z) / dist; } if (slope < self->velz) self->velz -= FRACUNIT/8; else self->velz += FRACUNIT/8; } }
// // A_Tracer // // (Accidentally?) randomized homing missile maintenance. // ioanch 20151230: fixed to be portal-aware // void A_Tracer(actionargs_t *actionargs) { angle_t exact; fixed_t dist; fixed_t slope; Mobj *actor = actionargs->actor; Mobj *dest; Mobj *th; // killough 1/18/98: this is why some missiles do not have smoke // and some do. Also, internal demos start at random gametics, // thus the bug in which revenants cause internal demos to go out // of sync. // // killough 3/6/98: fix revenant internal demo bug by subtracting // levelstarttic from gametic. // // killough 9/29/98: use new "basetic" so that demos stay in sync // during pauses and menu activations, while retaining old demo // sync. // // leveltime would have been better to use to start with in Doom, // but since old demos were recorded using gametic, we must stick // with it, and improvise around it (using leveltime causes desync // across levels). if((gametic-basetic) & 3) return; // spawn a puff of smoke behind the rocket P_SpawnPuff(actor->x, actor->y, actor->z, 0, 3, false); th = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momy, actor->z, E_SafeThingType(MT_SMOKE)); th->momz = FRACUNIT; th->tics -= P_Random(pr_tracer) & 3; if(th->tics < 1) th->tics = 1; // adjust direction dest = actor->tracer; if(!dest || dest->health <= 0) return; fixed_t dx = getThingX(actor, dest); fixed_t dy = getThingY(actor, dest); fixed_t dz = getThingZ(actor, dest); // change angle exact = P_PointToAngle(actor->x, actor->y, dx, dy); if(exact != actor->angle) { if(exact - actor->angle > 0x80000000) { actor->angle -= TRACEANGLE; if(exact - actor->angle < 0x80000000) actor->angle = exact; } else { actor->angle += TRACEANGLE; if(exact - actor->angle > 0x80000000) actor->angle = exact; } } exact = actor->angle>>ANGLETOFINESHIFT; actor->momx = FixedMul(actor->info->speed, finecosine[exact]); actor->momy = FixedMul(actor->info->speed, finesine[exact]); // change slope dist = P_AproxDistance(dx - actor->x, dy - actor->y); dist = dist / actor->info->speed; if(dist < 1) dist = 1; slope = (dz + 40*FRACUNIT - actor->z) / dist; if(slope < actor->momz) actor->momz -= FRACUNIT/8; else actor->momz += FRACUNIT/8; }
void P_XYMovement(mobj_t *mo) { player_t *player; fixed_t xmove, ymove; if (!mo->momx && !mo->momy) { if (mo->flags & MF_SKULLFLY) { // the skull slammed into something mo->flags &= ~MF_SKULLFLY; mo->momx = mo->momy = mo->momz = 0; P_SetMobjState(mo, (statenum_t)mo->info->spawnstate); } return; } player = mo->player; if (mo->type == MT_ROCKET) { if (puffcount++ > 1) P_SpawnPuff(mo->x, mo->y, mo->z, mo->angle); } if (mo->momx > MAXMOVE) mo->momx = MAXMOVE; else if (mo->momx < -MAXMOVE) mo->momx = -MAXMOVE; if (mo->momy > MAXMOVE) mo->momy = MAXMOVE; else if (mo->momy < -MAXMOVE) mo->momy = -MAXMOVE; xmove = mo->momx; ymove = mo->momy; do { fixed_t ptryx, ptryy; if (xmove > MAXMOVE / 2 || ymove > MAXMOVE / 2 || xmove < -MAXMOVE / 2 || ymove < -MAXMOVE / 2) { ptryx = mo->x + xmove / 2; ptryy = mo->y + ymove / 2; xmove >>= 1; ymove >>= 1; } else { ptryx = mo->x + xmove; ptryy = mo->y + ymove; xmove = ymove = 0; } if (!P_TryMove(mo, ptryx, ptryy)) { // blocked move if (mo->player) { // try to slide along it P_SlideMove(mo); } else if (mo->flags & MF_MISSILE) { // explode a missile if (ceilingline && ceilingline->backsector && ceilingline->backsector->ceilingpic == skyflatnum && mo->z > ceilingline->backsector->ceilingheight) { // Hack to prevent missiles exploding // against the sky. // Does not handle sky floors. shootingsky = true; P_RemoveMobj(mo); return; } P_ExplodeMissile(mo); } else { mo->momx = mo->momy = 0; } } }