Beispiel #1
0
void G_FinishTravel ()
{
	TThinkerIterator<APlayerPawn> it (STAT_TRAVELLING);
	APlayerPawn *pawn, *pawndup, *oldpawn, *next;
	AInventory *inv;
	FPlayerStart *start;
	int pnum;

	next = it.Next ();
	while ( (pawn = next) != NULL)
	{
		next = it.Next ();
		pnum = int(pawn->player - players);
		pawn->ChangeStatNum (STAT_PLAYER);
		pawndup = pawn->player->mo;
		start = NULL;
		assert (pawn != pawndup);
		if (pawndup == NULL)
		{ // Oh no! there was no start for this player!
			start = G_PickPlayerStart(pnum, PPS_FORCERANDOM); 
			if (start != NULL) pawndup = P_SpawnPlayer(start, pnum, (level.flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0);
			if (pawndup == NULL)
			{
				pawn->flags |= MF_NOSECTOR | MF_NOBLOCKMAP;
				pawn->Destroy();
				continue;
			}
		}

		if (start == NULL)
		{
			start = G_PickPlayerStart(pnum, 0);
			if (start == NULL)
			{
				Printf(TEXTCOLOR_RED "No player %d start to travel to!\n", pnum + 1);
				// Move to the coordinates this player had when they left the level.
				pawn->SetXYZ(pawndup->Pos());
			}
		}
		oldpawn = pawndup;

		// The player being spawned here is a short lived dummy and
		// must not start any ENTER script or big problems will happen.
		pawndup = P_SpawnPlayer(start, pnum, SPF_TEMPPLAYER);
		if (pawndup != NULL)
		{
			if (!(changeflags & CHANGELEVEL_KEEPFACING))
			{
				pawn->Angles = pawndup->Angles;
			}
			pawn->SetXYZ(pawndup->Pos());
			pawn->Vel = pawndup->Vel;
			pawn->Sector = pawndup->Sector;
			pawn->floorz = pawndup->floorz;
			pawn->ceilingz = pawndup->ceilingz;
			pawn->dropoffz = pawndup->dropoffz;
			pawn->floorsector = pawndup->floorsector;
			pawn->floorpic = pawndup->floorpic;
			pawn->floorterrain = pawndup->floorterrain;
			pawn->ceilingsector = pawndup->ceilingsector;
			pawn->ceilingpic = pawndup->ceilingpic;
			pawn->Floorclip = pawndup->Floorclip;
			pawn->waterlevel = pawndup->waterlevel;
		}
		else
		{
			P_FindFloorCeiling(pawn);
		}
		pawn->target = NULL;
		pawn->lastenemy = NULL;
		pawn->player->mo = pawn;
		pawn->player->camera = pawn;
		pawn->player->viewheight = pawn->ViewHeight;
		pawn->flags2 &= ~MF2_BLASTED;
		DObject::StaticPointerSubstitution (oldpawn, pawn);
		oldpawn->Destroy();
		if (pawndup != NULL)
		{
			pawndup->Destroy();
		}
		pawn->LinkToWorld ();
		pawn->ClearInterpolation();
		pawn->AddToHash ();
		pawn->SetState(pawn->SpawnState);
		pawn->player->SendPitchLimits();

		for (inv = pawn->Inventory; inv != NULL; inv = inv->Inventory)
		{
			inv->ChangeStatNum (STAT_INVENTORY);
			inv->LinkToWorld ();
			inv->Travelled ();
		}
		if (ib_compatflags & BCOMPATF_RESETPLAYERSPEED)
		{
			pawn->Speed = pawn->GetDefault()->Speed;
		}
		if (level.FromSnapshot)
		{
			FBehavior::StaticStartTypedScripts (SCRIPT_Return, pawn, true);
		}
	}

	bglobal.FinishTravel ();
}
Beispiel #2
0
void G_FinishTravel ()
{
	TThinkerIterator<APlayerPawn> it (STAT_TRAVELLING);
	APlayerPawn *pawn, *pawndup, *oldpawn, *next;
	AInventory *inv;

	next = it.Next ();
	while ( (pawn = next) != NULL)
	{
		next = it.Next ();
		pawn->ChangeStatNum (STAT_PLAYER);
		pawndup = pawn->player->mo;
		assert (pawn != pawndup);
		if (pawndup == NULL)
		{ // Oh no! there was no start for this player!
			pawn->flags |= MF_NOSECTOR|MF_NOBLOCKMAP;
			pawn->Destroy ();
		}
		else
		{
			oldpawn = pawndup;

			// The player being spawned here is a short lived dummy and
			// must not start any ENTER script or big problems will happen.
			pawndup = P_SpawnPlayer (&playerstarts[pawn->player - players], int(pawn->player - players), SPF_TEMPPLAYER);
			if (!(changeflags & CHANGELEVEL_KEEPFACING))
			{
				pawn->angle = pawndup->angle;
				pawn->pitch = pawndup->pitch;
			}
			pawn->x = pawndup->x;
			pawn->y = pawndup->y;
			pawn->z = pawndup->z;
			pawn->velx = pawndup->velx;
			pawn->vely = pawndup->vely;
			pawn->velz = pawndup->velz;
			pawn->Sector = pawndup->Sector;
			pawn->floorz = pawndup->floorz;
			pawn->ceilingz = pawndup->ceilingz;
			pawn->dropoffz = pawndup->dropoffz;
			pawn->floorsector = pawndup->floorsector;
			pawn->floorpic = pawndup->floorpic;
			pawn->ceilingsector = pawndup->ceilingsector;
			pawn->ceilingpic = pawndup->ceilingpic;
			pawn->floorclip = pawndup->floorclip;
			pawn->waterlevel = pawndup->waterlevel;
			pawn->target = NULL;
			pawn->lastenemy = NULL;
			pawn->player->mo = pawn;
			pawn->player->camera = pawn;
			DObject::StaticPointerSubstitution (oldpawn, pawn);
			oldpawn->Destroy();
			pawndup->Destroy ();
			pawn->LinkToWorld ();
			pawn->AddToHash ();
			pawn->SetState(pawn->SpawnState);
			pawn->player->SendPitchLimits();

			for (inv = pawn->Inventory; inv != NULL; inv = inv->Inventory)
			{
				inv->ChangeStatNum (STAT_INVENTORY);
				inv->LinkToWorld ();
				inv->Travelled ();
			}
			if (ib_compatflags & BCOMPATF_RESETPLAYERSPEED)
			{
				pawn->Speed = pawn->GetDefault()->Speed;
			}
			if (level.FromSnapshot)
			{
				FBehavior::StaticStartTypedScripts (SCRIPT_Return, pawn, true);
			}
		}
	}
}
Beispiel #3
0
void G_FinishTravel ()
{
	TThinkerIterator<APlayerPawn> it (STAT_TRAVELLING);
	APlayerPawn *pawn, *pawndup, *oldpawn, *next;
	AInventory *inv;
	FPlayerStart *start;
	int pnum;

	next = it.Next ();
	while ( (pawn = next) != NULL)
	{
		next = it.Next ();
		pnum = int(pawn->player - players);
		pawn->ChangeStatNum (STAT_PLAYER);
		pawndup = pawn->player->mo;
		assert (pawn != pawndup);

		start = G_PickPlayerStart(pnum, 0);
		if (start == NULL)
		{
			if (pawndup != nullptr)
			{
				Printf(TEXTCOLOR_RED "No player %d start to travel to!\n", pnum + 1);
				// Move to the coordinates this player had when they left the level.
				pawn->SetXYZ(pawndup->Pos());
			}
			else
			{
				// Could not find a start for this player at all. This really should never happen but if it does, let's better abort.
				DThinker::DestroyThinkersInList(STAT_TRAVELLING);
				I_Error ("No player %d start to travel to!\n", pnum + 1);
			}
		}
		oldpawn = pawndup;

		// The player being spawned here is a short lived dummy and
		// must not start any ENTER script or big problems will happen.
		pawndup = P_SpawnPlayer(start, pnum, SPF_TEMPPLAYER);
		if (pawndup != NULL)
		{
			if (!(changeflags & CHANGELEVEL_KEEPFACING))
			{
				pawn->Angles = pawndup->Angles;
			}
			pawn->SetXYZ(pawndup->Pos());
			pawn->Vel = pawndup->Vel;
			pawn->Sector = pawndup->Sector;
			pawn->floorz = pawndup->floorz;
			pawn->ceilingz = pawndup->ceilingz;
			pawn->dropoffz = pawndup->dropoffz;
			pawn->floorsector = pawndup->floorsector;
			pawn->floorpic = pawndup->floorpic;
			pawn->floorterrain = pawndup->floorterrain;
			pawn->ceilingsector = pawndup->ceilingsector;
			pawn->ceilingpic = pawndup->ceilingpic;
			pawn->Floorclip = pawndup->Floorclip;
			pawn->waterlevel = pawndup->waterlevel;
		}
		else
		{
			P_FindFloorCeiling(pawn);
		}
		pawn->target = NULL;
		pawn->lastenemy = NULL;
		pawn->player->mo = pawn;
		pawn->player->camera = pawn;
		pawn->player->viewheight = pawn->ViewHeight;
		pawn->flags2 &= ~MF2_BLASTED;
		if (oldpawn != nullptr)
		{
			DObject::StaticPointerSubstitution (oldpawn, pawn);
			oldpawn->Destroy();
		}
		if (pawndup != NULL)
		{
			pawndup->Destroy();
		}
		pawn->LinkToWorld (nullptr);
		pawn->ClearInterpolation();
		pawn->AddToHash ();
		pawn->SetState(pawn->SpawnState);
		pawn->player->SendPitchLimits();

		for (inv = pawn->Inventory; inv != NULL; inv = inv->Inventory)
		{
			inv->ChangeStatNum (STAT_INVENTORY);
			inv->LinkToWorld (nullptr);
			inv->Travelled ();
		}
		if (ib_compatflags & BCOMPATF_RESETPLAYERSPEED)
		{
			pawn->Speed = pawn->GetDefault()->Speed;
		}
		if (level.FromSnapshot)
		{
			FBehavior::StaticStartTypedScripts (SCRIPT_Return, pawn, true);

			// [Nash] run REOPEN scripts upon map re-entry
			FBehavior::StaticStartTypedScripts(SCRIPT_Reopen, NULL, false);
		}
	}

	bglobal.FinishTravel ();

	// make sure that, after travelling has completed, no travelling thinkers are left.
	// Since this list is excluded from regular thinker cleaning, anything that may survive through here
	// will endlessly multiply and severely break the following savegames or just simply crash on broken pointers.
	DThinker::DestroyThinkersInList(STAT_TRAVELLING);
}