Пример #1
0
inline void GLPortal::ClearClipper()
{
	DAngle angleOffset = deltaangle(savedAngle, ViewAngle);

	clipper.Clear();

	static int call=0;

	// Set the clipper to the minimal visible area
	clipper.SafeAddClipRange(0,0xffffffff);
	for (unsigned int i = 0; i < lines.Size(); i++)
	{
		DAngle startAngle = (DVector2(lines[i].glseg.x2, lines[i].glseg.y2) - savedViewPos).Angle() + angleOffset;
		DAngle endAngle = (DVector2(lines[i].glseg.x1, lines[i].glseg.y1) - savedViewPos).Angle() + angleOffset;

		if (deltaangle(endAngle, startAngle) < 0)
		{
			clipper.SafeRemoveClipRangeRealAngles(startAngle.BAMs(), endAngle.BAMs());
		}
	}

	// and finally clip it to the visible area
	angle_t a1 = GLRenderer->FrustumAngle();
	if (a1 < ANGLE_180) clipper.SafeAddClipRangeRealAngles(ViewAngle.BAMs() + a1, ViewAngle.BAMs() - a1);

	// lock the parts that have just been clipped out.
	clipper.SetSilhouette();
}
Пример #2
0
void HWScenePortalBase::ClearClipper(HWDrawInfo *di, Clipper *clipper)
{
	auto outer_di = di->outer;
	DAngle angleOffset = deltaangle(outer_di->Viewpoint.Angles.Yaw, di->Viewpoint.Angles.Yaw);

	clipper->Clear();

	// Set the clipper to the minimal visible area
	clipper->SafeAddClipRange(0, 0xffffffff);
	for (unsigned int i = 0; i < lines.Size(); i++)
	{
		DAngle startAngle = (DVector2(lines[i].glseg.x2, lines[i].glseg.y2) - outer_di->Viewpoint.Pos).Angle() + angleOffset;
		DAngle endAngle = (DVector2(lines[i].glseg.x1, lines[i].glseg.y1) - outer_di->Viewpoint.Pos).Angle() + angleOffset;

		if (deltaangle(endAngle, startAngle) < 0)
		{
			clipper->SafeRemoveClipRangeRealAngles(startAngle.BAMs(), endAngle.BAMs());
		}
	}

	// and finally clip it to the visible area
	angle_t a1 = di->FrustumAngle();
	if (a1 < ANGLE_180) clipper->SafeAddClipRangeRealAngles(di->Viewpoint.Angles.Yaw.BAMs() + a1, di->Viewpoint.Angles.Yaw.BAMs() - a1);

	// lock the parts that have just been clipped out.
	clipper->SetSilhouette();
}
Пример #3
0
DEFINE_ACTION_FUNCTION(AActor, A_Tracer2)
{
	PARAM_ACTION_PROLOGUE;

	AActor *dest;
	double dist;
	double slope;

	dest = self->tracer;

	if (!dest || dest->health <= 0 || self->Speed == 0 || !self->CanSeek(dest))
		return 0;

	DAngle exact = self->AngleTo(dest);
	DAngle diff = deltaangle(self->Angles.Yaw, exact);

	if (diff < 0)
	{
		self->Angles.Yaw -= TRACEANGLE;
		if (deltaangle(self->Angles.Yaw, exact) > 0)
			self->Angles.Yaw = exact;
	}
	else if (diff > 0)
	{
		self->Angles.Yaw += TRACEANGLE;
		if (deltaangle(self->Angles.Yaw, exact) < 0.)
			self->Angles.Yaw = exact;
	}

	self->VelFromAngle();

	if (!(self->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER)))
	{
		// change slope
		dist = self->DistanceBySpeed (dest, self->Speed);
		if (dest->Height >= 56)
		{
			slope = (dest->Z()+40 - self->Z()) / dist;
		}
		else
		{
			slope = (dest->Z() + self->Height*(2./3) - self->Z()) / dist;
		}
		if (slope < self->Vel.Z)
		{
			self->Vel.Z -= 1 / 8.;
		}
		else
		{
			self->Vel.Z += 1 / 8.;
		}
	}
	return 0;
}
Пример #4
0
void PolyDrawSectorPortal::SaveGlobals()
{
	auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
	const auto &viewwindow = PolyRenderer::Instance()->Viewwindow;

	SavedViewpoint = viewpoint;
	SavedInvisibility = viewpoint.camera ? (viewpoint.camera->renderflags & RF_INVISIBLE) == RF_INVISIBLE : false;

	if (Portal->mType == PORTS_SKYVIEWPOINT)
	{
		// Don't let gun flashes brighten the sky box
		AActor *sky = Portal->mSkybox;
		viewpoint.extralight = 0;
		//PolyRenderer::Instance()->Light.SetVisibility(sky->args[0] * 0.25f);
		viewpoint.Pos = sky->InterpolatedPosition(viewpoint.TicFrac);
		viewpoint.Angles.Yaw = SavedViewpoint.Angles.Yaw + (sky->PrevAngles.Yaw + deltaangle(sky->PrevAngles.Yaw, sky->Angles.Yaw) * viewpoint.TicFrac);
	}
	else //if (Portal->mType == PORTS_STACKEDSECTORTHING || Portal->mType == PORTS_PORTAL || Portal->mType == PORTS_LINKEDPORTAL)
	{
		//extralight = pl->extralight;
		//SetVisibility(pl->visibility);
		viewpoint.Pos.X += Portal->mDisplacement.X;
		viewpoint.Pos.Y += Portal->mDisplacement.Y;
	}

	viewpoint.camera = nullptr;
	viewpoint.sector = Portal->mDestination;
	viewpoint.SetViewAngle(viewwindow);

	Portal->mFlags |= PORTSF_INSKYBOX;
	if (Portal->mPartner > 0) PolyRenderer::Instance()->Level->sectorPortals[Portal->mPartner].mFlags |= PORTSF_INSKYBOX;
}
Пример #5
0
void GLSkyboxPortal::DrawContents()
{
	int old_pm = PlaneMirrorMode;
	int saved_extralight = extralight;

	if (skyboxrecursion >= 3)
	{
		ClearScreen();
		return;
	}

	skyboxrecursion++;
	AActor *origin = portal->mSkybox;
	portal->mFlags |= PORTSF_INSKYBOX;
	extralight = 0;

	PlaneMirrorMode = 0;

	bool oldclamp = gl_RenderState.SetDepthClamp(false);
	ViewPos = origin->InterpolatedPosition(r_TicFracF);
	ViewAngle += (origin->PrevAngles.Yaw + deltaangle(origin->PrevAngles.Yaw, origin->Angles.Yaw) * r_TicFracF);

	// Don't let the viewpoint be too close to a floor or ceiling
	double floorh = origin->Sector->floorplane.ZatPoint(origin->Pos());
	double ceilh = origin->Sector->ceilingplane.ZatPoint(origin->Pos());
	if (ViewPos.Z < floorh + 4) ViewPos.Z = floorh + 4;
	if (ViewPos.Z > ceilh - 4) ViewPos.Z = ceilh - 4;

	GLRenderer->mViewActor = origin;

	inskybox = true;
	GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1));
	GLRenderer->SetViewArea();
	ClearClipper();

	int mapsection = R_PointInSubsector(ViewPos)->mapsection;

	SaveMapSection();
	currentmapsection[mapsection >> 3] |= 1 << (mapsection & 7);

	GLRenderer->DrawScene(DM_PORTAL);
	portal->mFlags &= ~PORTSF_INSKYBOX;
	inskybox = false;
	gl_RenderState.SetDepthClamp(oldclamp);
	skyboxrecursion--;

	PlaneMirrorMode = old_pm;
	extralight = saved_extralight;

	RestoreMapSection();
}
Пример #6
0
bool HWSkyboxPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
{
	auto state = mState;
	old_pm = state->PlaneMirrorMode;

	if (mState->skyboxrecursion >= 3)
	{
		return false;
	}
	auto &vp = di->Viewpoint;

	state->skyboxrecursion++;
	state->PlaneMirrorMode = 0;
	state->inskybox = true;

	AActor *origin = portal->mSkybox;
	portal->mFlags |= PORTSF_INSKYBOX;
	vp.extralight = 0;

	oldclamp = rstate.SetDepthClamp(false);
	vp.Pos = origin->InterpolatedPosition(vp.TicFrac);
	vp.ActorPos = origin->Pos();
	vp.Angles.Yaw += (origin->PrevAngles.Yaw + deltaangle(origin->PrevAngles.Yaw, origin->Angles.Yaw) * vp.TicFrac);

	// Don't let the viewpoint be too close to a floor or ceiling
	double floorh = origin->Sector->floorplane.ZatPoint(origin->Pos());
	double ceilh = origin->Sector->ceilingplane.ZatPoint(origin->Pos());
	if (vp.Pos.Z < floorh + 4) vp.Pos.Z = floorh + 4;
	if (vp.Pos.Z > ceilh - 4) vp.Pos.Z = ceilh - 4;

	vp.ViewActor = origin;

	di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
	di->SetViewArea();
	ClearClipper(di, clipper);
	di->UpdateCurrentMapSection();
	return true;
}
Пример #7
0
void AdjustPlayerAngle (AActor *pmo, FTranslatedLineTarget *t)
{
	// normally this will adjust relative to the actual direction to the target,
	// but with arbitrary portals that cannot be calculated so using the actual
	// attack angle is the only option.
	DAngle atkangle = t->unlinked ? t->angleFromSource : pmo->AngleTo(t->linetarget);
	DAngle difference = deltaangle(pmo->Angles.Yaw, atkangle);
	if (fabs(difference) > MAX_ANGLE_ADJUST)
	{
		if (difference > 0)
		{
			pmo->Angles.Yaw += MAX_ANGLE_ADJUST;
		}
		else
		{
			pmo->Angles.Yaw -= MAX_ANGLE_ADJUST;
		}
	}
	else
	{
		pmo->Angles.Yaw = t->angleFromSource;
	}
}
Пример #8
0
	// Draws any recorded sky boxes and then frees them.
	//
	// The process:
	//   1. Move the camera to coincide with the SkyViewpoint.
	//   2. Clear out the old planes. (They have already been drawn.)
	//   3. Clear a window out of the ClipSegs just large enough for the plane.
	//   4. Pretend the existing vissprites and drawsegs aren't there.
	//   5. Create a drawseg at 0 distance to clip sprites to the visplane. It
	//      doesn't need to be associated with a line in the map, since there
	//      will never be any sprites in front of it.
	//   6. Render the BSP, then planes, then masked stuff.
	//   7. Restore the previous vissprites and drawsegs.
	//   8. Repeat for any other sky boxes.
	//   9. Put the camera back where it was to begin with.
	//
	void RenderPortal::RenderPlanePortals()
	{
		numskyboxes = 0;

		VisiblePlaneList *planes = Thread->PlaneList.get();
		DrawSegmentList *drawseglist = Thread->DrawSegments.get();

		if (!planes->HasPortalPlanes())
			return;

		Thread->Clip3D->EnterSkybox();
		CurrentPortalInSkybox = true;

		int savedextralight = Thread->Viewport->viewpoint.extralight;
		DVector3 savedpos = Thread->Viewport->viewpoint.Pos;
		DRotator savedangles = Thread->Viewport->viewpoint.Angles;
		double savedvisibility = Thread->Light->GetVisibility();
		AActor *savedcamera = Thread->Viewport->viewpoint.camera;
		sector_t *savedsector = Thread->Viewport->viewpoint.sector;

		for (VisiblePlane *pl = planes->PopFirstPortalPlane(); pl != nullptr; pl = planes->PopFirstPortalPlane())
		{
			if (pl->right < pl->left || !r_skyboxes || numskyboxes == MAX_SKYBOX_PLANES || pl->portal == nullptr)
			{
				pl->Render(Thread, OPAQUE, false, false);
				continue;
			}

			numskyboxes++;

			FSectorPortal *port = pl->portal;
			switch (port->mType)
			{
			case PORTS_SKYVIEWPOINT:
			{
				// Don't let gun flashes brighten the sky box
				AActor *sky = port->mSkybox;
				Thread->Viewport->viewpoint.extralight = 0;
				Thread->Light->SetVisibility(Thread->Viewport.get(), sky->args[0] * 0.25f);

				Thread->Viewport->viewpoint.Pos = sky->InterpolatedPosition(Thread->Viewport->viewpoint.TicFrac);
				Thread->Viewport->viewpoint.Angles.Yaw = savedangles.Yaw + (sky->PrevAngles.Yaw + deltaangle(sky->PrevAngles.Yaw, sky->Angles.Yaw) * Thread->Viewport->viewpoint.TicFrac);

				CopyStackedViewParameters();
				break;
			}

			case PORTS_STACKEDSECTORTHING:
			case PORTS_PORTAL:
			case PORTS_LINKEDPORTAL:
				Thread->Viewport->viewpoint.extralight = pl->extralight;
				Thread->Light->SetVisibility(Thread->Viewport.get(), pl->visibility);
				Thread->Viewport->viewpoint.Pos.X = pl->viewpos.X + port->mDisplacement.X;
				Thread->Viewport->viewpoint.Pos.Y = pl->viewpos.Y + port->mDisplacement.Y;
				Thread->Viewport->viewpoint.Pos.Z = pl->viewpos.Z;
				Thread->Viewport->viewpoint.Angles.Yaw = pl->viewangle;
				break;

			case PORTS_HORIZON:
			case PORTS_PLANE:
				// not implemented yet

			default:
				pl->Render(Thread, OPAQUE, false, false);
				numskyboxes--;
				continue;
			}

			SetInSkyBox(port);
			if (port->mPartner > 0) SetInSkyBox(&level.sectorPortals[port->mPartner]);
			Thread->Viewport->viewpoint.camera = nullptr;
			Thread->Viewport->viewpoint.sector = port->mDestination;
			assert(Thread->Viewport->viewpoint.sector != nullptr);
			R_SetViewAngle(Thread->Viewport->viewpoint, Thread->Viewport->viewwindow);
			Thread->OpaquePass->ClearSeenSprites();
			Thread->Clip3D->ClearFakeFloors();

			planes->ClearKeepFakePlanes();
			Thread->ClipSegments->Clear(pl->left, pl->right);
			WindowLeft = pl->left;
			WindowRight = pl->right;

			auto ceilingclip = Thread->OpaquePass->ceilingclip;
			auto floorclip = Thread->OpaquePass->floorclip;
			for (int i = pl->left; i < pl->right; i++)
			{
				if (pl->top[i] == 0x7fff)
				{
					ceilingclip[i] = viewheight;
					floorclip[i] = -1;
				}
				else
				{
					ceilingclip[i] = pl->top[i];
					floorclip[i] = pl->bottom[i];
				}
			}

			drawseglist->PushPortal();
			Thread->SpriteList->PushPortal();
			viewposStack.Push(Thread->Viewport->viewpoint.Pos);
			visplaneStack.Push(pl);

			// Create a drawseg to clip sprites to the sky plane
			DrawSegment *draw_segment = Thread->FrameMemory->NewObject<DrawSegment>();
			draw_segment->CurrentPortalUniq = CurrentPortalUniq;
			draw_segment->siz1 = INT_MAX;
			draw_segment->siz2 = INT_MAX;
			draw_segment->sz1 = 0;
			draw_segment->sz2 = 0;
			draw_segment->x1 = pl->left;
			draw_segment->x2 = pl->right;
			draw_segment->silhouette = SIL_BOTH;
			draw_segment->sprbottomclip = Thread->FrameMemory->AllocMemory<short>(pl->right - pl->left);
			draw_segment->sprtopclip = Thread->FrameMemory->AllocMemory<short>(pl->right - pl->left);
			draw_segment->maskedtexturecol = nullptr;
			draw_segment->swall = nullptr;
			draw_segment->bFogBoundary = false;
			draw_segment->curline = nullptr;
			draw_segment->foggy = false;
			memcpy(draw_segment->sprbottomclip, floorclip + pl->left, (pl->right - pl->left) * sizeof(short));
			memcpy(draw_segment->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left) * sizeof(short));
			drawseglist->Push(draw_segment);

			Thread->OpaquePass->RenderScene();
			Thread->Clip3D->ResetClip(); // reset clips (floor/ceiling)
			planes->Render();

			ClearInSkyBox(port);
			if (port->mPartner > 0) SetInSkyBox(&level.sectorPortals[port->mPartner]);
		}

		// Draw all the masked textures in a second pass, in the reverse order they
		// were added. This must be done separately from the previous step for the
		// sake of nested skyboxes.
		while (viewposStack.Size() > 0)
		{
			// Masked textures and planes need the view coordinates restored for proper positioning.
			viewposStack.Pop(Thread->Viewport->viewpoint.Pos);
			
			Thread->TranslucentPass->Render();

			VisiblePlane *pl = nullptr;	// quiet, GCC!
			visplaneStack.Pop(pl);
			if (pl->Alpha > 0 && pl->picnum != skyflatnum)
			{
				pl->Render(Thread, pl->Alpha, pl->Additive, true);
			}
			
			Thread->SpriteList->PopPortal();
			drawseglist->PopPortal();
		}

		Thread->Viewport->viewpoint.camera = savedcamera;
		Thread->Viewport->viewpoint.sector = savedsector;
		Thread->Viewport->viewpoint.Pos = savedpos;
		Thread->Light->SetVisibility(Thread->Viewport.get(), savedvisibility);
		Thread->Viewport->viewpoint.extralight = savedextralight;
		Thread->Viewport->viewpoint.Angles = savedangles;
		R_SetViewAngle(Thread->Viewport->viewpoint, Thread->Viewport->viewwindow);

		CurrentPortalInSkybox = false;
		Thread->Clip3D->LeaveSkybox();

		if (Thread->Clip3D->fakeActive) return;

		planes->ClearPortalPlanes();
	}
