📄 p_map.c
字号:
fixed_t y2;#ifdef PARANOIA if(!t1) I_Error("P_aimlineattack: mobj == NULL !!!");#endif angle >>= ANGLETOFINESHIFT; shootthing = t1; if(t1->player && demoversion>=128) { fixed_t cosineaiming=finecosine[t1->player->aiming>>ANGLETOFINESHIFT]; int aiming=((int)t1->player->aiming)>>ANGLETOFINESHIFT; x2 = t1->x + FixedMul(FixedMul(distance,finecosine[angle]),cosineaiming); y2 = t1->y + FixedMul(FixedMul(distance,finesine[angle]),cosineaiming); topslope = 100*FRACUNIT/160+finetangent[(2048+aiming) & FINEMASK]; bottomslope = -100*FRACUNIT/160+finetangent[(2048+aiming) & FINEMASK]; } else { x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; //added:15-02-98: Fab comments... // Doom's base engine says that at a distance of 160, // the 2d graphics on the plane x,y correspond 1/1 with plane units topslope = 100*FRACUNIT/160; bottomslope = -100*FRACUNIT/160; } shootz = lastz = t1->z + (t1->height>>1) + 8*FRACUNIT; // can't shoot outside view angles attackrange = distance; linetarget = NULL; //added:15-02-98: comments // traverse all linedefs and mobjs from the blockmap containing t1, // to the blockmap containing the dest. point. // Call the function for each mobj/line on the way, // starting with the mobj/linedef at the shortest distance... P_PathTraverse ( t1->x, t1->y, x2, y2, PT_ADDLINES|PT_ADDTHINGS, PTR_AimTraverse ); //added:15-02-98: linetarget is only for mobjs, not for linedefs if (linetarget) return aimslope; return 0;}//// P_LineAttack// If damage == 0, it is just a test trace// that will leave linetarget set.////added:16-02-98: Fab comments...// t1 est l'attaquant (player ou monstre)// angle est l'angle de tir sur le plan x,y (orientation)// distance est la port閑 maximale de la balle// slope est la pente vers la destination (up/down)// damage est les degats infliges par la ballevoid P_LineAttack ( mobj_t* t1, angle_t angle, fixed_t distance, fixed_t slope, int damage ){ fixed_t x2; fixed_t y2; angle >>= ANGLETOFINESHIFT; shootthing = t1; la_damage = damage; // player autoaimed attack, if(demoversion<128 || !t1->player) { x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; } else { fixed_t cosangle=finecosine[t1->player->aiming>>ANGLETOFINESHIFT]; x2 = t1->x + FixedMul(FixedMul(distance,finecosine[angle]),cosangle); y2 = t1->y + FixedMul(FixedMul(distance,finesine[angle]),cosangle); } shootz = lastz = t1->z + (t1->height>>1) + 8*FRACUNIT; if (t1->flags2 & MF2_FEETARECLIPPED) shootz -= FOOTCLIPSIZE; attackrange = distance; aimslope = slope; tmthing = shootthing; P_PathTraverse ( t1->x, t1->y, x2, y2, PT_ADDLINES|PT_ADDTHINGS, PTR_ShootTraverse );}//// USE LINES//mobj_t* usething;boolean PTR_UseTraverse (intercept_t* in){ int side; tmthing = NULL; if (!in->d.line->special) { P_LineOpening (in->d.line); if (openrange <= 0) { if( gamemode != heretic ) S_StartSound (usething, sfx_noway); // can't use through a wall return false; } // not a special line, but keep checking return true ; } side = 0; if (P_PointOnLineSide (usething->x, usething->y, in->d.line) == 1) side = 1; // return false; // don't use back side P_UseSpecialLine (usething, in->d.line, side); // can't use for than one special line in a row // SoM: USE MORE THAN ONE! if(boomsupport && (in->d.line->flags&ML_PASSUSE)) return true; else return false;}//// P_UseLines// Looks for special lines in front of the player to activate.//void P_UseLines (player_t* player){ int angle; fixed_t x1; fixed_t y1; fixed_t x2; fixed_t 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 );}//// RADIUS ATTACK//mobj_t* bombsource;mobj_t* bombspot;int bombdamage;//// PIT_RadiusAttack// "bombsource" is the creature// that caused the explosion at "bombspot".//boolean PIT_RadiusAttack (mobj_t* thing){ fixed_t dx; fixed_t dy; fixed_t dz; fixed_t dist; if (!(thing->flags & MF_SHOOTABLE) ) return true; // Boss spider and cyborg // take no damage from concussion. if (thing->type == MT_CYBORG || thing->type == MT_SPIDER || thing->type == MT_MINOTAUR || thing->type == MT_SORCERER1 || thing->type == MT_SORCERER2) return true; dx = abs(thing->x - bombspot->x); dy = abs(thing->y - bombspot->y); dist = dx>dy ? dx : dy; dist -= thing->radius; //added:22-02-98: now checks also z dist for rockets exploding // above yer head... if (demoversion>=112) { dz = abs(thing->z+(thing->height>>1) - bombspot->z); dist = dist > dz ? dist : dz; } dist >>= FRACBITS; if (dist < 0) dist = 0; if (dist >= bombdamage) return true; // out of range if (thing->floorz > bombspot->z && bombspot->ceilingz < thing->z) return true; if (thing->ceilingz < bombspot->z && bombspot->floorz > thing->z) return true; if ( P_CheckSight (thing, bombspot) ) { int damage=bombdamage - dist; int momx=0,momy=0; if( dist ) { momx = (thing->x - bombspot->x)/dist; momy = (thing->y - bombspot->y)/dist; } // must be in direct path if( P_DamageMobj (thing, bombspot, bombsource, damage) && (thing->flags & MF_NOBLOOD)==0 && demoversion>=129 ) P_SpawnBloodSplats (thing->x,thing->y,thing->z, damage, momx, momy); } 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 x; int y; int xl; int xh; int yl; int yh; fixed_t dist; dist = (damage+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; if (spot->type == MT_POD && spot->target) bombsource = spot->target; else bombsource = source; bombdamage = damage; 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.//boolean crushchange;boolean nofit;sector_t *sectorchecked;//// PIT_ChangeSector//boolean PIT_ChangeSector (mobj_t* thing){ mobj_t* mo; if (P_ThingHeightClip (thing)) { // keep checking return true; } // crunch bodies to giblets if (thing->health <= 0) { if( gamemode != heretic ) { P_SetMobjState (thing, S_GIBS); thing->flags &= ~MF_SOLID; //added:22-02-98: lets have a neat 'crunch' sound! S_StartSound (thing, sfx_slop); thing->skin = 0; } thing->height = 0; thing->radius = 0; thing->skin = 0; //added:22-02-98: lets have a neat 'crunch' sound! S_StartSound (thing, sfx_slop); // keep checking return true; } // crunch dropped items if (thing->flags & MF_DROPPED) { P_RemoveMobj (thing); // keep checking return true; } if (! (thing->flags & MF_SHOOTABLE) ) { // assume it is bloody gibs or something return true; } nofit = true; if (crushchange && !(leveltime % (4*NEWTICRATERATIO)) ) { P_DamageMobj(thing,NULL,NULL,10); if( demoversion<132 || (!(leveltime % (16*NEWTICRATERATIO)) && !(thing->flags&MF_NOBLOOD)) ) { // spray blood in a random direction mo = P_SpawnMobj (thing->x, thing->y, thing->z + thing->height/2, MT_BLOOD); mo->momx = P_SignedRandom()<<12; mo->momy = P_SignedRandom()<<12; } } // keep checking (crush other things) return true;}//// P_ChangeSector//boolean P_ChangeSector ( sector_t* sector, boolean crunch ){ int x; int y; nofit = false; crushchange = crunch; sectorchecked = sector; // re-check 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;}//SoM: 3/15/2000: New function. Much faster.boolean P_CheckSector(sector_t* sector, boolean crunch){ msecnode_t *n; if (!boomsupport) // use the old routine for old demos though return P_ChangeSector(sector,crunch); nofit = false; crushchange = crunch; // killough 4/4/98: scan list front-to-back until empty or exhausted, // restarting from beginning after each thing is processed. Avoids // crashes, and is sure to examine all things in the sector, and only // the things which are in the sector, until a steady-state is reached. // Things can arbitrarily be inserted and removed and it won't mess up. // // killough 4/7/98: simplified to avoid using complicated counter if(sector->numattached) { int i; sector_t* sec; for(i = 0; i < sector->numattached; i ++) { sec = §ors[sector->attached[i]]; for (n=sec->touching_thinglist; n; n=n->m_snext) n->visited = false; sec->moved = true; do { for (n=sec->touching_thinglist; n; n=n->m_snext) if (!n->visited) { n->visited = true; if (!(n->m_thing->flags & MF_NOBLOCKMAP)) PIT_ChangeSector(n->m_thing); break; } } while (n); } } // Mark all things invalid sector->moved = true; for (n=sector->touching_thinglist; n; n=n->m_snext) n->visited = false; do { for (n=sector->touchi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -