DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Refire) { PARAM_ACTION_PROLOGUE; PARAM_BOOL_OPT(ignoremissile) { ignoremissile = false; } if (self->target == NULL || self->target->health <= 0) { if (self->MissileState && pr_m_refire() < 160) { // Look for a new target most of the time if (P_LookForPlayers (self, true, NULL) && P_CheckMissileRange (self)) { // Found somebody new and in range, so don't stop shooting return 0; } } self->SetState (self->state + 1); return 0; } if (((ignoremissile || self->MissileState == NULL) && !self->CheckMeleeRange ()) || !P_CheckSight (self, self->target) || pr_m_refire() < 4) // Small chance of stopping even when target not dead { self->SetState (self->state + 1); } return 0; }
void A_FiredChase (AActor *actor) { int weaveindex = actor->special1; AActor *target = actor->target; angle_t ang; fixed_t dist; if (actor->reactiontime) actor->reactiontime--; if (actor->threshold) actor->threshold--; // Float up and down actor->z += FloatBobOffsets[weaveindex]; actor->special1 = (weaveindex+2)&63; // Ensure it stays above certain height if (actor->z < actor->floorz + (64*FRACUNIT)) { actor->z += 2*FRACUNIT; } if(!actor->target || !(actor->target->flags&MF_SHOOTABLE)) { // Invalid target P_LookForPlayers (actor,true); return; } // Strafe if (actor->special2 > 0) { actor->special2--; } else { actor->special2 = 0; actor->momx = actor->momy = 0; dist = P_AproxDistance (actor->x - target->x, actor->y - target->y); if (dist < FIREDEMON_ATTACK_RANGE) { if (pr_firedemonchase() < 30) { ang = R_PointToAngle2 (actor->x, actor->y, target->x, target->y); if (pr_firedemonchase() < 128) ang += ANGLE_90; else ang -= ANGLE_90; ang >>= ANGLETOFINESHIFT; actor->momx = finecosine[ang] << 3; //FixedMul (8*FRACUNIT, finecosine[ang]); actor->momy = finesine[ang] << 3; //FixedMul (8*FRACUNIT, finesine[ang]); actor->special2 = 3; // strafe time } } }
DEFINE_ACTION_FUNCTION(AActor, A_FiredChase) { int weaveindex = self->special1; AActor *target = self->target; angle_t ang; fixed_t dist; if (self->reactiontime) self->reactiontime--; if (self->threshold) self->threshold--; // Float up and down self->z += finesine[weaveindex << BOBTOFINESHIFT] * 8; self->special1 = (weaveindex + 2) & 63; // Ensure it stays above certain height if (self->z < self->floorz + (64*FRACUNIT)) { self->z += 2*FRACUNIT; } if(!self->target || !(self->target->flags&MF_SHOOTABLE)) { // Invalid target P_LookForPlayers (self,true, NULL); return; } // Strafe if (self->special2 > 0) { self->special2--; } else { self->special2 = 0; self->velx = self->vely = 0; dist = P_AproxDistance (self->x - target->x, self->y - target->y); if (dist < FIREDEMON_ATTACK_RANGE) { if (pr_firedemonchase() < 30) { ang = R_PointToAngle2 (self->x, self->y, target->x, target->y); if (pr_firedemonchase() < 128) ang += ANGLE_90; else ang -= ANGLE_90; ang >>= ANGLETOFINESHIFT; self->velx = finecosine[ang] << 3; //FixedMul (8*FRACUNIT, finecosine[ang]); self->vely = finesine[ang] << 3; //FixedMul (8*FRACUNIT, finesine[ang]); self->special2 = 3; // strafe time } } }
DEFINE_ACTION_FUNCTION(AActor, A_M_Refire) { // [BC] Let the server do this. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } if (self->target == NULL || self->target->health <= 0) { if (self->MissileState && pr_m_refire() < 160) { // Look for a new target most of the time if (P_LookForPlayers (self, true) && P_CheckMissileRange (self)) { // Found somebody new and in range, so don't stop shooting return; } } // [BC] Update the thing's state. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SetThingFrame( self, self->state + 1 ); self->SetState (self->state + 1); return; } if ((self->MissileState == NULL && !self->CheckMeleeRange ()) || !P_CheckSight (self, self->target) || pr_m_refire() < 4) // Small chance of stopping even when target not dead { // [BC] Update the thing's state. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SetThingFrame( self, self->state + 1 ); self->SetState (self->state + 1); } }
static void SpawnFly(AActor *self, const PClass *spawntype, FSoundID sound) { AActor *newmobj; AActor *fog; AActor *eye = self->master; // The eye is the spawnshot's master, not the target! AActor *targ = self->target; // Unlike other projectiles, the target is the intended destination. int r; // [GZ] Should be more viable than a countdown... if (self->special2 != 0) { if (self->special2 > level.maptime) return; // still flying } else { if (self->reactiontime == 0 || --self->reactiontime != 0) return; // still flying } if (spawntype != NULL) { fog = Spawn (spawntype, targ->x, targ->y, targ->z, ALLOW_REPLACE); if (fog != NULL) S_Sound (fog, CHAN_BODY, sound, 1, ATTN_NORM); } FName SpawnName; FDropItem *di; // di will be our drop item list iterator FDropItem *drop; // while drop stays as the reference point. int n = 0; // First see if this cube has its own actor list drop = self->GetDropItems(); // If not, then default back to its master's list if (drop == NULL && eye != NULL) drop = eye->GetDropItems(); if (drop != NULL) { for (di = drop; di != NULL; di = di->Next) { if (di->Name != NAME_None) { if (di->amount < 0) { di->amount = 1; // default value is -1, we need a positive value. } n += di->amount; // this is how we can weight the list. } } di = drop; n = pr_spawnfly(n); while (n >= 0) { if (di->Name != NAME_None) { n -= di->amount; // logically, none of the -1 values have survived by now. } if ((di->Next != NULL) && (n >= 0)) { di = di->Next; } else { n = -1; } } SpawnName = di->Name; } if (SpawnName == NAME_None) { // Randomly select monster to spawn. r = pr_spawnfly (); // Probability distribution (kind of :), // decreasing likelihood. if (r < 50) SpawnName = "DoomImp"; else if (r < 90) SpawnName = "Demon"; else if (r < 120) SpawnName = "Spectre"; else if (r < 130) SpawnName = "PainElemental"; else if (r < 160) SpawnName = "Cacodemon"; else if (r < 162) SpawnName = "Archvile"; else if (r < 172) SpawnName = "Revenant"; else if (r < 192) SpawnName = "Arachnotron"; else if (r < 222) SpawnName = "Fatso"; else if (r < 246) SpawnName = "HellKnight"; else SpawnName = "BaronOfHell"; } spawntype = PClass::FindClass(SpawnName); if (spawntype != NULL) { newmobj = Spawn (spawntype, targ->x, targ->y, targ->z, ALLOW_REPLACE); if (newmobj != NULL) { // Make the new monster hate what the boss eye hates if (eye != NULL) { newmobj->CopyFriendliness (eye, false); } // Make it act as if it was around when the player first made noise // (if the player has made noise). newmobj->LastHeard = newmobj->Sector->SoundTarget; if (newmobj->SeeState != NULL && P_LookForPlayers (newmobj, true, NULL)) { newmobj->SetState (newmobj->SeeState); } if (!(newmobj->ObjectFlags & OF_EuthanizeMe)) { // telefrag anything in this spot P_TeleportMove (newmobj, newmobj->x, newmobj->y, newmobj->z, true); } newmobj->flags4 |= MF4_BOSSSPAWNED; } } // remove self (i.e., cube). self->Destroy (); }
DEFINE_ACTION_FUNCTION(AActor, A_FiredChase) { int weaveindex = self->special1; AActor *target = self->target; angle_t ang; fixed_t dist; // [BC] Let the server do this. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { // make active sound if (pr_firedemonchase() < 3) { self->PlayActiveSound (); } // Normal movement if ( self->special2 == 0 ) P_Move( self ); return; } if (self->reactiontime) self->reactiontime--; if (self->threshold) self->threshold--; // Float up and down self->z += FloatBobOffsets[weaveindex]; self->special1 = (weaveindex+2)&63; // Ensure it stays above certain height if (self->z < self->floorz + (64*FRACUNIT)) { self->z += 2*FRACUNIT; } // [BC] If we're the server, update the thing's z position. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_MoveThing( self, CM_Z ); if(!self->target || !(self->target->flags&MF_SHOOTABLE)) { // Invalid target P_LookForPlayers (self,true, NULL); return; } // Strafe if (self->special2 > 0) { self->special2--; } else { self->special2 = 0; self->velx = self->vely = 0; dist = P_AproxDistance (self->x - target->x, self->y - target->y); if (dist < FIREDEMON_ATTACK_RANGE) { if (pr_firedemonchase() < 30) { ang = R_PointToAngle2 (self->x, self->y, target->x, target->y); if (pr_firedemonchase() < 128) ang += ANGLE_90; else ang -= ANGLE_90; ang >>= ANGLETOFINESHIFT; self->velx = finecosine[ang] << 3; //FixedMul (8*FRACUNIT, finecosine[ang]); self->vely = finesine[ang] << 3; //FixedMul (8*FRACUNIT, finesine[ang]); self->special2 = 3; // strafe time } } // [BC] If we're the server, update the thing's z position. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) { SERVERCOMMANDS_MoveThingExact( self, CM_MOMX|CM_MOMY ); SERVERCOMMANDS_SetThingSpecial2( self ); } }