Beispiel #1
0
// [RH] Modified to support different source and destination ids.
// [RH] Modified some more to be accurate.
bool EV_SilentLineTeleport (line_t *line, int side, AActor *thing, int id, INTBOOL reverse)
{
	int i;
	line_t *l;

	if (side || thing->flags2 & MF2_NOTELEPORT || !line || line->sidedef[1] == NULL)
		return false;

	FLineIdIterator itr(id);
	while ((i = itr.Next()) >= 0)
	{
		if (line->Index() == i)
			continue;

		if ((l=&level.lines[i]) != line && l->backsector)
		{
			// Get the thing's position along the source linedef
			double pos;
			DVector2 npos;			// offsets from line
			double den;

			den = line->Delta().LengthSquared();
			if (den == 0)
			{
				pos = 0;
				npos.Zero();
			}
			else
			{
				double num = (thing->Pos().XY() - line->v1->fPos()) | line->Delta();
				if (num <= 0)
				{
					pos = 0;
				}
				else if (num >= den)
				{
					pos = 1;
				}
				else
				{
					pos = num / den;
				}
				npos = thing->Pos().XY() - line->v1->fPos() - line->Delta() * pos;
			}

			// Get the angle between the two linedefs, for rotating
			// orientation and velocity. Rotate 180 degrees, and flip
			// the position across the exit linedef, if reversed.
			DAngle angle = l->Delta().Angle() - line->Delta().Angle();

			if (!reverse)
			{
				angle += 180.;
				pos = 1 - pos;
			}

			// Sine, cosine of angle adjustment
			double s = angle.Sin();
			double c = angle.Cos();

			DVector2 p;

			// Rotate position along normal to match exit linedef
			p.X = npos.X*c - npos.Y*s;
			p.Y = npos.Y*c + npos.X*s;

			// Interpolate position across the exit linedef
			p += l->v1->fPos() + pos*l->Delta();

			// Whether this is a player, and if so, a pointer to its player_t.
			// Voodoo dolls are excluded by making sure thing->player->mo==thing.
			player_t *player = thing->player && thing->player->mo == thing ?
				thing->player : NULL;

			// Whether walking towards first side of exit linedef steps down
			bool stepdown = l->frontsector->floorplane.ZatPoint(p) < l->backsector->floorplane.ZatPoint(p);

			// Height of thing above ground
			double z = thing->Z() - thing->floorz;

			// Side to exit the linedef on positionally.
			//
			// Notes:
			//
			// This flag concerns exit position, not momentum. Due to
			// roundoff error, the thing can land on either the left or
			// the right side of the exit linedef, and steps must be
			// taken to make sure it does not end up on the wrong side.
			//
			// Exit momentum is always towards side 1 in a reversed
			// teleporter, and always towards side 0 otherwise.
			//
			// Exiting positionally on side 1 is always safe, as far
			// as avoiding oscillations and stuck-in-wall problems,
			// but may not be optimum for non-reversed teleporters.
			//
			// Exiting on side 0 can cause oscillations if momentum
			// is towards side 1, as it is with reversed teleporters.
			//
			// Exiting on side 1 slightly improves player viewing
			// when going down a step on a non-reversed teleporter.

			// Is this really still necessary with real math instead of imprecise trig tables?
#if 1
			int side = reverse || (player && stepdown);
			int fudge = FUDGEFACTOR;

			double dx = line->Delta().X;
			double dy = line->Delta().Y;
			// Make sure we are on correct side of exit linedef.
			while (P_PointOnLineSidePrecise(p, l) != side && --fudge >= 0)
			{
				if (fabs(dx) > fabs(dy))
					p.Y -= (dx < 0) != side ? -1 : 1;
				else
					p.X += (dy < 0) != side ? -1 : 1;
			}
#endif

			// Adjust z position to be same height above ground as before.
			// Ground level at the exit is measured as the higher of the
			// two floor heights at the exit linedef.
			z = z + l->sidedef[stepdown]->sector->floorplane.ZatPoint(p);

			// Attempt to teleport, aborting if blocked
			if (!P_TeleportMove (thing, DVector3(p, z), false))
			{
				return false;
			}

			if (thing == players[consoleplayer].camera)
			{
				R_ResetViewInterpolation ();
			}

			// Rotate thing's orientation according to difference in linedef angles
			thing->Angles.Yaw += angle;

			// Rotate thing's velocity to come out of exit just like it entered
			p = thing->Vel.XY();
			thing->Vel.X = p.X*c - p.Y*s;
			thing->Vel.Y = p.Y*c + p.X*s;

			// Adjust a player's view, in case there has been a height change
			if (player && player->mo == thing)
			{
				// Adjust player's local copy of velocity
				p = player->Vel;
				player->Vel.X = p.X*c - p.Y*s;
				player->Vel.Y = p.Y*c + p.X*s;

				// Save the current deltaviewheight, used in stepping
				double deltaviewheight = player->deltaviewheight;

				// Clear deltaviewheight, since we don't want any changes now
				player->deltaviewheight = 0;

				// Set player's view according to the newly set parameters
				P_CalcHeight(player);

				// Reset the delta to have the same dynamics as before
				player->deltaviewheight = deltaviewheight;
			}

			return true;
		}
	}
	return false;
}
Beispiel #2
0
bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
				 bool useFog, bool sourceFog, bool keepOrientation, bool bHaltVelocity, bool keepHeight)
{
	fixed_t oldx;
	fixed_t oldy;
	fixed_t oldz;
	fixed_t aboveFloor;
	player_t *player;
	angle_t an;
	sector_t *destsect;
	bool resetpitch = false;
	fixed_t floorheight, ceilingheight;
	fixed_t missilespeed;

	oldx = thing->x;
	oldy = thing->y;
	oldz = thing->z;
	aboveFloor = thing->z - thing->floorz;
	destsect = P_PointInSector (x, y);
	// killough 5/12/98: exclude voodoo dolls:
	player = thing->player;
	if (player && player->mo != thing)
		player = NULL;
	floorheight = destsect->floorplane.ZatPoint (x, y);
	ceilingheight = destsect->ceilingplane.ZatPoint (x, y);
	if (thing->flags & MF_MISSILE)
	{ // We don't measure z velocity, because it doesn't change.
		missilespeed = xs_CRoundToInt(TVector2<double>(thing->velx, thing->vely).Length());
	}
	if (keepHeight)
	{
		z = floorheight + aboveFloor;
	}
	else if (z == ONFLOORZ)
	{
		if (player)
		{
			if (thing->flags & MF_NOGRAVITY && aboveFloor)
			{
				z = floorheight + aboveFloor;
				if (z + thing->height > ceilingheight)
				{
					z = ceilingheight - thing->height;
				}
			}
			else
			{
				z = floorheight;
				if (!keepOrientation)
				{
					resetpitch = false;
				}
			}
		}
		else if (thing->flags & MF_MISSILE)
		{
			z = floorheight + aboveFloor;
			if (z + thing->height > ceilingheight)
			{
				z = ceilingheight - thing->height;
			}
		}
		else
		{
			z = floorheight;
		}
	}
	if (!P_TeleportMove (thing, x, y, z, false))
	{
		return false;
	}
	if (player)
	{
		player->viewz = thing->z + player->viewheight;
		if (resetpitch)
		{
			player->mo->pitch = 0;
		}
	}
	if (!keepOrientation)
	{
		thing->angle = angle;
	}
	else
	{
		angle = thing->angle;
	}
	// Spawn teleport fog at source and destination
	if (sourceFog)
	{
		fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT;
		AActor *fog = Spawn<ATeleportFog> (oldx, oldy, oldz + fogDelta, ALLOW_REPLACE);
		fog->target = thing;
	}
	if (useFog)
	{
		fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT;
		an = angle >> ANGLETOFINESHIFT;
		AActor *fog = Spawn<ATeleportFog> (x + 20*finecosine[an],
			y + 20*finesine[an], thing->z + fogDelta, ALLOW_REPLACE);
		fog->target = thing;
		if (thing->player)
		{
			// [RH] Zoom player's field of vision
			// [BC] && bHaltVelocity.
			if (telezoom && thing->player->mo == thing && bHaltVelocity)
				thing->player->FOV = MIN (175.f, thing->player->DesiredFOV + 45.f);
		}
	}
	// [BC] && bHaltVelocity.
	if (thing->player && (useFog || !keepOrientation) && bHaltVelocity)
	{
		// Freeze player for about .5 sec
		if (thing->Inventory == NULL || thing->Inventory->GetSpeedFactor() <= FRACUNIT)
			thing->reactiontime = 18;
	}
	if (thing->flags & MF_MISSILE)
	{
		angle >>= ANGLETOFINESHIFT;
		thing->velx = FixedMul (missilespeed, finecosine[angle]);
		thing->vely = FixedMul (missilespeed, finesine[angle]);
	}
//
// P_SpawnPlayer
// Called when a player is spawned on the level.
// Most of the player structure stays unchanged
//	between levels.
//
void P_SpawnPlayer (player_t &player, mapthing2_t *mthing)
{
    // denis - clients should not control spawning
    if(!serverside)
        return;

    // [RH] Things 4001-? are also multiplayer starts. Just like 1-4.
    //		To make things simpler, figure out which player is being
    //		spawned here.
    player_t *p = &player;

    // not playing?
    if(!p->ingame())
        return;

    if (p->playerstate == PST_REBORN || p->playerstate == PST_ENTER)
        G_PlayerReborn (*p);

    AActor *mobj = new AActor (mthing->x << FRACBITS, mthing->y << FRACBITS, ONFLOORZ, MT_PLAYER);

    // set color translations for player sprites
    // [RH] Different now: MF_TRANSLATION is not used.
    //		  mobj->translation = translationtables + 256*playernum;

    mobj->angle = ANG45 * (mthing->angle/45);
    mobj->pitch = mobj->roll = 0;
    mobj->player = p;
    mobj->health = p->health;

    // [RH] Set player sprite based on skin
    if(p->userinfo.skin >= numskins)
        p->userinfo.skin = 0;

    mobj->sprite = skins[p->userinfo.skin].sprite;

    p->fov = 90.0f;
    p->mo = p->camera = mobj->ptr();
    p->playerstate = PST_LIVE;
    p->refire = 0;
    p->damagecount = 0;
    p->bonuscount = 0;
    p->extralight = 0;
    p->fixedcolormap = 0;
    p->viewheight = VIEWHEIGHT;
    p->xviewshift = 0;
    p->attacker = AActor::AActorPtr();

    // Set up some special spectator stuff
    if (p->spectator)
    {
        mobj->translucency = 0;
        p->mo->flags |= MF_SPECTATOR;
        p->mo->flags2 |= MF2_FLY;
    }

    // [RH] Allow chasecam for demo watching
    //if ((demoplayback || demonew) && chasedemo)
    //	p->cheats = CF_CHASECAM;

    // setup gun psprite
    P_SetupPsprites (p);

    // give all cards in death match mode
    if (sv_gametype != GM_COOP)
    {
        for (int i = 0; i < NUMCARDS; i++)
            p->cards[i] = true;
    }

    if(serverside)
    {
        // [RH] If someone is in the way, kill them
        P_TeleportMove (mobj, mobj->x, mobj->y, mobj->z, true);

        // [BC] Do script stuff
        if (level.behavior != NULL)
        {
            if (p->playerstate == PST_ENTER)
            {
                level.behavior->StartTypedScripts (SCRIPT_Enter, p->mo);
            }
            else if (p->playerstate == PST_REBORN)
            {
                level.behavior->StartTypedScripts (SCRIPT_Respawn, p->mo);
            }
        }

        // send new objects
        SV_SpawnMobj(mobj);
    }
}
Beispiel #4
0
bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
				 bool useFog, bool sourceFog, bool keepOrientation, bool bHaltVelocity, bool keepHeight)
{
	bool predicting = (thing->player && (thing->player->cheats & CF_PREDICTING));

	fixedvec3 old;
	fixed_t aboveFloor;
	player_t *player;
	angle_t an;
	sector_t *destsect;
	bool resetpitch = false;
	fixed_t floorheight, ceilingheight;
	fixed_t missilespeed = 0;

	old = thing->Pos();
	aboveFloor = thing->Z() - thing->floorz;
	destsect = P_PointInSector (x, y);
	// killough 5/12/98: exclude voodoo dolls:
	player = thing->player;
	if (player && player->mo != thing)
		player = NULL;
	floorheight = destsect->floorplane.ZatPoint (x, y);
	ceilingheight = destsect->ceilingplane.ZatPoint (x, y);
	if (thing->flags & MF_MISSILE)
	{ // We don't measure z velocity, because it doesn't change.
		missilespeed = xs_CRoundToInt(TVector2<double>(thing->velx, thing->vely).Length());
	}
	if (keepHeight)
	{
		z = floorheight + aboveFloor;
	}
	else if (z == ONFLOORZ)
	{
		if (player)
		{
			if (thing->flags & MF_NOGRAVITY && aboveFloor)
			{
				z = floorheight + aboveFloor;
				if (z + thing->height > ceilingheight)
				{
					z = ceilingheight - thing->height;
				}
			}
			else
			{
				z = floorheight;
				if (!keepOrientation)
				{
					resetpitch = false;
				}
			}
		}
		else if (thing->flags & MF_MISSILE)
		{
			z = floorheight + aboveFloor;
			if (z + thing->height > ceilingheight)
			{
				z = ceilingheight - thing->height;
			}
		}
		else
		{
			z = floorheight;
		}
	}
	if (!P_TeleportMove (thing, x, y, z, false))
	{
		return false;
	}
	if (player)
	{
		player->viewz = thing->Z() + player->viewheight;
		if (resetpitch)
		{
			player->mo->pitch = 0;
		}
	}
	if (!keepOrientation)
	{
		thing->angle = angle;
	}
	else
	{
		angle = thing->angle;
	}
	// Spawn teleport fog at source and destination
	if (sourceFog && !predicting)
	{
		P_SpawnTeleportFog(thing, old, true, true); //Passes the actor through which then pulls the TeleFog metadata types based on properties.
	}
	if (useFog)
	{
		if (!predicting)
		{
			fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT;
			an = angle >> ANGLETOFINESHIFT;
			P_SpawnTeleportFog(thing, x + 20 * finecosine[an], y + 20 * finesine[an], thing->Z() + fogDelta, false, true);

		}
		if (thing->player)
		{
			// [RH] Zoom player's field of vision
			// [BC] && bHaltVelocity.
			if (telezoom && thing->player->mo == thing && bHaltVelocity)
				thing->player->FOV = MIN (175.f, thing->player->DesiredFOV + 45.f);
		}
	}
Beispiel #5
0
int EV_Teleport(Line* line, int side, mobj_t* mo, dd_bool spawnFog)
{
    mobj_t* dest;

    // Clients cannot teleport on their own.
    if(IS_CLIENT) return 0;

    if(mo->flags2 & MF2_NOTELEPORT) return 0;

    // Don't teleport if hit back of line, so you can get out of teleporter.
    if(side == 1) return 0;

    if((dest = getTeleportDestination(P_ToXLine(line)->tag)) != NULL)
    {
        // A suitable destination has been found.
        coord_t oldPos[3], aboveFloor;
        angle_t oldAngle;
        mobj_t* fog;
        uint an;

        memcpy(oldPos, mo->origin, sizeof(mo->origin));
        oldAngle = mo->angle;
        aboveFloor = mo->origin[VZ] - mo->floorZ;

        if(!P_TeleportMove(mo, dest->origin[VX], dest->origin[VY], false))
            return 0;

        mo->origin[VZ] = mo->floorZ;

        if(spawnFog)
        {
            // Spawn teleport fog at source and destination.
            if((fog = P_SpawnMobj(MT_TFOG, oldPos, oldAngle + ANG180, 0)))
                S_StartSound(SFX_TELEPT, fog);

            an = dest->angle >> ANGLETOFINESHIFT;
            if((fog = P_SpawnMobjXYZ(MT_TFOG, dest->origin[VX] + 20 * FIX2FLT(finecosine[an]),
                                              dest->origin[VY] + 20 * FIX2FLT(finesine[an]),
                                              mo->origin[VZ], dest->angle + ANG180, 0)))
            {
                // Emit sound, where?
                S_StartSound(SFX_TELEPT, fog);
            }
        }

        mo->angle = dest->angle;
        if(mo->flags2 & MF2_FLOORCLIP)
        {
            mo->floorClip = 0;

            if(FEQUAL(mo->origin[VZ], P_GetDoublep(Mobj_Sector(mo), DMU_FLOOR_HEIGHT)))
            {
                terraintype_t const *tt = P_MobjFloorTerrain(mo);
                if(tt->flags & TTF_FLOORCLIP)
                {
                    mo->floorClip = 10;
                }
            }
        }

        mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0;

        // $voodoodolls Must be the real player.
        if(mo->player && mo->player->plr->mo == mo)
        {
            mo->reactionTime = 18; // Don't move for a bit.
            if(mo->player->powers[PT_FLIGHT] && aboveFloor > 0)
            {
                mo->origin[VZ] = mo->floorZ + aboveFloor;
                if(mo->origin[VZ] + mo->height > mo->ceilingZ)
                {
                    mo->origin[VZ] = mo->ceilingZ - mo->height;
                }
            }
            else
            {
                //mo->dPlayer->clLookDir = 0; /* $unifiedangles */
                mo->dPlayer->lookDir = 0;
            }
            mo->player->viewHeight = (coord_t) cfg.common.plrViewHeight;
            mo->player->viewHeightDelta = 0;
            mo->player->viewZ = mo->origin[VZ] + mo->player->viewHeight;
            mo->player->viewOffset[VX] = mo->player->viewOffset[VY] = mo->player->viewOffset[VZ] = 0;
            mo->player->bob = 0;

            //mo->dPlayer->clAngle = mo->angle; /* $unifiedangles */
            mo->dPlayer->flags |= DDPF_FIXANGLES | DDPF_FIXORIGIN | DDPF_FIXMOM;
        }

        return 1;
    }
Beispiel #6
0
//
// TELEPORTATION
//
dboolean EV_Teleport(line_t *line, int side, mobj_t *thing)
{
    thinker_t   *thinker;
    int         i;

    // Don't teleport missiles.
    // Don't teleport if hit back of line, so you can get out of teleporter.
    if (side || (thing->flags & MF_MISSILE))
        return false;

    // [BH] Don't teleport corpses once kill ccmd used
    if (thing->flags2 & MF2_MASSACRE)
        return false;

    // killough 1/31/98: improve performance by using
    // P_FindSectorFromLineTag instead of simple linear search.
    for (i = -1; (i = P_FindSectorFromLineTag(line, i)) >= 0;)
        for (thinker = thinkerclasscap[th_mobj].cnext; thinker != &thinkerclasscap[th_mobj];
            thinker = thinker->cnext)
        {
            mobj_t  *m;

            if ((m = (mobj_t *)thinker)->type == MT_TELEPORTMAN
                && m->subsector->sector - sectors == i)
            {
                fixed_t     oldx = thing->x;
                fixed_t     oldy = thing->y;
                fixed_t     oldz = thing->z;
                player_t    *player = thing->player;

                // killough 5/12/98: exclude voodoo dolls:
                if (player && player->mo != thing)
                    player = NULL;

                if (P_TeleportMove(thing, m->x, m->y, m->z, false))     // killough 8/9/98
                {
                    mobj_t  *fog;
                    fixed_t newx = m->x;
                    fixed_t newy = m->y;

                    // spawn teleport fog at source
                    fog = P_SpawnMobj(oldx, oldy, oldz, MT_TFOG);
                    fog->angle = thing->angle;
                    S_StartSound(fog, sfx_telept);

                    // spawn teleport fog at destination
                    thing->z = thing->floorz;
                    if (player)
                    {
                        unsigned int    an = m->angle >> ANGLETOFINESHIFT;

                        newx += 20 * finecosine[an];
                        newy += 20 * finesine[an];
                        player->viewz = thing->z + player->viewheight;
                    }
                    fog = P_SpawnMobj(newx, newy, thing->z, MT_TFOG);
                    fog->angle = m->angle;
                    S_StartSound(fog, sfx_telept);

                    if (player)
                    {
                        // [BH] teleport can be drawn on automap
                        if (line->backsector)
                        {
                            int j;

                            for (j = 0; j < line->backsector->linecount; j++)
                                line->backsector->lines[j]->flags |= ML_TELEPORTTRIGGERED;
                        }

                        // don't move for a bit
                        thing->reactiontime = 18;

                        player->psprites[ps_weapon].sx = 0;
                        player->psprites[ps_weapon].sy = WEAPONTOP;

                        player->momx = player->momy = 0;
                    }

                    thing->angle = m->angle;

                    thing->momx = thing->momy = thing->momz = 0;

                    return true;
                }
            }
Beispiel #7
0
//
// TELEPORTATION
//
int
EV_Teleport
( line_t*	line,
  int		side,
  mobj_t*	thing )
{
    int		i;
    int		tag;
    mobj_t*	m;
    mobj_t*	fog;
    unsigned	an;
    thinker_t*	thinker;
    sector_t*	sector;
    int	oldx;
    int	oldy;
    int	oldz;

    // don't teleport missiles
    if (thing->flags & MF_MISSILE)
	return 0;		

    // Don't teleport if hit back of line,
    //  so you can get out of teleporter.
    if (side == 1)		
	return 0;	

    
    tag = line->tag;
    for (i = 0; i < numsectors; i++)
    {
	if (sectors[ i ].tag == tag )
	{
	    thinker = thinkercap.next;
	    for (thinker = thinkercap.next;
		 thinker != &thinkercap;
		 thinker = thinker->next)
	    {
		// not a mobj
		if (thinker->function.acp1 != (actionf_p1)P_MobjThinker)
		    continue;	

		m = (mobj_t *)thinker;
		
		// not a teleportman
		if (m->type != MT_TELEPORTMAN )
		    continue;		

		sector = m->subsector->sector;
		// wrong sector
		if (sector-sectors != i )
		    continue;	

		oldx = thing->x;
		oldy = thing->y;
		oldz = thing->z;
				
		if (!P_TeleportMove (thing, m->x, m->y))
		    return 0;
		
		thing->z = thing->floorz;  //fixme: not needed?
		if (thing->player)
		    thing->player->viewz = thing->z+thing->player->viewheight;
				
		// spawn teleport fog at source and destination
		fog = P_SpawnMobj (oldx, oldy, oldz, MT_TFOG);
		I_Sound::getInstance()->startSound (fog, sfx_telept);
		an = m->angle >> ANGLETOFINESHIFT;
		fog = P_SpawnMobj (m->x+20*finecosine[an], m->y+20*finesine[an]
				   , thing->z, MT_TFOG);

		// emit sound, where?
		I_Sound::getInstance()->startSound (fog, sfx_telept);
		
		// don't move for a bit
		if (thing->player)
		    thing->reactiontime = 18;	

		thing->angle = m->angle;
		thing->momx = thing->momy = thing->momz = 0;
		return 1;
	    }	
	}
    }
Beispiel #8
0
//
// TELEPORTATION
//
int
EV_Teleport(line_t * line, int side, mobj_t * thing) {
    int i;
    int tag;
    mobj_t *m;
    mobj_t *fog;
    unsigned an;
    thinker_t *thinker;
    sector_t *sector;
    fixed_t oldx;
    fixed_t oldy;
    fixed_t oldz;

    // don't teleport missiles
    if (thing->flags & MF_MISSILE)
        return 0;

    // Don't teleport if hit back of line,
    //  so you can get out of teleporter.
    if (side == 1)
        return 0;

    tag = line->tag;
    for (i = 0; i < numsectors; i++) {
        if (sectors[i].tag == tag) {
            thinker = thinkercap.next;
            for (thinker = thinkercap.next;
                    thinker != &thinkercap; thinker = thinker->next) {
                // not a mobj
                if (thinker->function.acp1 !=
                        (actionf_p1) P_MobjThinker)
                    continue;

                m = (mobj_t *) thinker;

                // not a teleportman
                if (m->type != MT_TELEPORTMAN)
                    continue;

                sector = m->subsector->sector;
                // wrong sector
                if (sector - sectors != i)
                    continue;

                oldx = thing->x;
                oldy = thing->y;
                oldz = thing->z;

                if (!P_TeleportMove(thing, m->x, m->y))
                    return 0;

                // fraggle: this was changed in final doom,
                // problem between normal doom2 1.9 and final doom
                //
                // Note that although chex.exe is based on Final Doom,
                // it does not have this quirk.

                if (gameversion < exe_final
                        || gameversion == exe_chex)
                    thing->z = thing->floorz;

                if (thing->player) {
                    thing->player->viewz =
                        thing->z +
                        thing->player->viewheight;
                }

                // spawn teleport fog at source and destination
                fog = P_SpawnMobj(oldx, oldy, oldz, MT_TFOG);
                S_StartSound(fog, sfx_telept);
                an = m->angle >> ANGLETOFINESHIFT;
                fog =
                    P_SpawnMobj(m->x + 20 * finecosine[an],
                                m->y + 20 * finesine[an]
                                , thing->z, MT_TFOG);

                // emit sound, where?
                S_StartSound(fog, sfx_telept);

                // don't move for a bit
                if (thing->player)
                    thing->reactiontime = 18;

                thing->angle = m->angle;
                thing->momx = thing->momy = thing->momz = 0;
                if (thing->player) {
                    thing->player->prevx = m->x;
                    thing->player->prevy = m->y;
                    thing->player->prevan = m->angle;
                }
                return 1;
            }
        }
    }
Beispiel #9
0
//
// TELEPORTATION
//
int
EV_Teleport
( line_t*	line,
  int		side,
  mobj_t*	thing )
{
    int		i;
    int		tag;
    mobj_t*	m;
    mobj_t*	fog;
    unsigned	an;
    thinker_t*	thinker;
    sector_t*	sector;
    fixed_t	oldx;
    fixed_t	oldy;
    fixed_t	oldz;

    // don't teleport missiles
    if (thing->flags & MF_MISSILE)
	return 0;		

    // Don't teleport if hit back of line,
    //  so you can get out of teleporter.
    if (side == 1)		
	return 0;	

    
    tag = line->tag;
    for (i = 0; i < numsectors; i++)
    {
	if (sectors[ i ].tag == tag )
	{
	    thinker = thinkercap.next;
	    for (thinker = thinkercap.next;
		 thinker != &thinkercap;
		 thinker = thinker->next)
	    {
		// not a mobj
		if (thinker->function.acp1 != (actionf_p1)P_MobjThinker)
		    continue;	

		m = (mobj_t *)thinker;
		
		// not a teleportman
		if (m->type != MT_TELEPORTMAN )
		    continue;		

		sector = m->subsector->sector;
		// wrong sector
		if (sector-sectors != i )
		    continue;	

		oldx = thing->x;
		oldy = thing->y;
		oldz = thing->z;
				
		if (!P_TeleportMove (thing, m->x, m->y))
		    return 0;

                // The first Final Doom executable does not set thing->z
                // when teleporting. This quirk is unique to this
                // particular version; the later version included in
                // some versions of the Id Anthology fixed this.

                if (gameversion != exe_final)
		    thing->z = thing->floorz;

		if (thing->player)
		    thing->player->viewz = thing->z+thing->player->viewheight;

		// spawn teleport fog at source and destination
		fog = P_SpawnMobj (oldx, oldy, oldz, MT_TFOG);
		S_StartSound (fog, sfx_telept);
		an = m->angle >> ANGLETOFINESHIFT;
		fog = P_SpawnMobj (m->x+20*finecosine[an], m->y+20*finesine[an]
				   , thing->z, MT_TFOG);

		// emit sound, where?
		S_StartSound (fog, sfx_telept);
		
		// don't move for a bit
		if (thing->player)
		    thing->reactiontime = 18;	

		thing->angle = m->angle;
		thing->momx = thing->momy = thing->momz = 0;
		return 1;
	    }	
	}
    }
Beispiel #10
0
bool P_Teleport (AActor *thing, DVector3 pos, DAngle angle, int flags)
{
	bool predicting = (thing->player && (thing->player->cheats & CF_PREDICTING));

	DVector3 old;
	double aboveFloor;
	player_t *player;
	sector_t *destsect;
	bool resetpitch = false;
	double floorheight, ceilingheight;
	double missilespeed = 0;

	old = thing->Pos();
	aboveFloor = thing->Z() - thing->floorz;
	destsect = P_PointInSector (pos);
	// killough 5/12/98: exclude voodoo dolls:
	player = thing->player;
	if (player && player->mo != thing)
		player = NULL;
	floorheight = destsect->floorplane.ZatPoint (pos);
	ceilingheight = destsect->ceilingplane.ZatPoint (pos);
	if (thing->flags & MF_MISSILE)
	{ // We don't measure z velocity, because it doesn't change.
		missilespeed = thing->VelXYToSpeed();
	}
	if (flags & TELF_KEEPHEIGHT)
	{
		pos.Z = floorheight + aboveFloor;
	}
	else if (pos.Z == ONFLOORZ)
	{
		if (player)
		{
			if (thing->flags & MF_NOGRAVITY && aboveFloor)
			{
				pos.Z = floorheight + aboveFloor;
				if (pos.Z + thing->Height > ceilingheight)
				{
					pos.Z = ceilingheight - thing->Height;
				}
			}
			else
			{
				pos.Z = floorheight;
				if (!(flags & TELF_KEEPORIENTATION))
				{
					resetpitch = false;
				}
			}
		}
		else if (thing->flags & MF_MISSILE)
		{
			pos.Z = floorheight + aboveFloor;
			if (pos.Z + thing->Height > ceilingheight)
			{
				pos.Z = ceilingheight - thing->Height;
			}
		}
		else
		{
			pos.Z = floorheight;
		}
	}
	if (!P_TeleportMove (thing, pos, false))
	{
		return false;
	}
	if (player)
	{
		player->viewz = thing->Z() + player->viewheight;
		if (resetpitch)
		{
			player->mo->Angles.Pitch = 0.;
		}
	}
	if (!(flags & TELF_KEEPORIENTATION))
	{
		thing->Angles.Yaw = angle;
	}
	else
	{
		angle = thing->Angles.Yaw;
	}
	// Spawn teleport fog at source and destination
	if ((flags & TELF_SOURCEFOG) && !predicting)
	{
		P_SpawnTeleportFog(thing, old, true, true); //Passes the actor through which then pulls the TeleFog metadata types based on properties.
	}
	if (flags & TELF_DESTFOG)
	{
		if (!predicting)
		{
			DVector2 vector = angle.ToVector(20);
			DVector2 fogpos = P_GetOffsetPosition(pos.X, pos.Y, vector.X, vector.Y);
			P_SpawnTeleportFog(thing, DVector3(fogpos, thing->Z()), false, true);

		}
		if (thing->player)
		{
			// [RH] Zoom player's field of vision
			// [BC] && bHaltVelocity.
			if (telezoom && thing->player->mo == thing && !(flags & TELF_KEEPVELOCITY))
				thing->player->FOV = MIN (175.f, thing->player->DesiredFOV + 45.f);
		}
	}
	// [BC] && bHaltVelocity.
	if (thing->player && ((flags & TELF_DESTFOG) || !(flags & TELF_KEEPORIENTATION)) && !(flags & TELF_KEEPVELOCITY))
	{
		// Freeze player for about .5 sec
		if (thing->Inventory == NULL || !thing->Inventory->GetNoTeleportFreeze())
			thing->reactiontime = 18;
	}
	if (thing->flags & MF_MISSILE)
	{
		thing->VelFromAngle(missilespeed);
	}
	// [BC] && bHaltVelocity.
	else if (!(flags & TELF_KEEPORIENTATION) && !(flags & TELF_KEEPVELOCITY))
	{ // no fog doesn't alter the player's momentum
		thing->Vel.Zero();
		// killough 10/98: kill all bobbing velocity too
		if (player)	player->Vel.Zero();
	}
	return true;
}
Beispiel #11
0
static void SpawnFly(AActor *self, const PClass *spawntype, FSoundID sound)
{
	AActor *newmobj;
	AActor *fog;
	AActor *eye = self->master; // The eye is the spawnshot's master, not the target!
	AActor *targ = self->target; // Unlike other projectiles, the target is the intended destination.
	int r;
		
	// [GZ] Should be more viable than a countdown...
	if (self->special2 != 0)
	{
		if (self->special2 > level.maptime)
			return;		// still flying
	}
	else
	{
		if (self->reactiontime == 0 || --self->reactiontime != 0)
			return;		// still flying
	}
	
	if (spawntype != NULL)
	{
		fog = Spawn (spawntype, targ->x, targ->y, targ->z, ALLOW_REPLACE);
		if (fog != NULL) S_Sound (fog, CHAN_BODY, sound, 1, ATTN_NORM);
	}

	FName SpawnName;

	FDropItem *di;   // di will be our drop item list iterator
	FDropItem *drop; // while drop stays as the reference point.
	int n = 0;

	// First see if this cube has its own actor list
	drop = self->GetDropItems();

	// If not, then default back to its master's list
	if (drop == NULL && eye != NULL)
		drop = eye->GetDropItems();

	if (drop != NULL)
	{
		for (di = drop; di != NULL; di = di->Next)
		{
			if (di->Name != NAME_None)
			{
				if (di->amount < 0)
				{
					di->amount = 1; // default value is -1, we need a positive value.
				}
				n += di->amount; // this is how we can weight the list.
			}
		}
		di = drop;
		n = pr_spawnfly(n);
		while (n >= 0)
		{
			if (di->Name != NAME_None)
			{
				n -= di->amount; // logically, none of the -1 values have survived by now.
			}
			if ((di->Next != NULL) && (n >= 0))
			{
				di = di->Next;
			}
			else
			{
				n = -1;
			}
		}
		SpawnName = di->Name;
	}
	if (SpawnName == NAME_None)
	{
		// Randomly select monster to spawn.
		r = pr_spawnfly ();

		// Probability distribution (kind of :),
		// decreasing likelihood.
			 if (r < 50)  SpawnName = "DoomImp";
		else if (r < 90)  SpawnName = "Demon";
		else if (r < 120) SpawnName = "Spectre";
		else if (r < 130) SpawnName = "PainElemental";
		else if (r < 160) SpawnName = "Cacodemon";
		else if (r < 162) SpawnName = "Archvile";
		else if (r < 172) SpawnName = "Revenant";
		else if (r < 192) SpawnName = "Arachnotron";
		else if (r < 222) SpawnName = "Fatso";
		else if (r < 246) SpawnName = "HellKnight";
		else			  SpawnName = "BaronOfHell";
	}
	spawntype = PClass::FindClass(SpawnName);
	if (spawntype != NULL)
	{
		newmobj = Spawn (spawntype, targ->x, targ->y, targ->z, ALLOW_REPLACE);
		if (newmobj != NULL)
		{
			// Make the new monster hate what the boss eye hates
			if (eye != NULL)
			{
				newmobj->CopyFriendliness (eye, false);
			}
			// Make it act as if it was around when the player first made noise
			// (if the player has made noise).
			newmobj->LastHeard = newmobj->Sector->SoundTarget;

			if (newmobj->SeeState != NULL && P_LookForPlayers (newmobj, true, NULL))
			{
				newmobj->SetState (newmobj->SeeState);
			}
			if (!(newmobj->ObjectFlags & OF_EuthanizeMe))
			{
				// telefrag anything in this spot
				P_TeleportMove (newmobj, newmobj->x, newmobj->y, newmobj->z, true);
			}
			newmobj->flags4 |= MF4_BOSSSPAWNED;
		}
	}

	// remove self (i.e., cube).
	self->Destroy ();
}
Beispiel #12
0
boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, angle_t angle,
				   boolean useFog)
{
	fixed_t oldx;
	fixed_t oldy;
	fixed_t oldz;
	fixed_t aboveFloor;
	fixed_t fogDelta;
	player_t *player;
	unsigned an;
	mobj_t *fog;

	oldx = thing->x;
	oldy = thing->y;
	oldz = thing->z;
	aboveFloor = thing->z - thing->floorz;
	if(!P_TeleportMove(thing, x, y))
	{
		return false;
	}
	if(thing->player)
	{
		player = thing->player;
		player->plr->flags |= DDPF_FIXANGLES | DDPF_FIXPOS | DDPF_FIXMOM;
		if(player->powers[pw_flight] && aboveFloor)
		{
			thing->z = thing->floorz + aboveFloor;
			if(thing->z + thing->height > thing->ceilingz)
			{
				thing->z = thing->ceilingz - thing->height;
			}
			player->plr->viewz = thing->z + player->plr->viewheight;
		}
		else
		{
			thing->z = thing->floorz;
			player->plr->viewz = thing->z + player->plr->viewheight;
			if(useFog)
			{
				player->plr->lookdir = 0;
			}
		}
	}
	else if(thing->flags & MF_MISSILE)
	{
		thing->z = thing->floorz + aboveFloor;
		if(thing->z + thing->height > thing->ceilingz)
		{
			thing->z = thing->ceilingz - thing->height;
		}
	}
	else
	{
		thing->z = thing->floorz;
	}
	// Spawn teleport fog at source and destination
	if(useFog)
	{
		fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT;
		fog = P_SpawnMobj(oldx, oldy, oldz + fogDelta, MT_TFOG);
		S_StartSound(SFX_TELEPORT, fog);
		an = angle >> ANGLETOFINESHIFT;
		fog =
			P_SpawnMobj(x + 20 * finecosine[an], y + 20 * finesine[an],
						thing->z + fogDelta, MT_TFOG);
		S_StartSound(SFX_TELEPORT, fog);
		if(thing->player && !thing->player->powers[pw_speed])
		{						// Freeze player for about .5 sec
			thing->reactiontime = 18;
		}
		thing->angle = angle;
	}
	if(thing->flags2 & MF2_FLOORCLIP)
	{
		if(thing->z == thing->subsector->sector->floorheight &&
		   P_GetThingFloorType(thing) > FLOOR_SOLID)
		{
			thing->floorclip = 10 * FRACUNIT;
		}
		else
		{
			thing->floorclip = 0;
		}
	}
	if(thing->flags & MF_MISSILE)
	{
		angle >>= ANGLETOFINESHIFT;
		thing->momx = FixedMul(thing->info->speed, finecosine[angle]);
		thing->momy = FixedMul(thing->info->speed, finesine[angle]);
	}