static int STACK_ARGS segcmp(const void * a, const void * b) { seg_t * seg1 = *((seg_t**)a); seg_t * seg2 = *((seg_t**)b); return P_AproxDistance(seg2->v1->x - compareseg->v1->x, seg2->v1->y - compareseg->v1->y) - P_AproxDistance(seg1->v1->x - compareseg->v1->x, seg1->v1->y - compareseg->v1->y); //return (seg2->v1 - compareseg->v1).LengthSquared() - (seg1->v1 - compareseg->v1).LengthSquared(); }
void A_InquisitorJump (AActor *self) { fixed_t dist; fixed_t speed; angle_t an; if (self->target == NULL) return; S_LoopedSound (self, CHAN_ITEM, "inquisitor/jump", 1, ATTN_NORM); self->z += 64*FRACUNIT; A_FaceTarget (self); an = self->angle >> ANGLETOFINESHIFT; speed = self->Speed * 2/3; self->momx += FixedMul (speed, finecosine[an]); self->momy += FixedMul (speed, finesine[an]); dist = P_AproxDistance (self->target->x - self->x, self->target->y - self->y); dist /= speed; if (dist < 1) { dist = 1; } self->momz = (self->target->z - self->z) / dist; self->reactiontime = 60; self->flags |= MF_NOGRAVITY; }
int DEarthquake::StaticGetQuakeIntensity (AActor *victim) { int intensity = 0; TThinkerIterator<DEarthquake> iterator (STAT_EARTHQUAKE); DEarthquake *quake; if (victim->player != NULL && (victim->player->cheats & CF_NOCLIP)) { return 0; } while ( (quake = iterator.Next()) != NULL) { if (quake->m_Spot != NULL) { fixed_t dist = P_AproxDistance (victim->x - quake->m_Spot->x, victim->y - quake->m_Spot->y); if (dist < quake->m_TremorRadius) { if (intensity < quake->m_Intensity) intensity = quake->m_Intensity; } } } return intensity; }
void APowerSpeed::DoEffect () { if (Owner->player->cheats & CF_PREDICTING) return; if (level.time & 1) return; if (P_AproxDistance (Owner->momx, Owner->momy) <= 12*FRACUNIT) return; AActor *speedMo = Spawn<APlayerSpeedTrail> (Owner->x, Owner->y, Owner->z); if (speedMo) { speedMo->angle = Owner->angle; speedMo->Translation = Owner->Translation; speedMo->target = Owner; speedMo->sprite = Owner->sprite; speedMo->frame = Owner->frame; speedMo->floorclip = Owner->floorclip; if (Owner == players[consoleplayer].camera && !(Owner->player->cheats & CF_CHASECAM)) { speedMo->renderflags |= RF_INVISIBLE; } } }
void A_ImpMsAttack (AActor *self) { AActor *dest; angle_t an; int dist; if (!self->target || pr_impmsatk() > 64) { self->SetState (self->SeeState); return; } dest = self->target; self->flags |= MF_SKULLFLY; S_SoundID (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); A_FaceTarget (self); an = self->angle >> ANGLETOFINESHIFT; self->momx = FixedMul (12*FRACUNIT, finecosine[an]); self->momy = FixedMul (12*FRACUNIT, finesine[an]); dist = P_AproxDistance (dest->x - self->x, dest->y - self->y); dist = dist/(12*FRACUNIT); if (dist < 1) { dist = 1; } self->momz = (dest->z + (dest->height>>1) - self->z)/dist; }
void A_Tracer2 (AActor *self) { AActor *dest; angle_t exact; fixed_t dist; fixed_t slope; dest = self->tracer; if (dest == NULL || dest->health <= 0 || self->Speed == 0) 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->momx = FixedMul (self->Speed, finecosine[exact]); self->momy = FixedMul (self->Speed, finesine[exact]); // change slope dist = P_AproxDistance (dest->x - self->x, dest->y - self->y); 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->momz) { self->momz -= FRACUNIT/8; } else { self->momz += FRACUNIT/8; } }
//MAKEME: Make this a smart decision AActor *DCajunMaster::Find_enemy (AActor *bot) { int count; fixed_t closest_dist, temp; //To target. AActor *target; angle_t vangle; AActor *observer; if (!deathmatch) { // [RH] Take advantage of the Heretic/Hexen code to be a little smarter return P_RoughMonsterSearch (bot, 20); } //Note: It's hard to ambush a bot who is not alone if (bot->player->allround || bot->player->mate) vangle = ANGLE_MAX; else vangle = ENEMY_SCAN_FOV; bot->player->allround = false; target = NULL; closest_dist = FIXED_MAX; if (bot_observer) observer = players[consoleplayer].mo; else observer = NULL; for (count = 0; count < MAXPLAYERS; count++) { player_t *client = &players[count]; if (playeringame[count] && !bot->IsTeammate (client->mo) && client->mo != observer && client->mo->health > 0 && bot != client->mo) { if (Check_LOS (bot, client->mo, vangle)) //Here's a strange one, when bot is standing still, the P_CheckSight within Check_LOS almost always returns false. tought it should be the same checksight as below but.. (below works) something must be f****n wierd screded up. //if(P_CheckSight( bot, players[count].mo)) { temp = P_AproxDistance (client->mo->x - bot->x, client->mo->y - bot->y); //Too dark? if (temp > DARK_DIST && client->mo->Sector->lightlevel < WHATS_DARK && bot->player->Powers & PW_INFRARED) continue; if (temp < closest_dist) { closest_dist = temp; target = client->mo; } } } } return target; }
bool Sys_1ed64 (AActor *self) { if (P_CheckSight (self, self->target) && self->reactiontime == 0) { return P_AproxDistance (self->x - self->target->x, self->y - self->target->y) < 264*FRACUNIT; } return false; }
bool InquisitorCheckDistance (AActor *self) { if (self->reactiontime == 0 && P_CheckSight (self, self->target)) { return P_AproxDistance (self->x - self->target->x, self->y - self->target->y) < 264*FRACUNIT; } return false; }
angle_t DCajunMaster::FireRox (AActor *bot, AActor *enemy, ticcmd_t *cmd) { fixed_t dist; angle_t ang; AActor *actor; int m; SetBodyAt (bot->x + FixedMul(bot->momx, 5*FRACUNIT), bot->y + FixedMul(bot->momy, 5*FRACUNIT), bot->z + (bot->height / 2), 2); actor = bglobal.body2; dist = P_AproxDistance (actor->x-enemy->x, actor->y-enemy->y); if (dist < SAFE_SELF_MISDIST) return 0; //Predict. m = (((dist+1)/FRACUNIT) / GetDefault<ARocket>()->Speed); SetBodyAt (enemy->x + FixedMul (enemy->momx, (m+2*FRACUNIT)), enemy->y + FixedMul(enemy->momy, (m+2*FRACUNIT)), ONFLOORZ, 1); dist = P_AproxDistance(actor->x-bglobal.body1->x, actor->y-bglobal.body1->y); //try the predicted location if (P_CheckSight (actor, bglobal.body1, 1)) //See the predicted location, so give a test missile { if (SafeCheckPosition (bot, actor->x, actor->y)) { if (FakeFire (actor, bglobal.body1, cmd) >= SAFE_SELF_MISDIST) { ang = R_PointToAngle2 (actor->x, actor->y, bglobal.body1->x, bglobal.body1->y); return ang; } } } //Try fire straight. if (P_CheckSight (actor, enemy, 0)) { if (FakeFire (bot, enemy, cmd) >= SAFE_SELF_MISDIST) { ang = R_PointToAngle2(bot->x, bot->y, enemy->x, enemy->y); return ang; } } return 0; }
void DBot::Pitch (AActor *target) { double aim; double diff; diff = target->z - player->mo->z; aim = atan (diff / (double)P_AproxDistance (player->mo->x - target->x, player->mo->y - target->y)); player->mo->pitch = -(int)(aim * ANGLE_180/M_PI); }
void FCajunMaster::Pitch (AActor *actor, AActor *target) { double aim; double diff; diff = target->z - actor->z; aim = atan (diff / (double)P_AproxDistance (actor->x - target->x, actor->y - target->y)); actor->pitch = -(int)(aim * ANGLE_180/M_PI); }
/** \brief The P_Teleport function \param thing mobj_t to teleport \param x new x pos \param y new y pos \param z new y pos \param angle new angle to look at \return if true, the thing "teleported" */ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, boolean flash, boolean dontstopmove) { if (!P_TeleportMove(thing, x, y, z)) return false; thing->angle = angle; if (!dontstopmove) thing->momx = thing->momy = thing->momz = 0; else // Change speed to match direction P_InstaThrust(thing, thing->angle, P_AproxDistance(thing->momx, thing->momy)); if (thing->player) { if (thing->eflags & MFE_VERTICALFLIP) thing->player->viewz = thing->z + thing->height - thing->player->viewheight; else thing->player->viewz = thing->z + thing->player->viewheight; if (!dontstopmove) thing->reactiontime = TICRATE/2; // don't move for about half a second // absolute angle position if (thing->player == &players[consoleplayer]) localangle = angle; if (splitscreen && thing->player == &players[secondarydisplayplayer]) localangle2 = angle; // move chasecam at new player location if (splitscreen && cv_chasecam2.value && thing->player == &players[secondarydisplayplayer]) { P_ResetCamera(thing->player, &camera2); } else if (cv_chasecam.value && thing->player == &players[displayplayer]) P_ResetCamera(thing->player, &camera); // don't run in place after a teleport if (!dontstopmove) { thing->player->cmomx = thing->player->cmomy = 0; thing->player->rmomx = thing->player->rmomy = 0; thing->player->speed = 0; P_ResetPlayer(thing->player); P_SetPlayerMobjState(thing, S_PLAY_STND); } if (flash) thing->player->bonuscount = 10; // flash the palette } return true; }
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 } } }
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 } } }
void P_DSparilTeleport (AActor *actor) { int i; fixed_t prevX; fixed_t prevY; fixed_t prevZ; AActor *mo; ASorcerer2 *self = static_cast<ASorcerer2 *> (actor); ABossSpot *spot; ABossSpot *initial; if (!self->NumBossSpots) { // No spots return; } i = pr_dst () % self->NumBossSpots; spot = static_cast<ABossSpot *> (self->FirstBossSpot); while (i-- > 0) { spot = spot->NextSpot; } initial = spot; while (P_AproxDistance (actor->x - spot->x, actor->y - spot->y) < 128*FRACUNIT) { spot = spot->NextSpot; if (spot == NULL) { spot = static_cast<ABossSpot *> (self->FirstBossSpot); } if (spot == initial) { // [RH] Don't inifinite loop if no spots further than 128*FRACUNIT return; } } prevX = actor->x; prevY = actor->y; prevZ = actor->z; if (P_TeleportMove (actor, spot->x, spot->y, spot->z, false)) { mo = Spawn<ASorcerer2Telefade> (prevX, prevY, prevZ, ALLOW_REPLACE); S_Sound (mo, CHAN_BODY, "misc/teleport", 1, ATTN_NORM); actor->SetState (&ASorcerer2::States[S_SOR2_TELE]); S_Sound (actor, CHAN_BODY, "misc/teleport", 1, ATTN_NORM); actor->z = actor->floorz; actor->angle = spot->angle; actor->momx = actor->momy = actor->momz = 0; } }
void DEarthquake::Tick () { int i; if (m_Spot == NULL) { Destroy (); return; } if (!S_IsActorPlayingSomething (m_Spot, CHAN_BODY, m_QuakeSFX)) { S_Sound (m_Spot, CHAN_BODY | CHAN_LOOP, m_QuakeSFX, 1, ATTN_NORM); } if (m_DamageRadius > 0) { for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i] && !(players[i].cheats & CF_NOCLIP)) { AActor *victim = players[i].mo; fixed_t dist; dist = P_AproxDistance (victim->x - m_Spot->x, victim->y - m_Spot->y); // Check if in damage radius if (dist < m_DamageRadius && victim->z <= victim->floorz) { if (pr_quake() < 50) { P_DamageMobj (victim, NULL, NULL, pr_quake.HitDice (1), NAME_None); } // Thrust player around angle_t an = victim->angle + ANGLE_1*pr_quake(); if (m_IntensityX == m_IntensityY) { // Thrust in a circle P_ThrustMobj (victim, an, m_IntensityX << (FRACBITS-1)); } else { // Thrust in an ellipse an >>= ANGLETOFINESHIFT; // So this is actually completely wrong, but it ought to be good // enough. Otherwise, I'd have to use tangents and square roots. victim->velx += FixedMul(m_IntensityX << (FRACBITS-1), finecosine[an]); victim->vely += FixedMul(m_IntensityY << (FRACBITS-1), finesine[an]); } } } } }
// // P_CheckMissileRange // boolean P_CheckMissileRange (mobj_t* actor) { fixed_t dist; if (! P_CheckSight (actor, actor->target) ) return false; if ( actor->flags & MF_JUSTHIT ) { // the target just hit the enemy, // so fight back! actor->flags &= ~MF_JUSTHIT; return true; } if (actor->reactiontime) return false; // do not attack yet // OPTIMIZE: get this from a global checksight dist = P_AproxDistance ( actor->x-actor->target->x, actor->y-actor->target->y) - 64*FRACUNIT; if (!actor->info->meleestate) dist -= 128*FRACUNIT; // no melee attack, so fire more dist >>= 16; if (actor->type == MT_VILE) { if (dist > 14*64) return false; // too far away } if (actor->type == MT_UNDEAD) { if (dist < 196) return false; // close for fist attack dist >>= 1; } if (actor->type == MT_CYBORG || actor->type == MT_SPIDER || actor->type == MT_SKULL) { dist >>= 1; }
void DEarthquake::Tick () { int i; if (m_Spot == NULL) { Destroy (); return; } if (!S_IsActorPlayingSomething (m_Spot, CHAN_BODY, m_QuakeSFX)) { S_Sound (m_Spot, CHAN_BODY | CHAN_LOOP, m_QuakeSFX, 1, ATTN_NORM); } if (m_DamageRadius > 0) { for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i] && !(players[i].cheats & CF_NOCLIP)) { AActor *victim = players[i].mo; fixed_t dist; dist = P_AproxDistance (victim->x - m_Spot->x, victim->y - m_Spot->y); // Check if in damage radius if (dist < m_DamageRadius && victim->z <= victim->floorz) { if (pr_quake() < 50) { P_DamageMobj (victim, NULL, NULL, pr_quake.HitDice (1), NAME_None); } // Thrust player around angle_t an = victim->angle + ANGLE_1*pr_quake(); P_ThrustMobj (victim, an, m_Intensity << (FRACBITS-1)); } } } } if (--m_Countdown == 0) { if (S_IsActorPlayingSomething(m_Spot, CHAN_BODY, m_QuakeSFX)) { S_StopSound(m_Spot, CHAN_BODY); } Destroy(); } }
//Checks TRUE reachability from //one actor to another. First mobj (actor) is looker. bool DCajunMaster::Reachable (AActor *actor, AActor *target) { if (actor == target) return false; if ((target->Sector->ceilingplane.ZatPoint (target->x, target->y) - target->Sector->floorplane.ZatPoint (target->x, target->y)) < actor->height) //Where target is, looker can't be. return false; looker = actor; rtarget = target; last_s = actor->Sector; last_z = last_s->floorplane.ZatPoint (actor->x, actor->y); reachable = true; estimated_dist = P_AproxDistance (actor->x - target->x, actor->y - target->y); P_PathTraverse (actor->x+actor->momx, actor->y+actor->momy, target->x, target->y, PT_ADDLINES|PT_ADDTHINGS, PTR_Reachable); return reachable; }
void A_SkullAttack(AActor *self, fixed_t speed) { AActor *dest; angle_t an; int dist; // [BC] This is handled server-side. if ( NETWORK_InClientMode() ) { return; } if (!self->target) return; dest = self->target; self->flags |= MF_SKULLFLY; S_Sound (self, CHAN_VOICE, self->AttackSound, 1, ATTN_NORM); // [BC] If we're the server, tell clients play this sound. // [BB] And tell them of MF_SKULLFLY. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) { SERVERCOMMANDS_SetThingFlags( self, FLAGSET_FLAGS ); SERVERCOMMANDS_SoundActor( self, CHAN_VOICE, S_GetName( self->AttackSound ), 1, ATTN_NORM ); } A_FaceTarget (self); an = self->angle >> ANGLETOFINESHIFT; self->velx = FixedMul (speed, finecosine[an]); self->vely = FixedMul (speed, finesine[an]); dist = P_AproxDistance (dest->x - self->x, dest->y - self->y); dist = dist / speed; if (dist < 1) dist = 1; self->velz = (dest->z + (dest->height>>1) - self->z) / dist; // [BC] Update the lost soul's momentum. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_MoveThingExact( self, CM_X|CM_Y|CM_Z|CM_MOMX|CM_MOMY|CM_MOMZ ); }
END_DEFAULTS bool AArtiHealingRadius::Use (bool pickup) { bool effective = false; for (int i = 0; i < MAXPLAYERS; ++i) { if (playeringame[i] && players[i].mo != NULL && players[i].mo->health > 0 && P_AproxDistance (players[i].mo->x - Owner->x, players[i].mo->y - Owner->y) <= HEAL_RADIUS_DIST) { effective |= static_cast<APlayerPawn*>(Owner)->DoHealingRadius (players[i].mo); } } return effective; }
// // P_CheckMeleeRange // boolean P_CheckMeleeRange (mobj_t* actor) { mobj_t* pl; fixed_t dist; if (!actor->target) return false; pl = actor->target; dist = P_AproxDistance (pl->x-actor->x, pl->y-actor->y); if (dist >= MELEERANGE-20*FRACUNIT+pl->info->radius) return false; if (! P_CheckSight (actor, actor->target) ) return false; return true; }
DEFINE_ACTION_FUNCTION(AActor, A_InquisitorJump) { fixed_t dist; fixed_t speed; angle_t an; // [BC] This is handled server-side. if ( NETWORK_InClientMode() ) { return; } if (self->target == NULL) return; S_Sound (self, CHAN_ITEM|CHAN_LOOP, "inquisitor/jump", 1, ATTN_NORM); self->z += 64*FRACUNIT; A_FaceTarget (self); an = self->angle >> ANGLETOFINESHIFT; speed = self->Speed * 2/3; self->velx += FixedMul (speed, finecosine[an]); self->vely += FixedMul (speed, finesine[an]); dist = P_AproxDistance (self->target->x - self->x, self->target->y - self->y); dist /= speed; if (dist < 1) { dist = 1; } self->velz = (self->target->z - self->z) / dist; self->reactiontime = 60; self->flags |= MF_NOGRAVITY; // [BC] If we're the server, update the thing's position. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) { SERVERCOMMANDS_MoveThingExact( self, CM_Z|CM_MOMX|CM_MOMY|CM_MOMZ ); // [CW] Also, set the flags to ensure the actor can fly. SERVERCOMMANDS_SetThingFlags( self, FLAGSET_FLAGS ); } }
/// Bot pathing: Continue the path from a node to its neighbours. void SearchNode_t::PushSuccessors(priorityQ_t *q, int destgx, int destgy) { for (int angle=0; angle<NUMBOTDIRS; angle++) { if (dir[angle]) { SearchNode_t *node = dir[angle]; fixed_t n_cost = costDir[angle] + cost; fixed_t n_heuristic = P_AproxDistance(destgx - node->gx, destgy - node->gy) * 10000; //CONS_Printf("got heuristic of %d\n", node->heuristic); fixed_t n_f = n_cost + n_heuristic; if (node->visited && (node->f <= n_f)) continue; //if already been looked at before, and before look was better if (q->FindNode(node)) { //this node has already been pushed on the todo list if (node->f <= n_f) continue; //the path to get here this way is better then the old one's //so use this instead, remove the old //CONS_Printf("found better path\n"); q->RemoveNode(node); } node->cost = n_cost; node->heuristic = n_heuristic; node->f = n_f; node->pprevious = this; q->Push(node); //CONS_Printf("pushed node at x:%d, y:%d\n", node->x>>FRACBITS, node->y>>FRACBITS); } } }
void A_SkullAttack (AActor *self) { AActor *dest; angle_t an; int dist; if (!self->target) return; dest = self->target; self->flags |= MF_SKULLFLY; S_SoundID (self, CHAN_VOICE, self->AttackSound, 1, ATTN_NORM); A_FaceTarget (self); an = self->angle >> ANGLETOFINESHIFT; self->momx = FixedMul (SKULLSPEED, finecosine[an]); self->momy = FixedMul (SKULLSPEED, finesine[an]); dist = P_AproxDistance (dest->x - self->x, dest->y - self->y); dist = dist / SKULLSPEED; if (dist < 1) dist = 1; self->momz = (dest->z+(dest->height>>1) - self->z) / dist; }
DEFINE_ACTION_FUNCTION(AActor, A_MinotaurDecide) { bool friendly = !!(self->flags5 & MF5_SUMMONEDMONSTER); angle_t angle; AActor *target; int dist; target = self->target; if (!target) { return; } if (!friendly) { S_Sound (self, CHAN_WEAPON, "minotaur/sight", 1, ATTN_NORM); } dist = P_AproxDistance (self->x-target->x, self->y-target->y); if (target->z+target->height > self->z && target->z+target->height < self->z+self->height && dist < (friendly ? 16*64*FRACUNIT : 8*64*FRACUNIT) && dist > 1*64*FRACUNIT && pr_minotaurdecide() < 150) { // Charge attack // Don't call the state function right away self->SetState (self->FindState ("Charge"), true); self->flags |= MF_SKULLFLY; if (!friendly) { // Heretic's Minotaur is invulnerable during charge attack self->flags2 |= MF2_INVULNERABLE; } A_FaceTarget (self); angle = self->angle>>ANGLETOFINESHIFT; self->velx = FixedMul (MNTR_CHARGE_SPEED, finecosine[angle]); self->vely = FixedMul (MNTR_CHARGE_SPEED, finesine[angle]); self->special1 = TICRATE/2; // Charge duration }
/// Main pathfinding routine bool BotNodes::FindPath(list<SearchNode_t *> &path, SearchNode_t *start, SearchNode_t *dest) { bool found = false; SearchNode_t *best = NULL; // if can't reach destination, try heading towards this closest point int numNodesSearched = 0; if (start)// || P_AproxDistance(pawn->x - start->x, pawn->y - start->y) > (BOTNODEGRIDSIZE<<1)) //no nodes can get here { path.clear(); priorityQ_t pq; deque<SearchNode_t *> visitedList; //CONS_Printf("closest node found is x:%d, y:%d\n", start->x>>FRACBITS, start->y>>FRACBITS); start->pprevious = NULL; start->cost = 0; start->f = start->heuristic = P_AproxDistance(start->gx - dest->gx, start->gy - dest->gy) * 10000; pq.Push(start); while (!pq.Empty() && !found) // while there are nodes left to check { SearchNode_t *temp = pq.Pop(); //CONS_Printf("doing node a node at x:%d, y:%d\n", temp->x>>FRACBITS, temp->y>>FRACBITS); if (temp == dest) { //I have found the sector where I want to get to best = temp; found = true; } else { if (!best || (temp->heuristic < best->heuristic)) best = temp; temp->PushSuccessors(&pq, dest->gx, dest->gy); if (!temp->visited) { visitedList.push_front(temp); //so later can set this back to not visited temp->visited = true; } } numNodesSearched++; } // reset all visited nodes to not visited while (!visitedList.empty()) { visitedList.front()->visited = false; visitedList.pop_front(); } if (best && (best != start)) { while (best->pprevious) // backtrack the route, store the nodes in the path list { #ifdef SHOWBOTPATH fixed_t x = posX2x(best->gx); fixed_t y = posY2y(best->gy); best->marker = mp->SpawnDActor(x, y, ONFLOORZ, MT_MISC49); #endif path.push_front(best); best = best->pprevious; } found = true; } } //else // CONS_Printf("Bot is stuck here x:%d y:%d\n", pawn->x>>FRACBITS, pawn->y>>FRACBITS); return found; }
void FPortal::AddVertexToShape(vertex_t *vertex) { for(unsigned i=0;i<Shape.Size(); i++) { if (vertex->x == Shape[i]->x && vertex->y == Shape[i]->y) return; } if (Shape.Size() < 2) { Shape.Push(vertex); } else if (Shape.Size() == 2) { // Special case: We need to check if the vertex is on an extension of the line between the first two vertices. int pos = PointOnShapeLineSide(vertex->x, vertex->y, 0); if (pos == 0) { fixed_t distv1 = P_AproxDistance(vertex->x - Shape[0]->x, vertex->y - Shape[0]->y); fixed_t distv2 = P_AproxDistance(vertex->x - Shape[1]->x, vertex->y - Shape[1]->y); fixed_t distvv = P_AproxDistance(Shape[0]->x - Shape[1]->x, Shape[0]->y - Shape[1]->y); if (distv1 > distvv) { Shape[1] = vertex; } else if (distv2 > distvv) { Shape[0] = vertex; } return; } else if (pos > 0) { Shape.Insert(1, vertex); } else { Shape.Push(vertex); } } else { for(unsigned i=0; i<Shape.Size(); i++) { int startlinepos = PointOnShapeLineSide(vertex->x, vertex->y, i); if (startlinepos >= 0) { int previouslinepos = PointOnShapeLineSide(vertex->x, vertex->y, (i+Shape.Size()-1)%Shape.Size()); if (previouslinepos < 0) // we found the first line for which the vertex lies in front { unsigned int nextpoint = i; do { nextpoint = (nextpoint+1) % Shape.Size(); } while (PointOnShapeLineSide(vertex->x, vertex->y, nextpoint) >= 0); int removecount = (nextpoint - i + Shape.Size()) % Shape.Size() - 1; if (removecount == 0) { if (startlinepos > 0) { Shape.Insert(i+1, vertex); } } else if (nextpoint > i || nextpoint == 0) { // The easy case: It doesn't wrap around Shape.Delete(i+1, removecount-1); Shape[i+1] = vertex; } else { // It does wrap around. Shape.Delete(i+1, removecount); Shape.Delete(1, nextpoint-1); Shape[0] = vertex; } return; } } } } }
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; } }