Beispiel #1
0
boolean P_ActivateLine(line_t *line, mobj_t *mo, int side, int activationType)
{
	int     lineActivation;
	boolean repeat;
	boolean buttonSuccess;

	lineActivation = GET_SPAC(line->flags);
	if(lineActivation != activationType)
	{
		return false;
	}
	if(!mo->player && !(mo->flags & MF_MISSILE))
	{
		if(lineActivation != SPAC_MCROSS)
		{						// currently, monsters can only activate the MCROSS activation type
			return false;
		}
		if(line->flags & ML_SECRET)
			return false;		// never open secret doors
	}
	repeat = line->flags & ML_REPEAT_SPECIAL;
	buttonSuccess = false;

	buttonSuccess =
		P_ExecuteLineSpecial(line->special, &line->arg1, line, side, mo);
	if(!repeat && buttonSuccess)
	{							// clear the special on non-retriggerable lines
		line->special = 0;
	}
	if((lineActivation == SPAC_USE || lineActivation == SPAC_IMPACT) &&
	   buttonSuccess)
	{
		P_ChangeSwitchTexture(line, repeat);
	}
	return true;
}
Beispiel #2
0
void P_TranslateLineDef (line_t *ld, maplinedef_t *mld)
{
	unsigned short special = (unsigned short) LittleShort(mld->special);
	short tag = LittleShort(mld->tag);
	DWORD flags = LittleShort(mld->flags);
	INTBOOL passthrough = 0;

	DWORD flags1 = flags;
	DWORD newflags = 0;

	for(int i=0;i<16;i++)
	{
		if ((flags & (1<<i)) && LineFlagTranslations[i].ismask)
		{
			flags1 &= LineFlagTranslations[i].newvalue;
		}
	}
	for(int i=0;i<16;i++)
	{
		if ((flags1 & (1<<i)) && !LineFlagTranslations[i].ismask)
		{
			switch (LineFlagTranslations[i].newvalue)
			{
			case -1:
				passthrough = true;
				break;
			case -2:
				ld->Alpha = FRACUNIT*3/4;
				break;
			default:
				newflags |= LineFlagTranslations[i].newvalue;
				break;
			}
		}
	}
	flags = newflags;

	// For purposes of maintaining BOOM compatibility, each
	// line also needs to have its ID set to the same as its tag.
	// An external conversion program would need to do this more
	// intelligently.
	ld->id = tag;

	// 0 specials are never translated.
	if (special == 0)
	{
		ld->special = 0;
		ld->flags = flags;
		ld->args[0] = mld->tag;
		memset (ld->args+1, 0, sizeof(ld->args)-sizeof(ld->args[0]));
		return;
	}

	FLineTrans *linetrans = NULL;
	if (special < SimpleLineTranslations.Size()) linetrans = &SimpleLineTranslations[special];
	if (linetrans != NULL && linetrans->special != 0)
	{
		ld->special = linetrans->special;

		ld->flags = flags | ((linetrans->flags & 0x1f) << 9);
		if (linetrans->flags & 0x20) ld->flags |= ML_FIRSTSIDEONLY;
		ld->activation = 1 << GET_SPAC(ld->flags);
		if (ld->activation == SPAC_AnyCross)
		{ // this is really PTouch
			ld->activation = SPAC_Impact|SPAC_PCross;
		}
		else if (ld->activation == SPAC_Impact)
		{ // In non-UMDF maps, Impact implies PCross
			ld->activation = SPAC_Impact | SPAC_PCross;
		}
		ld->flags &= ~ML_SPAC_MASK;

		if (passthrough && ld->activation == SPAC_Use)
		{
			ld->activation = SPAC_UseThrough;
		}
		// Set special arguments.
		FXlatExprState state;
		state.tag = tag;
		state.linetype = special;
		for (int t = 0; t < LINETRANS_MAXARGS; ++t)
		{
			int arg = linetrans->args[t];
			int argop = (linetrans->flags >> (LINETRANS_TAGSHIFT + t*TAGOP_NUMBITS)) & TAGOP_MASK;

			switch (argop)
			{
			case ARGOP_Const:
				ld->args[t] = arg;
				break;
			case ARGOP_Tag:
				ld->args[t] = tag;
				break;
			case ARGOP_Expr:
				{
					int *xnode = &XlatExpressions[arg];
					state.bIsConstant = true;
					XlatExprEval[*xnode](&ld->args[t], xnode, &state);
				}
				break;
			default:
				assert(0);
				ld->args[t] = 0;
				break;
			}
		}

		if ((ld->flags & ML_SECRET) && ld->activation & (SPAC_Use|SPAC_UseThrough))
		{
			ld->flags &= ~ML_MONSTERSCANACTIVATE;
		}
		return;
	}
Beispiel #3
0
BOOL EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing,
                int tag, int speed, int delay, card_t lock)
{
	BOOL		rtn = false;
	int 		secnum;
	sector_t*	sec;
    DDoor *door;

	if (lock && thing && !P_CheckKeys (thing->player, lock, tag))
		return false;

	if (tag == 0)
	{		// [RH] manual door
		if (!line)
			return false;

		// if the wrong side of door is pushed, give oof sound
		if (line->sidenum[1]==R_NOSIDE)				// killough
		{
			UV_SoundAvoidPlayer (thing, CHAN_VOICE, "player/male/grunt1", ATTN_NORM);
			return false;
		}

		// get the sector on the second side of activating linedef
		sec = sides[line->sidenum[1]].sector;
		secnum = sec-sectors;

		if (sec->ceilingdata && P_MovingCeilingCompleted(sec))
		{
			sec->ceilingdata->Destroy();
			sec->ceilingdata = NULL;
		}
		
		// if door already has a thinker, use it
		door = static_cast<DDoor *>(sec->ceilingdata);
		// cph 2001/04/05 -
		// Original Doom didn't distinguish floor/lighting/ceiling
		// actions, so we need to do the same in demo compatibility mode.
		//   [SL] 2011-06-20 - Credit to PrBoom for the fix
		if (!door)
			door = static_cast<DDoor *>(sec->floordata);
		if (!door)
			door = static_cast<DDoor *>(sec->lightingdata);

		if (door)
		{
			// ONLY FOR "RAISE" DOORS, NOT "OPEN"s
			if (door->m_Type == DDoor::doorRaise && type == DDoor::doorRaise)
			{
				if (sec->ceilingdata && sec->ceilingdata->IsKindOf (RUNTIME_CLASS(DDoor)))
				{
					if (door->m_Status == DDoor::closing)
					{
						// go back up
						door->m_Status = DDoor::reopening;
						return true;
					}
					else if (GET_SPAC(line->flags) == SPAC_PUSH)
					{
						// [RH] activate push doors don't go back down when you
						// run into them (otherwise opening them would be
						// a real pain).
						door->m_Line = line;
						return true;	
					}
					else if (thing && thing->player)
					{
						// go back down
						door->m_Status = DDoor::closing;
						return true;
					}
				}
				return false;
			}
		}
        else
        {
            door = new DDoor(sec, line, type, speed, delay);
            P_AddMovingCeiling(sec);
        }
		if (door)
        {
			rtn = true;
        }
	}
	else
	{	// [RH] Remote door
		secnum = -1;
		while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
		{
			sec = &sectors[secnum];
			// if the ceiling already moving, don't start the door action
			if (sec->ceilingdata)
				continue;

			door = new DDoor(sec, line, type, speed, delay);
			P_AddMovingCeiling(sec);
			
			if (door)
				rtn = true;
		}
	}
	
	return rtn;
}
Beispiel #4
0
BOOL EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing,
                int tag, int speed, int delay, card_t lock)
{
    BOOL		rtn = false;
    int 		secnum;
    sector_t*	sec;
    DDoor *door;

    if (lock && thing && !P_CheckKeys (thing->player, lock, tag))
        return false;

    if (tag == 0)
    {   // [RH] manual door
        if (!line)
            return false;

        // if the wrong side of door is pushed, give oof sound
        if (line->sidenum[1]==-1)				// killough
        {
            UV_SoundAvoidPlayer (thing, CHAN_VOICE, "player/male/grunt1", ATTN_NORM);
            return false;
        }

        // get the sector on the second side of activating linedef
        sec = sides[line->sidenum[1]].sector;
        secnum = sec-sectors;

        // if door already has a thinker, use it
        if (sec->ceilingdata && sec->ceilingdata->IsKindOf (RUNTIME_CLASS(DDoor)))
        {
            door = static_cast<DDoor *>(sec->ceilingdata);
            door->m_Line = line;

            // ONLY FOR "RAISE" DOORS, NOT "OPEN"s
            if (door->m_Type == DDoor::doorRaise && type == DDoor::doorRaise)
            {
                if (door->m_Direction == -1)
                {
                    door->m_Direction = 1;	// go back up
                }
                else if (GET_SPAC(line->flags) != SPAC_PUSH)
                    // [RH] activate push doors don't go back down when you
                    //		run into them (otherwise opening them would be
                    //		a real pain).
                {
                    if (thing && !thing->player)
                        return false;	// JDC: bad guys never close doors

                    // From Chocolate Doom:
                    // When is a door not a door?
                    // In Vanilla, door->direction is set, even though
                    // "specialdata" might not actually point at a door.

                    else if (sec->floordata && sec->floordata->IsKindOf (RUNTIME_CLASS(DPlat)))
                    {
                        // Erm, this is a plat, not a door.
                        // This notably causes a problem in ep1-0500.lmp where
                        // a plat and a door are cross-referenced; the door
                        // doesn't open on 64-bit.
                        // The direction field in vldoor_t corresponds to the wait
                        // field in plat_t.  Let's set that to -1 instead.

                        DPlat *plat = static_cast<DPlat *>(sec->floordata);
                        byte state;
                        int count;

                        plat->GetState(state, count);

                        if (count >= 16)    // ep1-0500 always returns a count of 16.
                            return false;   // We may be able to always return false?
                    }
                    else
                    {
                        door->m_Direction = -1;	// try going back down anyway?
                    }
                }
                return true;
            }
        }
        else
        {
            door = new DDoor(sec, line, type, speed, delay);
        }
        if (door)
        {
            rtn = true;
        }
    }
    else
    {   // [RH] Remote door

        secnum = -1;
        while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
        {
            sec = &sectors[secnum];
            // if the ceiling already moving, don't start the door action
            if (sec->ceilingdata)
                continue;

            if (new DDoor (sec, line, type, speed, delay))
                rtn = true;
        }

    }
    return rtn;
}
Beispiel #5
0
void P_TranslateLineDef (line_t *ld, maplinedef_t *mld)
{
	short special = LESHORT(mld->special);
	short tag = LESHORT(mld->tag);
	short flags = LESHORT(mld->flags);
	bool passthrough = (flags & ML_PASSUSE_BOOM);
	int i;
	
	flags &= 0x01ff;	// Ignore flags unknown to DOOM

	if (special <= NUM_SPECIALS)
	{
		// This is a regular special; translate thru LUT
		flags = flags | (SpecialTranslation[special].flags << 8);
		if (passthrough)
		{	
			if (GET_SPAC(flags) == SPAC_USE)
			{
				flags &= ~ML_SPAC_MASK;
				flags |= SPAC_USETHROUGH << ML_SPAC_SHIFT;
			}
			if (GET_SPAC(flags) == SPAC_CROSS)
			{
				flags &= ~ML_SPAC_MASK;
				flags |= SPAC_CROSSTHROUGH << ML_SPAC_SHIFT;
			}
			
			// TODO: what to do with gun-activated lines with passthrough?
		}

		ld->special = SpecialTranslation[special].newspecial;
		for (i = 0; i < 5; i++)
			ld->args[i] = SpecialTranslation[special].args[i] == TAG ? tag :
						  SpecialTranslation[special].args[i];
	}
	else if (special == 337)
	{
		ld->special = Line_Horizon;
		ld->flags = flags;
		ld->id = tag;
		memset(ld->args, 0, sizeof(ld->args));
	}
	else if (special >= 340 && special <= 347)
	{
		// [SL] 2012-01-30 - convert to ZDoom Plane_Align special for
		// sloping sectors
		ld->special = Plane_Align;
		ld->flags = flags;
		ld->id = tag;
		memset(ld->args, 0, sizeof(ld->args));
		
		switch (special)
		{
		case 340:		// Slope the Floor in front of the line
			ld->args[0] = 1;
			break;
		case 341:		// Slope the Ceiling in front of the line
			ld->args[1] = 1;
			break;
		case 342:		// Slope the Floor+Ceiling in front of the line
			ld->args[0] = ld->args[1] = 1;
			break;
		case 343:		// Slope the Floor behind the line
			ld->args[0] = 2;
			break;
		case 344:		// Slope the Ceiling behind the line
			ld->args[1] = 2;
			break;
		case 345:		// Slope the Floor+Ceiling behind the line
			ld->args[0] = ld->args[1] = 2;
			break;
		case 346:		// Slope the Floor behind+Ceiling in front of the line
			ld->args[0] = 2;
			ld->args[1] = 1;
			break;
		case 347:		// Slope the Floor in front+Ceiling behind the line
			ld->args[0] = 1;
			ld->args[1] = 2;
		}
	}
	else if (special <= GenCrusherBase)
	{
		if (special >= OdamexStaticInits && special < OdamexStaticInits + NUM_STATIC_INITS)
		{
			// An Odamex Static_Init special
			ld->special = Static_Init;
			ld->args[0] = tag;
			ld->args[1] = special - OdamexStaticInits;
		}
		else
		{
			// This is an unknown special. Just zero it.
			ld->special = 0;
			memset (ld->args, 0, sizeof(ld->args));
		}
	}
	else
	{
		// Anything else is a BOOM generalized linedef type
		switch (special & 0x0007)
		{
		case WalkMany:
			flags |= ML_REPEAT_SPECIAL;
		case WalkOnce:
            if (passthrough)
                flags |= SPAC_CROSSTHROUGH << ML_SPAC_SHIFT;
            else
                flags |= SPAC_CROSS << ML_SPAC_SHIFT;
			break;

		case SwitchMany:
		case PushMany:
			flags |= ML_REPEAT_SPECIAL;
		case SwitchOnce:
		case PushOnce:
			if (passthrough)
				flags |= SPAC_USETHROUGH << ML_SPAC_SHIFT;
			else
				flags |= SPAC_USE << ML_SPAC_SHIFT;
			break;

		case GunMany:
			flags |= ML_REPEAT_SPECIAL;
		case GunOnce:
			flags |= SPAC_IMPACT << ML_SPAC_SHIFT;
			break;
		}

		// We treat push triggers like switch triggers with zero tags.
		if ((special & 0x0007) == PushMany ||
			(special & 0x0007) == PushOnce)
			ld->args[0] = 0;
		else
			ld->args[0] = tag;

		if (special <= GenStairsBase)
		{
			// Generalized crusher (tag, dnspeed, upspeed, silent, damage)
			ld->special = Generic_Crusher;
			if (special & 0x0020)
				flags |= ML_MONSTERSCANACTIVATE;
			switch (special & 0x0018) {
				case 0x0000:	ld->args[1] = C_SLOW;	break;
				case 0x0008:	ld->args[1] = C_NORMAL;	break;
				case 0x0010:	ld->args[1] = C_FAST;	break;
				case 0x0018:	ld->args[1] = C_TURBO;	break;
			}
			ld->args[2] = ld->args[1];
			ld->args[3] = (special & 0x0040) >> 6;
			ld->args[4] = 10;
		}
		else if (special <= GenLiftBase)