📄 p_map.c
字号:
if (li->backsector && li->backsector->ceilingpic == skyflatnum) return false; // it's a sky hack wall } P_SpawnPuff (x,y,z); return false; // don't go any farther }//// shoot a thing// th = in->d.thing; if (th == shootthing) return true; // can't shoot self if (!(th->flags&MF_SHOOTABLE)) return true; // corpse or something//// check for physical attacks on a ghost///* FIX: Impliment Heretic 2 weapons here if(th->flags&MF_SHADOW && shootthing->player->readyweapon == wp_staff) { return(true); }*/// check angles to see if the thing can be aimed at dist = FixedMul (attackrange, in->frac); thingtopslope = FixedDiv (th->z+th->height - shootz , dist); if (thingtopslope < aimslope) return true; // shot over the thing thingbottomslope = FixedDiv (th->z - shootz, dist); if (thingbottomslope > aimslope) return true; // shot under the thing//// hit thing// // position a bit closer frac = in->frac - FixedDiv (10*FRACUNIT,attackrange); x = trace.x + FixedMul(trace.dx, frac); y = trace.y + FixedMul(trace.dy, frac); z = shootz + FixedMul(aimslope, FixedMul(frac, attackrange)); P_SpawnPuff(x, y, z); if(la_damage) { if (!(in->d.thing->flags&MF_NOBLOOD) && !(in->d.thing->flags2&MF2_INVULNERABLE)) { if(PuffType == MT_AXEPUFF || PuffType == MT_AXEPUFF_GLOW) { P_BloodSplatter2(x, y, z, in->d.thing); } if(P_Random() < 192) { P_BloodSplatter(x, y, z, in->d.thing); } } if(PuffType == MT_FLAMEPUFF2) { // Cleric FlameStrike does fire damage P_DamageMobj(th, &LavaInflictor, shootthing, la_damage); } else { P_DamageMobj(th, shootthing, shootthing, la_damage); } } return(false); // don't go any farther}/*=================== P_AimLineAttack==================*/fixed_t P_AimLineAttack (mobj_t *t1, angle_t angle, fixed_t distance){ fixed_t x2, y2; angle >>= ANGLETOFINESHIFT; shootthing = t1; x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; shootz = t1->z + (t1->height>>1) + 8*FRACUNIT; topslope = 100*FRACUNIT/160; // can't shoot outside view angles bottomslope = -100*FRACUNIT/160; attackrange = distance; linetarget = NULL; P_PathTraverse ( t1->x, t1->y, x2, y2 , PT_ADDLINES|PT_ADDTHINGS, PTR_AimTraverse ); if (linetarget) return aimslope; return 0;}/*=================== P_LineAttack== if damage == 0, it is just a test trace that will leave linetarget set==================*/void P_LineAttack (mobj_t *t1, angle_t angle, fixed_t distance, fixed_t slope, int damage){ fixed_t x2, y2; angle >>= ANGLETOFINESHIFT; shootthing = t1; la_damage = damage; x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; shootz = t1->z + (t1->height>>1) + 8*FRACUNIT; shootz -= t1->floorclip; attackrange = distance; aimslope = slope; if(P_PathTraverse(t1->x, t1->y, x2, y2, PT_ADDLINES|PT_ADDTHINGS, PTR_ShootTraverse)) { switch(PuffType) { case MT_PUNCHPUFF: S_StartSound(t1, SFX_FIGHTER_PUNCH_MISS); break; case MT_HAMMERPUFF: case MT_AXEPUFF: case MT_AXEPUFF_GLOW: S_StartSound(t1, SFX_FIGHTER_HAMMER_MISS); break; case MT_FLAMEPUFF: P_SpawnPuff(x2, y2, shootz+FixedMul(slope, distance)); break; default: break; } }}/*============================================================================== USE LINES==============================================================================*/mobj_t *usething;boolean PTR_UseTraverse (intercept_t *in){ int sound; fixed_t pheight; if (!in->d.line->special) { P_LineOpening (in->d.line); if (openrange <= 0) { if(usething->player) { switch(usething->player->class) { case PCLASS_FIGHTER: sound = SFX_PLAYER_FIGHTER_FAILED_USE; break; case PCLASS_CLERIC: sound = SFX_PLAYER_CLERIC_FAILED_USE; break; case PCLASS_MAGE: sound = SFX_PLAYER_MAGE_FAILED_USE; break; case PCLASS_PIG: sound = SFX_PIG_ACTIVE1; break; default: sound = SFX_NONE; break; } S_StartSound(usething, sound); } return false; // can't use through a wall } if(usething->player) { pheight = usething->z + (usething->height/2); if ((opentop < pheight) || (openbottom > pheight)) { switch(usething->player->class) { case PCLASS_FIGHTER: sound = SFX_PLAYER_FIGHTER_FAILED_USE; break; case PCLASS_CLERIC: sound = SFX_PLAYER_CLERIC_FAILED_USE; break; case PCLASS_MAGE: sound = SFX_PLAYER_MAGE_FAILED_USE; break; case PCLASS_PIG: sound = SFX_PIG_ACTIVE1; break; default: sound = SFX_NONE; break; } S_StartSound(usething, sound); } } return true ; // not a special line, but keep checking } if (P_PointOnLineSide (usething->x, usething->y, in->d.line) == 1) return false; // don't use back sides// P_UseSpecialLine (usething, in->d.line); P_ActivateLine(in->d.line, usething, 0, SPAC_USE); return false; // can't use for than one special line in a row}/*================== P_UseLines== Looks for special lines in front of the player to activate================*/void P_UseLines (player_t *player){ int angle; fixed_t x1, y1, x2, y2; usething = player->mo; angle = player->mo->angle >> ANGLETOFINESHIFT; x1 = player->mo->x; y1 = player->mo->y; x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle]; y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle]; P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse );}//==========================================================================//// PTR_PuzzleItemTraverse////==========================================================================#define USE_PUZZLE_ITEM_SPECIAL 129static mobj_t *PuzzleItemUser;static int PuzzleItemType;static boolean PuzzleActivated;boolean PTR_PuzzleItemTraverse(intercept_t *in){ mobj_t *mobj; int sound; if(in->isaline) { // Check line if(in->d.line->special != USE_PUZZLE_ITEM_SPECIAL) { P_LineOpening(in->d.line); if(openrange <= 0) { sound = SFX_NONE; if(PuzzleItemUser->player) { switch(PuzzleItemUser->player->class) { case PCLASS_FIGHTER: sound = SFX_PUZZLE_FAIL_FIGHTER; break; case PCLASS_CLERIC: sound = SFX_PUZZLE_FAIL_CLERIC; break; case PCLASS_MAGE: sound = SFX_PUZZLE_FAIL_MAGE; break; default: sound = SFX_NONE; break; } } S_StartSound(PuzzleItemUser, sound); return false; // can't use through a wall } return true; // Continue searching } if(P_PointOnLineSide(PuzzleItemUser->x, PuzzleItemUser->y, in->d.line) == 1) { // Don't use back sides return false; } if(PuzzleItemType != in->d.line->arg1) { // Item type doesn't match return false; } P_StartACS(in->d.line->arg2, 0, &in->d.line->arg3, PuzzleItemUser, in->d.line, 0); in->d.line->special = 0; PuzzleActivated = true; return false; // Stop searching } // Check thing mobj = in->d.thing; if(mobj->special != USE_PUZZLE_ITEM_SPECIAL) { // Wrong special return true; } if(PuzzleItemType != mobj->args[0]) { // Item type doesn't match return true; } P_StartACS(mobj->args[1], 0, &mobj->args[2], PuzzleItemUser, NULL, 0); mobj->special = 0; PuzzleActivated = true; return false; // Stop searching}//==========================================================================//// P_UsePuzzleItem//// Returns true if the puzzle item was used on a line or a thing.////==========================================================================boolean P_UsePuzzleItem(player_t *player, int itemType){ int angle; fixed_t x1, y1, x2, y2; PuzzleItemType = itemType; PuzzleItemUser = player->mo; PuzzleActivated = false; angle = player->mo->angle>>ANGLETOFINESHIFT; x1 = player->mo->x; y1 = player->mo->y; x2 = x1+(USERANGE>>FRACBITS)*finecosine[angle]; y2 = y1+(USERANGE>>FRACBITS)*finesine[angle]; P_PathTraverse(x1, y1, x2, y2, PT_ADDLINES|PT_ADDTHINGS, PTR_PuzzleItemTraverse); return PuzzleActivated;}/*============================================================================== RADIUS ATTACK==============================================================================*/mobj_t *bombsource;mobj_t *bombspot;int bombdamage;int bombdistance;boolean DamageSource;/*=================== PIT_RadiusAttack== Source is the creature that casued the explosion at spot=================*/boolean PIT_RadiusAttack (mobj_t *thing){ fixed_t dx, dy, dist; int damage; if(!(thing->flags&MF_SHOOTABLE)) { return true; }// if(thing->flags2&MF2_BOSS)// { // Bosses take no damage from PIT_RadiusAttack// return(true);// } if(!DamageSource && thing == bombsource) { // don't damage the source of the explosion return true; } if(abs((thing->z-bombspot->z)>>FRACBITS) > 2*bombdistance) { // too high/low return true; } dx = abs(thing->x-bombspot->x); dy = abs(thing->y-bombspot->y); dist = dx > dy ? dx : dy; dist = (dist-thing->radius)>>FRACBITS; if(dist < 0) { dist = 0; } if(dist >= bombdistance) { // Out of range return true; } if(P_CheckSight(thing, bombspot)) { // OK to damage, target is in direct path damage = (bombdamage*(bombdistance-dist)/bombdistance)+1; if(thing->player) { damage >>= 2; } P_DamageMobj(thing, bombspot, bombsource, damage); } return(true);}/*=================== P_RadiusAttack== Source is the creature that caused the explosion at spot=================*/void P_RadiusAttack (mobj_t *spot, mobj_t *source, int damage, int distance, boolean damageSource){ int x,y, xl, xh, yl, yh; fixed_t dist; dist = (distance+MAXRADIUS)<<FRACBITS; yh = (spot->y+dist-bmaporgy)>>MAPBLOCKSHIFT; yl = (spot->y-dist-bmaporgy)>>MAPBLOCKSHIFT; xh = (spot->x+dist-bmaporgx)>>MAPBLOCKSHIFT; xl = (spot->x-dist-bmaporgx)>>MAPBLOCKSHIFT; bombspot = spot; bombsource = source; bombdamage = damage; bombdistance = distance; DamageSource = damageSource; for (y = yl; y <= yh; y++) { for (x = xl; x <= xh; x++) { P_BlockThingsIterator(x, y, PIT_RadiusAttack); } }}/*============================================================================== SECTOR HEIGHT CHANGING= After modifying a sectors floor or ceiling height, call this= routine to adjust the positions of all things that touch the= sector.== If anything doesn't fit anymore, true will be returned.= If crunch is true, they will take damage as they are being crushed= If Crunch is false, you should set the sector height back the way it= was and call P_ChangeSector again to undo the changes==============================================================================*/int crushchange;boolean nofit;/*================= PIT_ChangeSector================*/boolean PIT_ChangeSector (mobj_t *thing){ mobj_t *mo; if (P_ThingHeightClip (thing)) return true; // keep checking // crunch bodies to giblets if ((thing->flags&MF_CORPSE) && (thing->health <= 0)) { if (thing->flags&MF_NOBLOOD) { P_RemoveMobj (thing); } else { if (thing->state != &states[S_GIBS1]) { P_SetMobjState (thing, S_GIBS1); thing->height = 0; thing->radius = 0; S_StartSound(thing, SFX_PLAYER_FALLING_SPLAT); } } return true; // keep checking } // crunch dropped items if (thing->flags2&MF2_DROPPED) { P_RemoveMobj (thing); return true; // keep checking } if (! (thing->flags & MF_SHOOTABLE) ) return true; // assume it is bloody gibs or something nofit = true; if (crushchange && !(leveltime&3)) { P_DamageMobj(thing, NULL, NULL, crushchange); // spray blood in a random direction if ((!(thing->flags&MF_NOBLOOD)) && (!(thing->flags2&MF2_INVULNERABLE))) { mo = P_SpawnMobj (thing->x, thing->y, thing->z + thing->height/2, MT_BLOOD); mo->momx = (P_Random() - P_Random ())<<12; mo->momy = (P_Random() - P_Random ())<<12; } } return true; // keep checking (crush other things)}/*================= P_ChangeSector================*/boolean P_ChangeSector (sector_t *sector, int crunch){ int x,y; nofit = false; crushchange = crunch;// recheck heights for all things near the moving sector for (x=sector->blockbox[BOXLEFT] ; x<= sector->blockbox[BOXRIGHT] ; x++) for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++) P_BlockThingsIterator (x, y, PIT_ChangeSector); return nofit;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -