void C_DECL A_PotteryCheck(mobj_t* actor) { mobj_t* pmo; if(!IS_NETGAME) { pmo = players[CONSOLEPLAYER].plr->mo; if(P_CheckSight(actor, pmo) && (abs((int32_t)(M_PointToAngle2(pmo->origin, actor->origin) - pmo->angle)) <= ANGLE_45)) { // Previous state (pottery bit waiting state). P_MobjChangeState(actor, actor->state - &STATES[0] - 1); } return; } else { int i; for(i = 0; i < MAXPLAYERS; ++i) { if(!players[i].plr->inGame) continue; pmo = players[i].plr->mo; if(P_CheckSight(actor, pmo) && (abs((int32_t)(M_PointToAngle2(pmo->origin, actor->origin) - pmo->angle)) <= ANGLE_45)) { // Previous state (pottery bit waiting state). P_MobjChangeState(actor, actor->state - &STATES[0] - 1); return; } } } }
void C_DECL A_Punch(player_t *player, pspdef_t *psp) { angle_t angle; int damage; float slope; P_ShotAmmo(player); player->update |= PSF_AMMO; if(IS_CLIENT) return; damage = (P_Random() % 10 + 1) * 2; if(player->powers[PT_STRENGTH]) damage *= 10; angle = player->plr->mo->angle; angle += (P_Random() - P_Random()) << 18; slope = P_AimLineAttack(player->plr->mo, angle, PLRMELEERANGE); P_LineAttack(player->plr->mo, angle, PLRMELEERANGE, slope, damage, MT_PUFF); // Turn to face target. if(lineTarget) { S_StartSound(SFX_PUNCH, player->plr->mo); player->plr->mo->angle = M_PointToAngle2(player->plr->mo->origin, lineTarget->origin); player->plr->flags |= DDPF_FIXANGLES; } }
void C_DECL A_Saw(player_t *player, pspdef_t *psp) { angle_t angle; int damage; float slope; DENG_UNUSED(psp); P_ShotAmmo(player); player->update |= PSF_AMMO; if(IS_CLIENT) return; damage = (float) (P_Random() % 10 + 1) * 2; angle = player->plr->mo->angle; angle += (P_Random() - P_Random()) << 18; // Use meleerange + 1 so the puff doesn't skip the flash. slope = P_AimLineAttack(player->plr->mo, angle, PLRMELEERANGE + 1); P_LineAttack(player->plr->mo, angle, PLRMELEERANGE + 1, slope, damage, MT_PUFF); if(!lineTarget) { S_StartSound(SFX_SAWFUL, player->plr->mo); return; } S_StartSound(SFX_SAWHIT, player->plr->mo); // Turn to face target. angle = M_PointToAngle2(player->plr->mo->origin, lineTarget->origin); if(angle - player->plr->mo->angle > ANG180) { if(angle - player->plr->mo->angle < -ANG90 / 32) // jd64 was "/ 20" player->plr->mo->angle = angle + ANG90 / 32; // jd64 was "/ 21" else player->plr->mo->angle -= ANG90 / 20; } else { if(angle - player->plr->mo->angle > ANG90 / 32) // jd64 was "/ 20" player->plr->mo->angle = angle - ANG90 / 32; // jd64 was "/ 21" else player->plr->mo->angle += ANG90 / 20; } player->plr->mo->flags |= MF_JUSTATTACKED; }
/** * Damages both enemies and players. * * @param inflictor Mobj that caused the damage creature or missile, * can be NULL (slime, etc) * @param source Mobj to target after taking damage. Can be @c NULL * for barrel explosions and other environmental stuff. * Source and inflictor are the same for melee attacks. * @param skipNetworkCheck Allow the damage to be done regardless of netgame status. * * @return Actual amount of damage done. */ int P_DamageMobj2(mobj_t *target, mobj_t *inflictor, mobj_t *source, int damageP, dd_bool stomping, dd_bool skipNetworkCheck) { angle_t angle; int saved, originalHealth; player_t *player; int /*temp,*/ damage; if(!target) return 0; // Wha? originalHealth = target->health; // The actual damage (== damageP * netMobDamageModifier for any // non-player mobj). damage = damageP; if(!skipNetworkCheck) { if(IS_NETGAME && !stomping && D_NetDamageMobj(target, inflictor, source, damage)) { // We're done here. return 0; } // Clients can't harm anybody. if(IS_CLIENT) return 0; } if(!(target->flags & MF_SHOOTABLE)) return 0; // Shouldn't happen... if(target->health <= 0) return 0; if(target->player) { // Player specific. // Check if player-player damage is disabled. if(source && source->player && source->player != target->player) { // Co-op damage disabled? if(IS_NETGAME && !G_Ruleset_Deathmatch() && cfg.noCoopDamage) return 0; // Same color, no damage? if(cfg.noTeamDamage && cfg.playerColor[target->player - players] == cfg.playerColor[source->player - players]) return 0; } } if(target->flags & MF_SKULLFLY) { target->mom[MX] = target->mom[MY] = target->mom[MZ] = 0; } player = target->player; if(player && G_Ruleset_Skill() == SM_BABY) damage /= 2; // Take half damage in trainer mode. // Use the cvar damage multiplier netMobDamageModifier only if the // inflictor is not a player. if(inflictor && !inflictor->player && (!source || (source && !source->player))) { // damage = (int) ((float) damage * netMobDamageModifier); if(IS_NETGAME) damage *= cfg.netMobDamageModifier; } // Some close combat weapons should not inflict thrust and push the // victim out of reach, thus kick away unless using a melee weapon. if(inflictor && !(target->flags & MF_NOCLIP) && (!source || !source->player || source->player->readyWeapon != WT_EIGHTH) && !(inflictor->flags2 & MF2_NODMGTHRUST)) { uint an; coord_t thrust; angle = M_PointToAngle2(inflictor->origin, target->origin); thrust = FIX2FLT(damage * (FRACUNIT>>3) * 100 / target->info->mass); // Make fall forwards sometimes. if(damage < 40 && damage > target->health && target->origin[VZ] - inflictor->origin[VZ] > 64 && (P_Random() & 1)) { angle += ANG180; thrust *= 4; } an = angle >> ANGLETOFINESHIFT; target->mom[MX] += thrust * FIX2FLT(finecosine[an]); target->mom[MY] += thrust * FIX2FLT(finesine[an]); NetSv_PlayerMobjImpulse(target, thrust * FIX2FLT(finecosine[an]), thrust * FIX2FLT(finesine[an]), 0); // $dropoff_fix: thrust objects hanging off ledges. if((target->intFlags & MIF_FALLING) && target->gear >= MAXGEAR) target->gear = 0; }
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; }
/** * Damages both enemies and players * Source and inflictor are the same for melee attacks. * Source can be NULL for slime, barrel explosions * and other environmental stuff. * * @param inflictor Mobj that caused the damage creature or missile, * can be NULL (slime, etc). * @param source Mobj to target after taking damage, creature or NULL. * * @return Actual amount of damage done. */ int P_DamageMobj2(mobj_t *target, mobj_t *inflictor, mobj_t *source, int damageP, dd_bool stomping, dd_bool skipNetworkCheck) { // Follow a player exlusively for 3 seconds. #define BASETHRESHOLD (100) uint an; angle_t angle; int saved; player_t *player; float thrust; //int temp; int originalHealth; // The actual damage (== damageP * netMobDamageModifier for any non-player mobj). int damage = damageP; if(!target) return 0; // Wha? originalHealth = target->health; if(!skipNetworkCheck) { // Clients can't harm anybody. if(IS_CLIENT) return 0; } if(!(target->flags & MF_SHOOTABLE)) return 0; // Shouldn't happen... if(target->health <= 0) return 0; // Player specific. if(target->player) { // Check if player-player damage is disabled. if(source && source->player && source->player != target->player) { // Co-op damage disabled? if(IS_NETGAME && !G_Ruleset_Deathmatch() && cfg.noCoopDamage) return 0; // Same color, no damage? if(cfg.noTeamDamage && cfg.playerColor[target->player - players] == cfg.playerColor[source->player - players]) return 0; } } if(target->flags & MF_SKULLFLY) { target->mom[MX] = target->mom[MY] = target->mom[MZ] = 0; } player = target->player; if(player && G_Ruleset_Skill() == SM_BABY) damage >>= 1; // take half damage in trainer mode // jd64 > #if 0 if(inflictor && inflictor->type == MT_FIREEND) { // Special for Motherdemon attack #if 0 /** DJS - This was originally in a sub routine called P_TouchMotherFire * but due to the fact that @c player, was not initialized * this likely does not work the way kaiser expected it to. * What would actually happen is not certain but I would guess it * would most likely simply return without doing anything at all. * \todo SHOULD this be fixed? Or is something implemented elsewhere * which does what this was attempting to do? */ int damage; player_t *player; if(player = target->player) { damage = ((P_Random() % 10) + 1) * 8; P_DamageMobj(target, NULL, NULL, damage); player->plr->mo->momz = 16; player->jumpTics = 24; } #endif return; } #endif // < d64tc // Use the cvar damage multiplier netMobDamageModifier only if the // inflictor is not a player. if(inflictor && !inflictor->player && (!source || (source && !source->player))) { // damage = (int) ((float) damage * netMobDamageModifier); if(IS_NETGAME) damage *= cfg.common.netMobDamageModifier; } // Some close combat weapons should not inflict thrust and push the // victim out of reach, thus kick away unless using the chainsaw. if(inflictor && !(target->flags & MF_NOCLIP) && (!source || !source->player || source->player->readyWeapon != WT_EIGHTH) && !(inflictor->flags2 & MF2_NODMGTHRUST)) { angle = M_PointToAngle2(inflictor->origin, target->origin); thrust = FIX2FLT(damage * (FRACUNIT>>3) * 100 / target->info->mass); // Make fall forwards sometimes. if(damage < 40 && damage > target->health && target->origin[VZ] - inflictor->origin[VZ] > 64 && (P_Random() & 1)) { angle += ANG180; thrust *= 4; } an = angle >> ANGLETOFINESHIFT; target->mom[MX] += thrust * FIX2FLT(finecosine[an]); target->mom[MY] += thrust * FIX2FLT(finesine[an]); NetSv_PlayerMobjImpulse(target, thrust * FIX2FLT(finecosine[an]), thrust * FIX2FLT(finesine[an]), 0); // $dropoff_fix: thrust objects hanging off ledges. if(target->intFlags & MIF_FALLING && target->gear >= MAXGEAR) target->gear = 0; }
/** * 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; } } }