⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 p_map.c

📁 使用Doom引擎开发的著名游戏《毁灭巫师》的源代码。
💻 C
📖 第 1 页 / 共 4 页
字号:
			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 + -