bool FCajunMaster::Move (AActor *actor, ticcmd_t *cmd)
{
	fixed_t tryx, tryy;
	bool try_ok;
	int good;

	if (actor->movedir == DI_NODIR)
		return false;

	if ((unsigned)actor->movedir >= 8)
		I_Error ("Weird bot movedir!");

	tryx = actor->x + 8*xspeed[actor->movedir];
	tryy = actor->y + 8*yspeed[actor->movedir];

	try_ok = CleanAhead (actor, tryx, tryy, cmd);

	if (!try_ok) //Anything blocking that could be opened etc..
	{
		if (!spechit.Size ())
			return false;

		actor->movedir = DI_NODIR;

		good = 0;
		line_t *ld;

		while (spechit.Pop (ld))
		{
			bool tryit = true;

			if (ld->special == Door_LockedRaise && !P_CheckKeys (actor, ld->args[3], false))
				tryit = false;
			else if (ld->special == Generic_Door && !P_CheckKeys (actor, ld->args[4], false))
				tryit = false;

			if (tryit &&
				(P_TestActivateLine (ld, actor, 0, SPAC_Use) ||
				 P_TestActivateLine (ld, actor, 0, SPAC_Push)))
			{
				good |= ld == actor->BlockingLine ? 1 : 2;
			}
		}
		if (good && ((pr_botopendoor() >= 203) ^ (good & 1)))
		{
			cmd->ucmd.buttons |= BT_USE;
			cmd->ucmd.forwardmove = FORWARDRUN;
			return true;
		}
		else
			return false;
	}
	else //Move forward.
		cmd->ucmd.forwardmove = FORWARDRUN;

	return true;
}
Exemple #2
0
bool P_ActivateLine (line_t *line, AActor *mo, int side, int activationType, DVector3 *optpos)
{
	int lineActivation;
	INTBOOL repeat;
	INTBOOL buttonSuccess;
	BYTE special;

	if (!P_TestActivateLine (line, mo, side, activationType, optpos))
	{
		return false;
	}
	bool remote = (line->special != 7 && line->special != 8 && (line->special < 11 || line->special > 14));
	if (line->locknumber > 0 && !P_CheckKeys (mo, line->locknumber, remote)) return false;
	lineActivation = line->activation;
	repeat = line->flags & ML_REPEAT_SPECIAL;
	buttonSuccess = false;
	buttonSuccess = P_ExecuteSpecial(line->special,
					line, mo, side == 1, line->args[0],
					line->args[1], line->args[2],
					line->args[3], line->args[4]);

	special = line->special;
	if (!repeat && buttonSuccess)
	{ // clear the special on non-retriggerable lines
		line->special = 0;
	}

	if (buttonSuccess)
	{
		if (activationType == SPAC_Use || activationType == SPAC_Impact || activationType == SPAC_Push)
		{
			P_ChangeSwitchTexture (line->sidedef[0], repeat, special);
		}
	}
	// some old WADs use this method to create walls that change the texture when shot.
	else if (activationType == SPAC_Impact &&					// only for shootable triggers
		(level.flags2 & LEVEL2_DUMMYSWITCHES) &&				// this is only a compatibility setting for an old hack!
		!repeat &&												// only non-repeatable triggers
		(special<Generic_Floor || special>Generic_Crusher) &&	// not for Boom's generalized linedefs
		special &&												// not for lines without a special
		tagManager.LineHasID(line, line->args[0]) &&							// Safety check: exclude edited UDMF linedefs or ones that don't map the tag to args[0]
		line->args[0] &&										// only if there's a tag (which is stored in the first arg)
		P_FindFirstSectorFromTag (line->args[0]) == -1)			// only if no sector is tagged to this linedef
	{
		P_ChangeSwitchTexture (line->sidedef[0], repeat, special);
		line->special = 0;
	}
// end of changed code
	if (developer && buttonSuccess)
	{
		Printf ("Line special %d activated on line %i\n", special, int(line - lines));
	}
	return true;
}
Exemple #3
0
bool EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing,
				int tag, int speed, int delay, int lock, int lightTag, bool boomgen)
{
	bool		rtn = false;
	int 		secnum;
	sector_t*	sec;

	if (lock != 0 && !P_CheckKeys (thing, lock, tag != 0))
		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->sidedef[1] == NULL)			// killough
		{
			S_Sound (thing, CHAN_VOICE, "*usefail", 1, ATTN_NORM);
			return false;
		}

		// get the sector on the second side of activating linedef
		sec = line->sidedef[1]->sector;
		secnum = int(sec-sectors);

		// if door already has a thinker, use it
		if (sec->PlaneMoving(sector_t::ceiling))
		{
			// Boom used remote door logic for generalized doors, even if they are manual
			if (boomgen)
				return false;
			if (sec->ceilingdata->IsKindOf (RUNTIME_CLASS(DDoor)))
			{
				DDoor *door = barrier_cast<DDoor *>(sec->ceilingdata);

				// 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
						door->DoorSound (true);	// [RH] Make noise
					}
					else if (!(line->activation & (SPAC_Push|SPAC_MPush)))
						// [RH] activate push doors don't go back down when you
						//		run into them (otherwise opening them would be
						//		a real pain).
					{
						if (!thing->player || thing->player->Bot != NULL)
							return false;	// JDC: bad guys never close doors
											//Added by MC: Neither do bots.

						door->m_Direction = -1;	// start going down immediately

						// Start the door close sequence.
						door->DoorSound(false, SN_CheckSequence(sec, CHAN_CEILING));
						return true;
					}
					else
					{
						return false;
					}
				}
			}
			return false;
		}
		if (new DDoor (sec, type, speed, delay, lightTag))
			rtn = true;
	}
	else
	{	// [RH] Remote door

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

			if (new DDoor (sec, type, speed, delay, lightTag))
				rtn = true;
		}
				
	}
	return rtn;
}
Exemple #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]==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;
}
Exemple #5
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;
}