Пример #9
0
void R_DrawPortals ()
{
	static TArray<size_t> interestingStack;
	static TArray<ptrdiff_t> drawsegStack;
	static TArray<ptrdiff_t> visspriteStack;
	static TArray<DVector3> viewposStack;
	static TArray<visplane_t *> visplaneStack;

	numskyboxes = 0;

	if (visplanes[MAXVISPLANES] == NULL)
		return;

	R_3D_EnterSkybox();
	CurrentPortalInSkybox = true;

	int savedextralight = extralight;
	DVector3 savedpos = ViewPos;
	DAngle savedangle = ViewAngle;
	ptrdiff_t savedvissprite_p = vissprite_p - vissprites;
	ptrdiff_t savedds_p = ds_p - drawsegs;
	ptrdiff_t savedlastopening = lastopening;
	size_t savedinteresting = FirstInterestingDrawseg;
	double savedvisibility = R_GetVisibility();
	AActor *savedcamera = camera;
	sector_t *savedsector = viewsector;

	int i;
	visplane_t *pl;

	for (pl = visplanes[MAXVISPLANES]; pl != NULL; pl = visplanes[MAXVISPLANES])
	{
		// Pop the visplane off the list now so that if this skybox adds more
		// skyboxes to the list, they will be drawn instead of skipped (because
		// new skyboxes go to the beginning of the list instead of the end).
		visplanes[MAXVISPLANES] = pl->next;
		pl->next = NULL;

		if (pl->right < pl->left || !r_skyboxes || numskyboxes == MAX_SKYBOX_PLANES || pl->portal == NULL)
		{
			R_DrawSinglePlane (pl, OPAQUE, false, false);
			*freehead = pl;
			freehead = &pl->next;
			continue;
		}

		numskyboxes++;

		FSectorPortal *port = pl->portal;
		switch (port->mType)
		{
		case PORTS_SKYVIEWPOINT:
		{
			// Don't let gun flashes brighten the sky box
			ASkyViewpoint *sky = barrier_cast<ASkyViewpoint*>(port->mSkybox);
			extralight = 0;
			R_SetVisibility(sky->args[0] * 0.25f);

			ViewPos = sky->InterpolatedPosition(r_TicFracF);
			ViewAngle = savedangle + (sky->PrevAngles.Yaw + deltaangle(sky->PrevAngles.Yaw, sky->Angles.Yaw) * r_TicFracF);

			R_CopyStackedViewParameters();
			break;
		}

		case PORTS_STACKEDSECTORTHING:
		case PORTS_PORTAL:
		case PORTS_LINKEDPORTAL:
			extralight = pl->extralight;
			R_SetVisibility (pl->visibility);
			ViewPos.X = pl->viewpos.X + port->mDisplacement.X;
			ViewPos.Y = pl->viewpos.Y + port->mDisplacement.Y;
			ViewPos.Z = pl->viewpos.Z;
			ViewAngle = pl->viewangle;
			break;

		case PORTS_HORIZON:
		case PORTS_PLANE:
			// not implemented yet

		default:
			R_DrawSinglePlane(pl, OPAQUE, false, false);
			*freehead = pl;
			freehead = &pl->next;
			numskyboxes--;
			continue;
		}

		port->mFlags |= PORTSF_INSKYBOX;
		if (port->mPartner > 0) sectorPortals[port->mPartner].mFlags |= PORTSF_INSKYBOX;
		camera = NULL;
		viewsector = port->mDestination;
		assert(viewsector != NULL);
		R_SetViewAngle ();
		validcount++;	// Make sure we see all sprites

		R_ClearPlanes (false);
		R_ClearClipSegs (pl->left, pl->right);
		WindowLeft = pl->left;
		WindowRight = pl->right;

		for (i = pl->left; i < pl->right; i++)
		{
			if (pl->top[i] == 0x7fff)
			{
				ceilingclip[i] = viewheight;
				floorclip[i] = -1;
			}
			else
			{
				ceilingclip[i] = pl->top[i];
				floorclip[i] = pl->bottom[i];
			}
		}

		// Create a drawseg to clip sprites to the sky plane
		R_CheckDrawSegs ();
		ds_p->CurrentPortalUniq = CurrentPortalUniq;
		ds_p->siz1 = INT_MAX;
		ds_p->siz2 = INT_MAX;
		ds_p->sz1 = 0;
		ds_p->sz2 = 0;
		ds_p->x1 = pl->left;
		ds_p->x2 = pl->right;
		ds_p->silhouette = SIL_BOTH;
		ds_p->sprbottomclip = R_NewOpening (pl->right - pl->left);
		ds_p->sprtopclip = R_NewOpening (pl->right - pl->left);
		ds_p->maskedtexturecol = ds_p->swall = -1;
		ds_p->bFogBoundary = false;
		ds_p->curline = NULL;
		ds_p->fake = 0;
		memcpy (openings + ds_p->sprbottomclip, floorclip + pl->left, (pl->right - pl->left)*sizeof(short));
		memcpy (openings + ds_p->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left)*sizeof(short));

		firstvissprite = vissprite_p;
		firstdrawseg = ds_p++;
		FirstInterestingDrawseg = InterestingDrawsegs.Size();

		interestingStack.Push (FirstInterestingDrawseg);
		ptrdiff_t diffnum = firstdrawseg - drawsegs;
		drawsegStack.Push (diffnum);
		diffnum = firstvissprite - vissprites;
		visspriteStack.Push (diffnum);
		viewposStack.Push(ViewPos);
		visplaneStack.Push (pl);

		InSubsector = NULL;
		R_RenderBSPNode (nodes + numnodes - 1);
		R_3D_ResetClip(); // reset clips (floor/ceiling)
		R_DrawPlanes ();

		port->mFlags &= ~PORTSF_INSKYBOX;
		if (port->mPartner > 0) sectorPortals[port->mPartner].mFlags &= ~PORTSF_INSKYBOX;
	}

	// Draw all the masked textures in a second pass, in the reverse order they
	// were added. This must be done separately from the previous step for the
	// sake of nested skyboxes.
	while (interestingStack.Pop (FirstInterestingDrawseg))
	{
		ptrdiff_t pd = 0;

		drawsegStack.Pop (pd);
		firstdrawseg = drawsegs + pd;
		visspriteStack.Pop (pd);
		firstvissprite = vissprites + pd;

		// Masked textures and planes need the view coordinates restored for proper positioning.
		viewposStack.Pop(ViewPos);

		R_DrawMasked ();

		ds_p = firstdrawseg;
		vissprite_p = firstvissprite;

		visplaneStack.Pop (pl);
		if (pl->Alpha > 0 && pl->picnum != skyflatnum)
		{
			R_DrawSinglePlane (pl, pl->Alpha, pl->Additive, true);
		}
		*freehead = pl;
		freehead = &pl->next;
	}
	firstvissprite = vissprites;
	vissprite_p = vissprites + savedvissprite_p;
	firstdrawseg = drawsegs;
	ds_p = drawsegs + savedds_p;
	InterestingDrawsegs.Resize ((unsigned int)FirstInterestingDrawseg);
	FirstInterestingDrawseg = savedinteresting;

	lastopening = savedlastopening;

	camera = savedcamera;
	viewsector = savedsector;
	ViewPos = savedpos;
	R_SetVisibility(savedvisibility);
	extralight = savedextralight;
	ViewAngle = savedangle;
	R_SetViewAngle ();

	CurrentPortalInSkybox = false;
	R_3D_LeaveSkybox();

	if(fakeActive) return;

	for (*freehead = visplanes[MAXVISPLANES], visplanes[MAXVISPLANES] = NULL; *freehead; )
		freehead = &(*freehead)->next;
}
Пример #10
0
int FMugShot::UpdateState(player_t *player, StateFlags stateflags)
{
	FString		full_state_name;

	if (player->health > 0)
	{
		if (bEvilGrin && !(stateflags & DISABLEGRIN))
		{
			if (player->bonuscount)
			{
				SetState("grin", false);
				return 0;
			}
		}
		bEvilGrin = false;

		bool ouch = (!st_oldouch && FaceHealth - player->health > ST_MUCHPAIN) || (st_oldouch && player->health - FaceHealth > ST_MUCHPAIN);
		if (player->damagecount && 
			// Now go in if pain is disabled but we think ouch will be shown (and ouch is not disabled!)
			(!(stateflags & DISABLEPAIN) || (((FaceHealth != -1 && ouch) || bOuchActive) && !(stateflags & DISABLEOUCH))))
		{
			int damage_angle = 1;
			if (player->attacker && player->attacker != player->mo)
			{
				if (player->mo != NULL)
				{
					// The next 12 lines are from the Doom statusbar code.
					DAngle badguyangle = player->mo->AngleTo(player->attacker);
					DAngle diffang = deltaangle(player->mo->Angles.Yaw, badguyangle);
					if (diffang > 45.)
					{ // turn face right
						damage_angle = 0;
					}
					else if (diffang < -45.)
					{ // turn face left
						damage_angle = 2;
					}
				}
			}
			bool use_ouch = false;
			if (((FaceHealth != -1 && ouch) || bOuchActive) && !(stateflags & DISABLEOUCH))
			{
				use_ouch = true;
				full_state_name = "ouch.";
			}
			else
			{
				full_state_name = "pain.";
			}
			full_state_name += player->LastDamageType;
			if (SetState(full_state_name, false, true))
			{
				bDamageFaceActive = (CurrentState != NULL);
				LastDamageAngle = damage_angle;
				bOuchActive = use_ouch;
			}
			return damage_angle;
		}
		if (bDamageFaceActive)
		{
			if (CurrentState == NULL)
			{
				bDamageFaceActive = false;
			}
			else
			{
				bool use_ouch = false;
				if (((FaceHealth != -1 && ouch) || bOuchActive) && !(stateflags & DISABLEOUCH))
				{
					use_ouch = true;
					full_state_name = "ouch.";
				}
				else
				{
					full_state_name = "pain.";
				}
				full_state_name += player->LastDamageType;
				if (SetState(full_state_name))
				{
					bOuchActive = use_ouch;
				}
				return LastDamageAngle;
			}
		}

		if (RampageTimer == ST_RAMPAGEDELAY && !(stateflags & DISABLERAMPAGE))
		{
			SetState("rampage", !bNormal); //If we have nothing better to show, use the rampage face.
			return 0;
		}

		if (bNormal)
		{
			bool good;
			if ((player->cheats & CF_GODMODE) || (player->cheats & CF_GODMODE2) || (player->mo != NULL && player->mo->flags2 & MF2_INVULNERABLE))
			{
				good = SetState((stateflags & ANIMATEDGODMODE) ? "godanimated" : "god");
			}
			else
			{
				good = SetState("normal");
			}
			if (good)
			{
				bNormal = true; //SetState sets bNormal to false.
			}
		}
	}
	else
	{
		if (!(stateflags & XDEATHFACE) || !(player->cheats & CF_EXTREMELYDEAD))
		{
			full_state_name = "death.";
		}
		else
		{
			full_state_name = "xdeath.";
		}
		full_state_name += player->LastDamageType;
		SetState(full_state_name);
		bNormal = true; //Allow the face to return to alive states when the player respawns.
	}
	return 0;
}
Пример #11
0
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
{
	PARAM_ACTION_PROLOGUE;
	PARAM_SOUND_OPT	(fullsound)			{ fullsound = "weapons/sawfull"; }
	PARAM_SOUND_OPT	(hitsound)			{ hitsound = "weapons/sawhit"; }
	PARAM_INT_OPT	(damage)			{ damage = 2; }
	PARAM_CLASS_OPT	(pufftype, AActor)	{ pufftype = NULL; }
	PARAM_INT_OPT	(flags)				{ flags = 0; }
	PARAM_FLOAT_OPT	(range)				{ range = 0; }
	PARAM_ANGLE_OPT	(spread_xy)			{ spread_xy = 2.8125; }
	PARAM_ANGLE_OPT	(spread_z)			{ spread_z = 0.; }
	PARAM_FLOAT_OPT	(lifesteal)			{ lifesteal = 0; }
	PARAM_INT_OPT	(lifestealmax)		{ lifestealmax = 0; }
	PARAM_CLASS_OPT	(armorbonustype, ABasicArmorBonus)	{ armorbonustype = NULL; }

	DAngle angle;
	DAngle slope;
	player_t *player;
	FTranslatedLineTarget t;
	int actualdamage;

	if (NULL == (player = self->player))
	{
		return 0;
	}

	if (pufftype == NULL)
	{
		pufftype = PClass::FindActor(NAME_BulletPuff);
	}
	if (damage == 0)
	{
		damage = 2;
	}
	if (!(flags & SF_NORANDOM))
	{
		damage *= (pr_saw()%10+1);
	}
	if (range == 0)
	{ 
		range = SAWRANGE;
	}

	angle = self->Angles.Yaw + spread_xy * (pr_saw.Random2() / 255.);
	slope = P_AimLineAttack (self, angle, range, &t) + spread_z * (pr_saw.Random2() / 255.);

	AWeapon *weapon = self->player->ReadyWeapon;
	if ((weapon != NULL) && !(flags & SF_NOUSEAMMO) && !(!t.linetarget && (flags & SF_NOUSEAMMOMISS)) && !(weapon->WeaponFlags & WIF_DEHAMMO) && ACTION_CALL_FROM_WEAPON())
	{
		if (!weapon->DepleteAmmo (weapon->bAltFire))
			return 0;
	}

	P_LineAttack (self, angle, range, slope, damage, NAME_Melee, pufftype, false, &t, &actualdamage);

	if (!t.linetarget)
	{
		if ((flags & SF_RANDOMLIGHTMISS) && (pr_saw() > 64))
		{
			player->extralight = !player->extralight;
		}
		S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM);
		return 0;
	}

	if (flags & SF_RANDOMLIGHTHIT)
	{
		int randVal = pr_saw();
		if (randVal < 64)
		{
			player->extralight = 0;
		}
		else if (randVal < 160)
		{
			player->extralight = 1;
		}
		else
		{
			player->extralight = 2;
		}
	}

	if (lifesteal && !(t.linetarget->flags5 & MF5_DONTDRAIN))
	{
		if (flags & SF_STEALARMOR)
		{
			if (armorbonustype == NULL)
			{
				armorbonustype = dyn_cast<ABasicArmorBonus::MetaClass>(PClass::FindClass("ArmorBonus"));
			}
			if (armorbonustype != NULL)
			{
				assert(armorbonustype->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus)));
				ABasicArmorBonus *armorbonus = static_cast<ABasicArmorBonus *>(Spawn(armorbonustype));
				armorbonus->SaveAmount = int(armorbonus->SaveAmount * actualdamage * lifesteal);
				armorbonus->MaxSaveAmount = lifestealmax <= 0 ? armorbonus->MaxSaveAmount : lifestealmax;
				armorbonus->flags |= MF_DROPPED;
				armorbonus->ClearCounters();

				if (!armorbonus->CallTryPickup (self))
				{
					armorbonus->Destroy ();
				}
			}
		}

		else
		{
			P_GiveBody (self, int(actualdamage * lifesteal), lifestealmax);
		}
	}

	S_Sound (self, CHAN_WEAPON, hitsound, 1, ATTN_NORM);
		
	// turn to face target
	if (!(flags & SF_NOTURN))
	{
		DAngle anglediff = deltaangle(self->Angles.Yaw, t.angleFromSource);

		if (anglediff < 0.0)
		{
			if (anglediff < -4.5)
				self->Angles.Yaw = angle + 90.0 / 21;
			else
				self->Angles.Yaw -= 4.5;
		}
		else
		{
			if (anglediff > 4.5)
				self->Angles.Yaw = angle - 90.0 / 21;
			else
				self->Angles.Yaw += 4.5;
		}
	}
	if (!(flags & SF_NOPULLIN))
		self->flags |= MF_JUSTATTACKED;
	return 0;
}
Пример #12
0
bool APathFollower::Interpolate ()
{
	DVector3 dpos(0, 0, 0);
	FLinkContext ctx;

	if ((args[2] & 8) && Time > 0.f)
	{
		dpos = Pos();
	}

	if (CurrNode->Next==NULL) return false;

	UnlinkFromWorld (&ctx);
	DVector3 newpos;
	if (args[2] & 1)
	{	// linear
		newpos.X = Lerp(CurrNode->X(), CurrNode->Next->X());
		newpos.Y = Lerp(CurrNode->Y(), CurrNode->Next->Y());
		newpos.Z = Lerp(CurrNode->Z(), CurrNode->Next->Z());
	}
	else
	{	// spline
		if (CurrNode->Next->Next==NULL) return false;

		newpos.X = Splerp(PrevNode->X(), CurrNode->X(), CurrNode->Next->X(), CurrNode->Next->Next->X());
		newpos.Y = Splerp(PrevNode->Y(), CurrNode->Y(), CurrNode->Next->Y(), CurrNode->Next->Next->Y());
		newpos.Z = Splerp(PrevNode->Z(), CurrNode->Z(), CurrNode->Next->Z(), CurrNode->Next->Next->Z());
	}
	SetXYZ(newpos);
	LinkToWorld (&ctx);

	if (args[2] & 6)
	{
		if (args[2] & 8)
		{
			if (args[2] & 1)
			{ // linear
				dpos.X = CurrNode->Next->X() - CurrNode->X();
				dpos.Y = CurrNode->Next->Y() - CurrNode->Y();
				dpos.Z = CurrNode->Next->Z() - CurrNode->Z();
			}
			else if (Time > 0.f)
			{ // spline
				dpos = newpos - dpos;
			}
			else
			{
				int realarg = args[2];
				args[2] &= ~(2|4|8);
				Time += 0.1f;
				dpos = newpos;
				Interpolate ();
				Time -= 0.1f;
				args[2] = realarg;
				dpos = newpos - dpos;
				newpos -= dpos;
				SetXYZ(newpos);
			}
			if (args[2] & 2)
			{ // adjust yaw
				Angles.Yaw = dpos.Angle();
			}
			if (args[2] & 4)
			{ // adjust pitch; use floats for precision
				double dist = dpos.XY().Length();
				Angles.Pitch = dist != 0.f ? VecToAngle(dist, -dpos.Z) : 0.;
			}
		}
		else
		{
			if (args[2] & 2)
			{ // interpolate angle
				DAngle angle1 = CurrNode->Angles.Yaw.Normalized180();
				DAngle angle2 = angle1 + deltaangle(angle1, CurrNode->Next->Angles.Yaw);
				Angles.Yaw = Lerp(angle1.Degrees, angle2.Degrees);
			}
			if (args[2] & 1)
			{ // linear
				if (args[2] & 4)
				{ // interpolate pitch
					Angles.Pitch = Lerp(CurrNode->Angles.Pitch.Degrees, CurrNode->Next->Angles.Pitch.Degrees);
				}
			}
			else
			{ // spline
				if (args[2] & 4)
				{ // interpolate pitch
					Angles.Pitch = Splerp(PrevNode->Angles.Pitch.Degrees, CurrNode->Angles.Pitch.Degrees,
						CurrNode->Next->Angles.Pitch.Degrees, CurrNode->Next->Next->Angles.Pitch.Degrees);
				}
			}
		}
	}

	return true;
}