📄 p_inter.c
字号:
{ superSlot = i; superCount = player->inventory[i].count; } } if((gameskill == sk_baby) && (normalCount*25 >= saveHealth)) { // Use quartz flasks count = (saveHealth+24)/25; for(i = 0; i < count; i++) { player->health += 25; P_PlayerRemoveArtifact(player, normalSlot); } } else if(superCount*100 >= saveHealth) { // Use mystic urns count = (saveHealth+99)/100; for(i = 0; i < count; i++) { player->health += 100; P_PlayerRemoveArtifact(player, superSlot); } } else if((gameskill == sk_baby) && (superCount*100+normalCount*25 >= saveHealth)) { // Use mystic urns and quartz flasks count = (saveHealth+24)/25; saveHealth -= count*25; for(i = 0; i < count; i++) { player->health += 25; P_PlayerRemoveArtifact(player, normalSlot); } count = (saveHealth+99)/100; for(i = 0; i < count; i++) { player->health += 100; P_PlayerRemoveArtifact(player, normalSlot); } } player->mo->health = player->health;}/*=================== P_DamageMobj== Damages both enemies and players= inflictor is the thing that caused the damage= creature or missile, can be NULL (slime, etc)= source is the thing to target after taking damage= creature or NULL= Source and inflictor are the same for melee attacks= source can be null for barrel explosions and other environmental stuff==================*/void P_DamageMobj( mobj_t *target, mobj_t *inflictor, mobj_t *source, int damage){ unsigned ang; int saved; fixed_t savedPercent; player_t *player; mobj_t *master; fixed_t thrust; int temp; int i; if(!(target->flags&MF_SHOOTABLE)) { // Shouldn't happen return; } if(target->health <= 0) { if (inflictor && inflictor->flags2&MF2_ICEDAMAGE) { return; } else if (target->flags&MF_ICECORPSE) // frozen { target->tics = 1; target->momx = target->momy = 0; } return; } if ((target->flags2&MF2_INVULNERABLE) && damage < 10000) { // mobj is invulnerable if(target->player) return; // for player, no exceptions if(inflictor) { switch(inflictor->type) { // These inflictors aren't foiled by invulnerability case MT_HOLY_FX: case MT_POISONCLOUD: case MT_FIREBOMB: break; default: return; } } else { return; } } if(target->player) { if(damage < 1000 && ((target->player->cheats&CF_GODMODE) || target->player->powers[pw_invulnerability])) { return; } } if(target->flags&MF_SKULLFLY) { target->momx = target->momy = target->momz = 0; } if(target->flags2&MF2_DORMANT) { // Invulnerable, and won't wake up return; } player = target->player; if(player && gameskill == sk_baby) { // Take half damage in trainer mode damage >>= 1; } // Special damage types if(inflictor) { switch(inflictor->type) { case MT_EGGFX: if(player) { P_MorphPlayer(player); } else { P_MorphMonster(target); } return; // Always return case MT_TELOTHER_FX1: case MT_TELOTHER_FX2: case MT_TELOTHER_FX3: case MT_TELOTHER_FX4: case MT_TELOTHER_FX5: if ((target->flags&MF_COUNTKILL) && (target->type != MT_SERPENT) && (target->type != MT_SERPENTLEADER) && (!(target->flags2 & MF2_BOSS))) { P_TeleportOther(target); } return; case MT_MINOTAUR: if(inflictor->flags&MF_SKULLFLY) { // Slam only when in charge mode P_MinotaurSlam(inflictor, target); return; } break; case MT_BISH_FX: // Bishops are just too nasty damage >>= 1; break; case MT_SHARDFX1: switch(inflictor->special2) { case 3: damage <<= 3; break; case 2: damage <<= 2; break; case 1: damage <<= 1; break; default: break; } break; case MT_CSTAFF_MISSILE: // Cleric Serpent Staff does poison damage if(target->player) { P_PoisonPlayer(target->player, source, 20); damage >>= 1; } break; case MT_ICEGUY_FX2: damage >>= 1; break; case MT_POISONDART: if(target->player) { P_PoisonPlayer(target->player, source, 20); damage >>= 1; } break; case MT_POISONCLOUD: if(target->player) { if(target->player->poisoncount < 4) { P_PoisonDamage(target->player, source, 15+(P_Random()&15), false); // Don't play painsound P_PoisonPlayer(target->player, source, 50); S_StartSound(target, SFX_PLAYER_POISONCOUGH); } return; } else if(!(target->flags&MF_COUNTKILL)) { // only damage monsters/players with the poison cloud return; } break; case MT_FSWORD_MISSILE: if(target->player) { damage -= damage>>2; } break; default: break; } } // Push the target unless source is using the gauntlets if(inflictor && (!source || !source->player) && !(inflictor->flags2&MF2_NODMGTHRUST)) { ang = R_PointToAngle2(inflictor->x, inflictor->y, target->x, target->y); //thrust = damage*(FRACUNIT>>3)*100/target->info->mass; thrust = damage*(FRACUNIT>>3)*150/target->info->mass; // make fall forwards sometimes if((damage < 40) && (damage > target->health) && (target->z-inflictor->z > 64*FRACUNIT) && (P_Random()&1)) { ang += ANG180; thrust *= 4; } ang >>= ANGLETOFINESHIFT; target->momx += FixedMul(thrust, finecosine[ang]); target->momy += FixedMul(thrust, finesine[ang]); } // // player specific // if(player) { savedPercent = AutoArmorSave[player->class] +player->armorpoints[ARMOR_ARMOR]+player->armorpoints[ARMOR_SHIELD] +player->armorpoints[ARMOR_HELMET] +player->armorpoints[ARMOR_AMULET]; if(savedPercent) { // armor absorbed some damage if(savedPercent > 100*FRACUNIT) { savedPercent = 100*FRACUNIT; } for(i = 0; i < NUMARMOR; i++) { if(player->armorpoints[i]) { player->armorpoints[i] -= FixedDiv(FixedMul(damage<<FRACBITS, ArmorIncrement[player->class][i]), 300*FRACUNIT); if(player->armorpoints[i] < 2*FRACUNIT) { player->armorpoints[i] = 0; } } } saved = FixedDiv(FixedMul(damage<<FRACBITS, savedPercent), 100*FRACUNIT); if(saved > savedPercent*2) { saved = savedPercent*2; } damage -= saved>>FRACBITS; } if(damage >= player->health && ((gameskill == sk_baby) || deathmatch) && !player->morphTics) { // Try to use some inventory health P_AutoUseHealth(player, damage-player->health+1); } player->health -= damage; // mirror mobj health here for Dave if(player->health < 0) { player->health = 0; } player->attacker = source; player->damagecount += damage; // add damage after armor / invuln if(player->damagecount > 100) { player->damagecount = 100; // teleport stomp does 10k points... } temp = damage < 100 ? damage : 100; if(player == &players[consoleplayer]) { I_Tactile(40, 10, 40+temp*2); SB_PaletteFlash(false); } } // // do the damage // target->health -= damage; if(target->health <= 0) { // Death if(inflictor) { // check for special fire damage or ice damage deaths if(inflictor->flags2&MF2_FIREDAMAGE) { if(player && !player->morphTics) { // Check for flame death if(target->health > -50 && damage > 25) { target->flags2 |= MF2_FIREDAMAGE; } } else { target->flags2 |= MF2_FIREDAMAGE; } } else if(inflictor->flags2&MF2_ICEDAMAGE) { target->flags2 |= MF2_ICEDAMAGE; } } if(source && (source->type == MT_MINOTAUR)) { // Minotaur's kills go to his master master = (mobj_t *)(source->special1); // Make sure still alive and not a pointer to fighter head if (master->player && (master->player->mo == master)) { source = master; } } if(source && (source->player) && (source->player->readyweapon == WP_FOURTH)) { // Always extreme death from fourth weapon target->health = -5000; } P_KillMobj(source, target); return; } if((P_Random() < target->info->painchance) && !(target->flags&MF_SKULLFLY)) { if(inflictor && (inflictor->type >= MT_LIGHTNING_FLOOR && inflictor->type <= MT_LIGHTNING_ZAP)) { if(P_Random() < 96) { target->flags |= MF_JUSTHIT; // fight back! P_SetMobjState(target, target->info->painstate); } else { // "electrocute" the target target->frame |= FF_FULLBRIGHT; if(target->flags&MF_COUNTKILL && P_Random() < 128 && !S_GetSoundPlayingInfo(target, SFX_PUPPYBEAT)) { if ((target->type == MT_CENTAUR) || (target->type == MT_CENTAURLEADER) || (target->type == MT_ETTIN)) { S_StartSound(target, SFX_PUPPYBEAT); } } } } else { target->flags |= MF_JUSTHIT; // fight back! P_SetMobjState(target, target->info->painstate); if(inflictor && inflictor->type == MT_POISONCLOUD) { if(target->flags&MF_COUNTKILL && P_Random() < 128 && !S_GetSoundPlayingInfo(target, SFX_PUPPYBEAT)) { if ((target->type == MT_CENTAUR) || (target->type == MT_CENTAURLEADER) || (target->type == MT_ETTIN)) { S_StartSound(target, SFX_PUPPYBEAT); } } } } } target->reactiontime = 0; // we're awake now... if(!target->threshold && source && !(source->flags2&MF2_BOSS) && !(target->type == MT_BISHOP) && !(target->type == MT_MINOTAUR)) { // Target actor is not intent on another actor, // so make him chase after source if((target->type == MT_CENTAUR && source->type == MT_CENTAURLEADER) || (target->type == MT_CENTAURLEADER && source->type == MT_CENTAUR)) { return; } target->target = source; target->threshold = BASETHRESHOLD; if(target->state == &states[target->info->spawnstate] && target->info->seestate != S_NULL) { P_SetMobjState(target, target->info->seestate); } }}//==========================================================================//// P_FallingDamage////==========================================================================void P_FallingDamage(player_t *player){ int damage; int mom; int dist; mom = abs(player->mo->momz); dist = FixedMul(mom, 16*FRACUNIT/23); if(mom >= 63*FRACUNIT) { // automatic death P_DamageMobj(player->mo, NULL, NULL, 10000); return; } damage = ((FixedMul(dist, dist)/10)>>FRACBITS)-24; if(player->mo->momz > -39*FRACUNIT && damage > player->mo->health && player->mo->health != 1) { // No-death threshold damage = player->mo->health-1; } S_StartSound(player->mo, SFX_PLAYER_LAND); P_DamageMobj(player->mo, NULL, NULL, damage);}//==========================================================================//// P_PoisonPlayer - Sets up all data concerning poisoning////==========================================================================void P_PoisonPlayer(player_t *player, mobj_t *poisoner, int poison){ if((player->cheats&CF_GODMODE) || player->powers[pw_invulnerability]) { return; } player->poisoncount += poison; player->poisoner = poisoner; if(player->poisoncount > 100) { player->poisoncount = 100; }}//==========================================================================//// P_PoisonDamage - Similar to P_DamageMobj////==========================================================================void P_PoisonDamage(player_t *player, mobj_t *source, int damage, boolean playPainSound){ mobj_t *target; mobj_t *inflictor; target = player->mo; inflictor = source; if(target->health <= 0) { return; } if(target->flags2&MF2_INVULNERABLE && damage < 10000) { // mobj is invulnerable return; } if(player && gameskill == sk_baby) { // Take half damage in trainer mode damage >>= 1; } if(damage < 1000 && ((player->cheats&CF_GODMODE) || player->powers[pw_invulnerability])) { return; } if(damage >= player->health && ((gameskill == sk_baby) || deathmatch) && !player->morphTics) { // Try to use some inventory health P_AutoUseHealth(player, damage-player->health+1); } player->health -= damage; // mirror mobj health here for Dave if(player->health < 0) { player->health = 0; } player->attacker = source; // // do the damage // target->health -= damage; if(target->health <= 0) { // Death target->special1 = damage; if(player && inflictor && !player->morphTics) { // Check for flame death if((inflictor->flags2&MF2_FIREDAMAGE) && (target->health > -50) && (damage > 25)) { target->flags2 |= MF2_FIREDAMAGE; } if(inflictor->flags2&MF2_ICEDAMAGE) { target->flags2 |= MF2_ICEDAMAGE; } } P_KillMobj(source, target); return; } if(!(leveltime&63) && playPainSound) { P_SetMobjState(target, target->info->painstate); }/* if((P_Random() < target->info->painchance) && !(target->flags&MF_SKULLFLY)) { target->flags |= MF_JUSTHIT; // fight back! P_SetMobjState(target, target->info->painstate); }*/}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -