mobj_t *P_LaunchMissile(mobj_t *missile, angle_t angle, coord_t const targetPos[], coord_t const sourcePos[], coord_t extraMomZ) { DENG2_ASSERT(targetPos); if(missile) { DENG2_ASSERT(missile->info); // Play the launch sound. if(missile->info->seeSound) { S_StartSound(missile->info->seeSound, missile); } if(!sourcePos) { sourcePos = missile->origin; } // Determine speed. /// @todo Should optionally calculate this in true 3D. coord_t dist; uint an = angle >> ANGLETOFINESHIFT; missile->mom[0] = missile->info->speed * FIX2FLT(finecosine[an]); missile->mom[1] = missile->info->speed * FIX2FLT(finesine [an]); dist = M_ApproxDistance(targetPos[0] - sourcePos[0], targetPos[1] - sourcePos[1]); dist /= missile->info->speed; if(dist < 1) dist = 1; missile->mom[2] = (targetPos[2] - sourcePos[2] + extraMomZ) / dist; } return Mobj_ExplodeIfObstructed(missile); }
void C_DECL A_Quake(mobj_t* actor) { angle_t angle; player_t* player; mobj_t* victim; int richters = actor->args[0]; int playnum; coord_t dist; if(actor->args[1]-- > 0) { for(playnum = 0; playnum < MAXPLAYERS; ++playnum) { player = &players[playnum]; if(!players[playnum].plr->inGame) continue; victim = player->plr->mo; dist = M_ApproxDistance(actor->origin[VX] - victim->origin[VX], actor->origin[VY] - victim->origin[VY]); dist = FIX2FLT(FLT2FIX(dist) >> (FRACBITS + 6)); // Tested in tile units (64 pixels). if(dist < FIX2FLT(actor->args[3])) // In tremor radius. { localQuakeHappening[playnum] = richters; players[playnum].update |= PSF_LOCAL_QUAKE; } // Check if in damage radius. if(dist < FIX2FLT(actor->args[2]) && victim->origin[VZ] <= victim->floorZ) { if(P_Random() < 50) { P_DamageMobj(victim, NULL, NULL, HITDICE(1), false); } // Thrust player around. angle = victim->angle + ANGLE_1 * P_Random(); P_ThrustMobj(victim, angle, FIX2FLT(richters << (FRACBITS - 1))); } } } else { for(playnum = 0; playnum < MAXPLAYERS; playnum++)
dd_bool Mobj_LookForPlayers(mobj_t *mo, dd_bool allAround) { int const playerCount = P_CountPlayersInGame(); // Nobody to target? if(!playerCount) return false; int const from = mo->lastLook % MAXPLAYERS; int const to = (from + MAXPLAYERS - 1) % MAXPLAYERS; int cand = from; int tries = 0; bool foundTarget = false; for(; cand != to; cand = (cand < (MAXPLAYERS - 1)? cand + 1 : 0)) { player_t *player = players + cand; // Is player in the game? if(!player->plr->inGame) continue; mobj_t *plrmo = player->plr->mo; if(!plrmo) continue; // Do not target camera players. if(P_MobjIsCamera(plrmo)) continue; // Only look ahead a fixed number of times. if(tries++ == 2) break; // Do not target dead players. if(player->health <= 0) continue; // Within sight? if(!P_CheckSight(mo, plrmo)) continue; if(!allAround) { angle_t an = M_PointToAngle2(mo->origin, plrmo->origin); an -= mo->angle; if(an > ANG90 && an < ANG270) { // If real close, react anyway. coord_t dist = M_ApproxDistance(plrmo->origin[VX] - mo->origin[VX], plrmo->origin[VY] - mo->origin[VY]); // Behind us? if(dist > MELEERANGE) continue; } } #if __JHERETIC__ || __JHEXEN__ // If player is invisible we may not detect if too far or randomly. if(plrmo->flags & MF_SHADOW) { if((M_ApproxDistance(plrmo->origin[VX] - mo->origin[VX], plrmo->origin[VY] - mo->origin[VY]) > 2 * MELEERANGE) && M_ApproxDistance(plrmo->mom[MX], plrmo->mom[MY]) < 5) { // Too far; can't detect. continue; } // Randomly overlook the player regardless. if(P_Random() < 225) continue; } #endif #if __JHEXEN__ // Minotaurs do not target their master. if(mo->type == MT_MINOTAUR && mo->tracer && mo->tracer->player == player) continue; #endif // Found our quarry. mo->target = plrmo; foundTarget = true; } // Start looking from here next time. mo->lastLook = cand; return foundTarget; }
/** * Set appropriate parameters for a camera. */ void P_PlayerThinkCamera(player_t* player) { mobj_t* mo = player->plr->mo; if(!mo) return; // If this player is not a camera, get out of here. if(!(player->plr->flags & DDPF_CAMERA)) { if(player->playerState == PST_LIVE) { mo->flags |= (MF_SOLID | MF_SHOOTABLE | MF_PICKUP); } return; } mo->flags &= ~(MF_SOLID | MF_SHOOTABLE | MF_PICKUP); // How about viewlock? if(player->viewLock) { angle_t angle; int full; coord_t dist; mobj_t* target = players->viewLock; if(!target->player || !target->player->plr->inGame) { player->viewLock = NULL; return; } full = player->lockFull; angle = M_PointToAngle2(mo->origin, target->origin); //player->plr->flags |= DDPF_FIXANGLES; /* $unifiedangles */ mo->angle = angle; //player->plr->clAngle = angle; player->plr->flags |= DDPF_INTERYAW; if(full) { dist = M_ApproxDistance(mo->origin[VX] - target->origin[VX], mo->origin[VY] - target->origin[VY]); angle = M_PointXYToAngle2(0, 0, target->origin[VZ] + (target->height / 2) - mo->origin[VZ], dist); player->plr->lookDir = -(angle / (float) ANGLE_MAX * 360.0f - 90); if(player->plr->lookDir > 180) player->plr->lookDir -= 360; player->plr->lookDir *= 110.0f / 85.0f; if(player->plr->lookDir > 110) player->plr->lookDir = 110; if(player->plr->lookDir < -110) player->plr->lookDir = -110; player->plr->flags |= DDPF_INTERPITCH; } } }