Пример #1
0
inline void GLPortal::ClearClipper()
{
	fixed_t angleOffset = viewangle - savedviewangle;

	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++)
	{
		angle_t startAngle = R_PointToAnglePrecise(savedviewx, savedviewy, 
												FLOAT2FIXED(lines[i].glseg.x2), FLOAT2FIXED(lines[i].glseg.y2));

		angle_t endAngle = R_PointToAnglePrecise(savedviewx, savedviewy, 
												FLOAT2FIXED(lines[i].glseg.x1), FLOAT2FIXED(lines[i].glseg.y1));

		if (startAngle-endAngle>0) 
		{
			clipper.SafeRemoveClipRangeRealAngles(startAngle + angleOffset, endAngle + angleOffset);
		}
	}

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

	// lock the parts that have just been clipped out.
	clipper.SetSilhouette();
}
Пример #2
0
//Emulates missile travel. Returns distance travelled.
fixed_t FCajunMaster::FakeFire (AActor *source, AActor *dest, ticcmd_t *cmd)
{
	AActor *th = Spawn ("CajunTrace", source->PosPlusZ(4*8*FRACUNIT), NO_REPLACE);
	
	th->target = source;		// where it came from

	float speed = (float)th->Speed;

	TVector3<double> velocity = source->Vec3To(dest);
	velocity.MakeUnit();
	th->velx = FLOAT2FIXED(velocity[0] * speed);
	th->vely = FLOAT2FIXED(velocity[1] * speed);
	th->velz = FLOAT2FIXED(velocity[2] * speed);

	fixed_t dist = 0;

	while (dist < SAFE_SELF_MISDIST)
	{
		dist += th->Speed;
		th->Move(th->velx, th->vely, th->velz);
		if (!CleanAhead (th, th->X(), th->Y(), cmd))
			break;
	}
	th->Destroy ();
	return dist;
}
Пример #3
0
	// construct a new ViewShifter, to temporarily shift camera viewpoint
	ViewShifter(EyeView eyeView, player_t * player, FGLRenderer& renderer_param) {
		renderer = &renderer_param;
		saved_viewx = viewx;
		saved_viewy = viewy;

		float xf = FIXED2FLOAT(viewx);
		float yf = FIXED2FLOAT(viewy);
		float yaw = DEG2RAD( ANGLE_TO_FLOAT(viewangle) );

		float eyeShift = vr_ipd / 2.0;
		if (eyeView == EYE_VIEW_LEFT)
			eyeShift = -eyeShift;
		float vh = 41.0;
		if (player != NULL)
			vh = FIXED2FLOAT(player->mo->ViewHeight);
		float mapunits_per_meter = vh/(0.95 * vr_player_height_meters);
		float eyeShift_mapunits = eyeShift * mapunits_per_meter;

		xf += sin(yaw) * eyeShift_mapunits;
		yf -= cos(yaw) * eyeShift_mapunits;
		// Printf("eyeShift_mapunits (ViewShifter) = %.1f\n", eyeShift_mapunits);

		viewx = FLOAT2FIXED(xf);
		viewy = FLOAT2FIXED(yf);
		renderer->SetCameraPos(viewx, viewy, viewz, viewangle);
		renderer->SetViewMatrix(false, false);
	}
Пример #4
0
void FTexture::SetScaledSize(int fitwidth, int fitheight)
{
	xScale = FLOAT2FIXED(float(Width) / fitwidth);
	yScale = FLOAT2FIXED(float(Height) / fitheight);
	// compensate for roundoff errors
	if (MulScale16(xScale, fitwidth) != Width) xScale++;
	if (MulScale16(yScale, fitheight) != Height) yScale++;
}
Пример #5
0
	void RenderViewport::InitTextureMapping()
	{
		int i;

		// Calc focallength so FieldOfView angles cover viewwidth.
		FocalLengthX = CenterX / viewwindow.FocalTangent;
		FocalLengthY = FocalLengthX * YaspectMul;

		// This is 1/FocalTangent before the widescreen extension of FOV.
		viewingrangerecip = FLOAT2FIXED(1. / tan(viewpoint.FieldOfView.Radians() / 2));

		// Now generate xtoviewangle for sky texture mapping.
		// [RH] Do not generate viewangletox, because texture mapping is no
		// longer done with trig, so it's not needed.
		const double slopestep = viewwindow.FocalTangent / viewwindow.centerx;
		double slope;

		for (i = viewwindow.centerx, slope = 0; i <= viewwidth; i++, slope += slopestep)
		{
			xtoviewangle[i] = angle_t((2 * M_PI - atan(slope)) * (ANGLE_180 / M_PI));
		}
		for (i = 0; i < viewwindow.centerx; i++)
		{
			xtoviewangle[i] = 0 - xtoviewangle[viewwidth - i - 1];
		}
	}
Пример #6
0
void gl_BuildPortalCoverage(FPortalCoverage *coverage, subsector_t *subsector, const DVector2 &displacement)
{
	TArray<FCoverageVertex> shape;
	double centerx=0, centery=0;

	shape.Resize(subsector->numlines);
	for(unsigned i=0; i<subsector->numlines; i++)
	{
		centerx += (shape[i].x = FLOAT2FIXED(subsector->firstline[i].v1->fX() + displacement.X));
		centery += (shape[i].y = FLOAT2FIXED(subsector->firstline[i].v1->fY() + displacement.Y));
	}

	FCoverageBuilder build(subsector);
	build.center.x = xs_CRoundToInt(centerx / subsector->numlines);
	build.center.y = xs_CRoundToInt(centery / subsector->numlines);

	build.CollectNode(level.HeadNode(), shape);
	coverage->subsectors = new uint32_t[build.collect.Size()]; 
	coverage->sscount = build.collect.Size();
	memcpy(coverage->subsectors, &build.collect[0], build.collect.Size() * sizeof(uint32_t));
}
Пример #7
0
	void ParseVertex(vertex_t *vt, vertexdata_t *vd)
	{
		vt->x = vt->y = 0;
		vd->zCeiling = vd->zFloor = vd->flags = 0;
		sc.MustGetStringName("{");
		while (!sc.CheckString("}"))
		{
			sc.MustGetString();
			FName key = sc.String;
			sc.MustGetStringName("=");
			sc.MustGetString();
			FString value = sc.String;
			sc.MustGetStringName(";");
			switch(key)
			{
			case NAME_X:
				vt->x = FLOAT2FIXED(strtod(value, NULL));
				break;

			case NAME_Y:
				vt->y = FLOAT2FIXED(strtod(value, NULL));
				break;

			case NAME_ZCeiling:
				vd->zCeiling = FLOAT2FIXED(strtod(value, NULL));
				vd->flags |= VERTEXFLAG_ZCeilingEnabled;
				break;

			case NAME_ZFloor:
				vd->zFloor = FLOAT2FIXED(strtod(value, NULL));
				vd->flags |= VERTEXFLAG_ZFloorEnabled;
				break;

			default:
				break;
			}
		}
	}
Пример #8
0
	void RenderDecal::DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style)
	{
		auto viewport = thread->Viewport.get();
		
		float iscale = walltexcoords.VStep[x] * maskedScaleY;
		double spryscale = 1 / iscale;
		double sprtopscreen;
		if (sprflipvert)
			sprtopscreen = viewport->CenterY + texturemid * spryscale;
		else
			sprtopscreen = viewport->CenterY - texturemid * spryscale;

		drawerargs.DrawMaskedColumn(thread, x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, style);
	}
Пример #9
0
fixed_t GetUDMFFixed(int type, int index, const char *key)
{
	assert(type >=0 && type <=3);

	FUDMFKeys *pKeys = UDMFKeys[type].CheckKey(index);

	if (pKeys != NULL)
	{
		FUDMFKey *pKey = pKeys->Find(key);
		if (pKey != NULL)
		{
			return FLOAT2FIXED(pKey->FloatVal);
		}
	}
	return 0;
}
Пример #10
0
//==========================================================================
//
//
//
//==========================================================================
void ADynamicLight::UpdateLocation()
{
    fixed_t oldx=X();
    fixed_t oldy=Y();
    fixed_t oldradius=radius;
    float intensity;

    if (IsActive())
    {
        if (target)
        {
            angle_t angle = target->angle>>ANGLETOFINESHIFT;
            fixedvec3 pos = target->Vec3Offset(
                                FixedMul(m_offX, finecosine[angle]) + FixedMul(m_offZ, finesine[angle]),
                                FixedMul(m_offX, finesine[angle]) - FixedMul(m_offZ, finecosine[angle]),
                                m_offY + target->GetBobOffset());
            SetXYZ(pos); // attached lights do not need to go into the regular blockmap
            PrevX = pos.x;
            PrevY = pos.y;
            PrevZ = pos.z;
            subsector = R_PointInSubsector(pos.x, pos.y);
            Sector = subsector->sector;
        }


        // The radius being used here is always the maximum possible with the
        // current settings. This avoids constant relinking of flickering lights

        if (lighttype == FlickerLight || lighttype == RandomFlickerLight)
        {
            intensity = float(m_intensity[1]);
        }
        else
        {
            intensity = m_currentIntensity;
        }
        radius = FLOAT2FIXED(intensity * 2.0f * gl_lights_size);

        if (X()!=oldx || Y()!=oldy || radius!=oldradius)
        {
            //Update the light lists
            LinkLight();
        }
    }
}
Пример #11
0
//==========================================================================
//
//
//
//==========================================================================
void ADynamicLight::UpdateLocation()
{
	fixed_t oldx=x;
	fixed_t oldy=y;
	fixed_t oldradius=radius;
	float intensity;

	if (IsActive())
	{
		if (target)
		{
			angle_t angle = target->angle>>ANGLETOFINESHIFT;
			PrevX = x = target->x + FixedMul(m_offX, finecosine[angle]) + FixedMul(m_offZ, finesine[angle]);
			PrevY = y = target->y + FixedMul(m_offX, finesine[angle]) - FixedMul(m_offZ, finecosine[angle]);
			PrevZ = z = target->z + m_offY + target->GetBobOffset();
			subsector = R_PointInSubsector(x, y);
			Sector = subsector->sector;
		}


		// The radius being used here is always the maximum possible with the
		// current settings. This avoids constant relinking of flickering lights

		if (lighttype == FlickerLight || lighttype == RandomFlickerLight) 
		{
			intensity = float(m_intensity[1]);
		}
		else
		{
			intensity = m_currentIntensity;
		}
		radius = FLOAT2FIXED(intensity * 2.0f * gl_lights_size);

		if (x!=oldx || y!=oldy || radius!=oldradius) 
		{
			//Update the light lists
			LinkLight();
		}
	}
}
Пример #12
0
static void ParseDamageDefinition(FScanner &sc)
{
	sc.SetCMode (true); // This may be 100% irrelevant for such a simple syntax, but I don't know

	// Get DamageType

	sc.MustGetString();
	FName damageType = sc.String;

	DamageTypeDefinition dtd;

	sc.MustGetToken('{');
	while (sc.MustGetAnyToken(), sc.TokenType != '}')
	{
		if (sc.Compare("FACTOR"))
		{
			sc.MustGetFloat();
			dtd.DefaultFactor = FLOAT2FIXED(sc.Float);
			if (!dtd.DefaultFactor) dtd.ReplaceFactor = true; // Multiply by 0 yields 0: FixedMul(damage, FixedMul(factor, 0)) is more wasteful than FixedMul(factor, 0)
		}
		else if (sc.Compare("REPLACEFACTOR"))
		{
			dtd.ReplaceFactor = true;
		}
		else if (sc.Compare("NOARMOR"))
		{
			dtd.NoArmor = true;
		}
		else
		{
			sc.ScriptError("Unexpected data (%s) in damagetype definition.", sc.String);
		}
	}

	dtd.Apply(damageType);

	sc.SetCMode (false); // (set to true earlier in function)
}
Пример #13
0
//-----------------------------------------------------------------------------
//
// R_EnterMirror
//
//-----------------------------------------------------------------------------
void GLMirrorPortal::DrawContents()
{
	if (renderdepth>r_mirror_recursions) 
	{
		ClearScreen();
		return;
	}

	GLRenderer->mCurrentPortal = this;
	angle_t startang = viewangle;
	fixed_t startx = viewx;
	fixed_t starty = viewy;

	vertex_t *v1 = linedef->v1;
	vertex_t *v2 = linedef->v2;

	// Reflect the current view behind the mirror.
	if (linedef->dx == 0)
	{ 
		// vertical mirror
		viewx = v1->x - startx + v1->x;

		// Compensation for reendering inaccuracies
		if (startx<v1->x)  viewx -= FRACUNIT/2;
		else viewx += FRACUNIT/2;
	}
	else if (linedef->dy == 0)
	{ 
		// horizontal mirror
		viewy = v1->y - starty + v1->y;

		// Compensation for reendering inaccuracies
		if (starty<v1->y)  viewy -= FRACUNIT/2;
		else viewy += FRACUNIT/2;
	}
	else
	{ 
		// any mirror--use floats to avoid integer overflow. 
		// Use doubles to avoid losing precision which is very important here.

		double dx = FIXED2FLOAT(v2->x - v1->x);
		double dy = FIXED2FLOAT(v2->y - v1->y);
		double x1 = FIXED2FLOAT(v1->x);
		double y1 = FIXED2FLOAT(v1->y);
		double x = FIXED2FLOAT(startx);
		double y = FIXED2FLOAT(starty);

		// the above two cases catch len == 0
		double r = ((x - x1)*dx + (y - y1)*dy) / (dx*dx + dy*dy);

		viewx = FLOAT2FIXED((x1 + r * dx)*2 - x);
		viewy = FLOAT2FIXED((y1 + r * dy)*2 - y);

		// Compensation for reendering inaccuracies
		FVector2 v(-dx, dy);
		v.MakeUnit();

		viewx+= FLOAT2FIXED(v[1] * renderdepth / 2);
		viewy+= FLOAT2FIXED(v[0] * renderdepth / 2);
	}
	// we cannot afford any imprecisions caused by R_PointToAngle2 here. They'd be visible as seams around the mirror.
	viewangle = 2*R_PointToAnglePrecise (linedef->v1->x, linedef->v1->y,
										linedef->v2->x, linedef->v2->y) - startang;

	GLRenderer->mViewActor = NULL;

	validcount++;

	MirrorFlag++;
	GLRenderer->SetupView(viewx, viewy, viewz, viewangle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1));

	clipper.Clear();

	angle_t af = GLRenderer->FrustumAngle();
	if (af<ANGLE_180) clipper.SafeAddClipRangeRealAngles(viewangle+af, viewangle-af);

	angle_t a2 = linedef->v1->GetClipAngle();
	angle_t a1 = linedef->v2->GetClipAngle();
	clipper.SafeAddClipRange(a1,a2);

	GLRenderer->DrawScene();

	MirrorFlag--;
}
Пример #14
0
void R_DrawSkyPlane (visplane_t *pl)
{
	FTextureID sky1tex, sky2tex;
	double frontdpos = 0, backdpos = 0;

	if ((level.flags & LEVEL_SWAPSKIES) && !(level.flags & LEVEL_DOUBLESKY))
	{
		sky1tex = sky2texture;
	}
	else
	{
		sky1tex = sky1texture;
	}
	sky2tex = sky2texture;
	skymid = skytexturemid;
	skyangle = ViewAngle.BAMs();

	if (pl->picnum == skyflatnum)
	{
		if (!(pl->sky & PL_SKYFLAT))
		{	// use sky1
		sky1:
			frontskytex = TexMan(sky1tex, true);
			if (level.flags & LEVEL_DOUBLESKY)
				backskytex = TexMan(sky2tex, true);
			else
				backskytex = NULL;
			skyflip = 0;
			frontdpos = sky1pos;
			backdpos = sky2pos;
			frontcyl = sky1cyl;
			backcyl = sky2cyl;
		}
		else if (pl->sky == PL_SKYFLAT)
		{	// use sky2
			frontskytex = TexMan(sky2tex, true);
			backskytex = NULL;
			frontcyl = sky2cyl;
			skyflip = 0;
			frontdpos = sky2pos;
		}
		else
		{	// MBF's linedef-controlled skies
			// Sky Linedef
			const line_t *l = &lines[(pl->sky & ~PL_SKYFLAT)-1];

			// Sky transferred from first sidedef
			const side_t *s = l->sidedef[0];
			int pos;

			// Texture comes from upper texture of reference sidedef
			// [RH] If swapping skies, then use the lower sidedef
			if (level.flags & LEVEL_SWAPSKIES && s->GetTexture(side_t::bottom).isValid())
			{
				pos = side_t::bottom;
			}
			else
			{
				pos = side_t::top;
			}

			frontskytex = TexMan(s->GetTexture(pos), true);
			if (frontskytex == NULL || frontskytex->UseType == FTexture::TEX_Null)
			{ // [RH] The blank texture: Use normal sky instead.
				goto sky1;
			}
			backskytex = NULL;

			// Horizontal offset is turned into an angle offset,
			// to allow sky rotation as well as careful positioning.
			// However, the offset is scaled very small, so that it
			// allows a long-period of sky rotation.
			skyangle += FLOAT2FIXED(s->GetTextureXOffset(pos));

			// Vertical offset allows careful sky positioning.
			skymid = s->GetTextureYOffset(pos) - 28;

			// We sometimes flip the picture horizontally.
			//
			// Doom always flipped the picture, so we make it optional,
			// to make it easier to use the new feature, while to still
			// allow old sky textures to be used.
			skyflip = l->args[2] ? 0u : ~0u;

			int frontxscale = int(frontskytex->Scale.X * 1024);
			frontcyl = MAX(frontskytex->GetWidth(), frontxscale);
			if (skystretch)
			{
				skymid = skymid * frontskytex->GetScaledHeightDouble() / SKYSTRETCH_HEIGHT;
			}
		}
	}
	frontpos = int(fmod(frontdpos, sky1cyl * 65536.0));
	if (backskytex != NULL)
	{
		backpos = int(fmod(backdpos, sky2cyl * 65536.0));
	}

	bool fakefixed = false;
	if (fixedcolormap)
	{
		R_SetColorMapLight(fixedcolormap, 0, 0);
	}
	else
	{
		fakefixed = true;
		fixedcolormap = NormalLight.Maps;
		R_SetColorMapLight(fixedcolormap, 0, 0);
	}

	R_DrawSky (pl);

	if (fakefixed)
		fixedcolormap = NULL;
}
Пример #15
0
fixed_t UDMFParserBase::CheckFixed(const char *key)
{
	return FLOAT2FIXED(CheckFloat(key));
}
Пример #16
0
void R_DrawNormalPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t alpha, bool additive, bool masked)
{
	if (alpha <= 0)
	{
		return;
	}

	double planeang = (pl->xform.Angle + pl->xform.baseAngle).Radians();
	double xstep, ystep, leftxfrac, leftyfrac, rightxfrac, rightyfrac;
	double x;

	xscale = xs_ToFixed(32 - ds_xbits, _xscale);
	yscale = xs_ToFixed(32 - ds_ybits, _yscale);
	if (planeang != 0)
	{
		double cosine = cos(planeang), sine = sin(planeang);
		pviewx = FLOAT2FIXED(pl->xform.xOffs + ViewPos.X * cosine - ViewPos.Y * sine);
		pviewy = FLOAT2FIXED(pl->xform.yOffs - ViewPos.X * sine - ViewPos.Y * cosine);
	}
	else
	{
		pviewx = FLOAT2FIXED(pl->xform.xOffs + ViewPos.X);
		pviewy = FLOAT2FIXED(pl->xform.yOffs - ViewPos.Y);
	}

	pviewx = FixedMul (xscale, pviewx);
	pviewy = FixedMul (yscale, pviewy);
	
	// left to right mapping
	planeang += (ViewAngle - 90).Radians();

	// Scale will be unit scale at FocalLengthX (normally SCREENWIDTH/2) distance
	xstep = cos(planeang) / FocalLengthX;
	ystep = -sin(planeang) / FocalLengthX;

	// [RH] flip for mirrors
	if (MirrorFlags & RF_XFLIP)
	{
		xstep = -xstep;
		ystep = -ystep;
	}

	planeang += M_PI/2;
	double cosine = cos(planeang), sine = -sin(planeang);
	x = pl->right - centerx - 0.5;
	rightxfrac = _xscale * (cosine + x * xstep);
	rightyfrac = _yscale * (sine + x * ystep);
	x = pl->left - centerx - 0.5;
	leftxfrac = _xscale * (cosine + x * xstep);
	leftyfrac = _yscale * (sine + x * ystep);

	basexfrac = rightxfrac;
	baseyfrac = rightyfrac;
	xstepscale = (rightxfrac - leftxfrac) / (pl->right - pl->left);
	ystepscale = (rightyfrac - leftyfrac) / (pl->right - pl->left);

	planeheight = fabs(pl->height.Zat0() - ViewPos.Z);

	GlobVis = r_FloorVisibility / planeheight;
	ds_light = 0;
	if (fixedlightlev >= 0)
	{
		R_SetDSColorMapLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
		plane_shade = false;
	}
	else if (fixedcolormap)
	{
		R_SetDSColorMapLight(fixedcolormap, 0, 0);
		plane_shade = false;
	}
	else
	{
		plane_shade = true;
	}

	if (spanfunc != R_FillSpan)
	{
		if (masked)
		{
			if (alpha < OPAQUE || additive)
			{
				if (!additive)
				{
					spanfunc = R_DrawSpanMaskedTranslucent;
					dc_srcblend = Col2RGB8[alpha>>10];
					dc_destblend = Col2RGB8[(OPAQUE-alpha)>>10];
				}
				else
				{
					spanfunc = R_DrawSpanMaskedAddClamp;
					dc_srcblend = Col2RGB8_LessPrecision[alpha>>10];
					dc_destblend = Col2RGB8_LessPrecision[FRACUNIT>>10];
				}
			}
			else
			{
Пример #17
0
	void ParseSector(sector_t *sec, int index)
	{
		int lightcolor = -1;
		int fadecolor = -1;
		int desaturation = -1;
		int fplaneflags = 0, cplaneflags = 0;
		double fp[4] = { 0 }, cp[4] = { 0 };

		memset(sec, 0, sizeof(*sec));
		sec->lightlevel = 160;
		sec->SetXScale(sector_t::floor, FRACUNIT);	// [RH] floor and ceiling scaling
		sec->SetYScale(sector_t::floor, FRACUNIT);
		sec->SetXScale(sector_t::ceiling, FRACUNIT);
		sec->SetYScale(sector_t::ceiling, FRACUNIT);
		sec->SetAlpha(sector_t::floor, FRACUNIT);
		sec->SetAlpha(sector_t::ceiling, FRACUNIT);
		sec->thinglist = NULL;
		sec->touching_thinglist = NULL;		// phares 3/14/98
		sec->seqType = (level.flags & LEVEL_SNDSEQTOTALCTRL) ? 0 : -1;
		sec->nextsec = -1;	//jff 2/26/98 add fields to support locking out
		sec->prevsec = -1;	// stair retriggering until build completes
		sec->heightsec = NULL;	// sector used to get floor and ceiling height
		sec->sectornum = index;
		if (floordrop) sec->Flags = SECF_FLOORDROP;
		// killough 3/7/98: end changes

		sec->gravity = 1.f;	// [RH] Default sector gravity of 1.0
		sec->ZoneNumber = 0xFFFF;

		// killough 8/28/98: initialize all sectors to normal friction
		sec->friction = ORIG_FRICTION;
		sec->movefactor = ORIG_FRICTION_FACTOR;

		sc.MustGetToken('{');
		while (!sc.CheckToken('}'))
		{
			FName key = ParseKey();
			switch(key)
			{
			case NAME_Heightfloor:
				sec->SetPlaneTexZ(sector_t::floor, CheckInt(key) << FRACBITS);
				continue;

			case NAME_Heightceiling:
				sec->SetPlaneTexZ(sector_t::ceiling, CheckInt(key) << FRACBITS);
				continue;

			case NAME_Texturefloor:
				SetTexture(sec, index, sector_t::floor, CheckString(key), missingTex, false);
				continue;

			case NAME_Textureceiling:
				SetTexture(sec, index, sector_t::ceiling, CheckString(key), missingTex, false);
				continue;

			case NAME_Lightlevel:
				sec->lightlevel = sector_t::ClampLight(CheckInt(key));
				continue;

			case NAME_Special:
				sec->special = (short)CheckInt(key);
				if (isTranslated) sec->special = P_TranslateSectorSpecial(sec->special);
				else if (namespc == NAME_Hexen)
				{
					if (sec->special < 0 || sec->special > 255 || !HexenSectorSpecialOk[sec->special])
						sec->special = 0;	// NULL all unknown specials
				}
				continue;

			case NAME_Id:
				sec->tag = (short)CheckInt(key);
				continue;

			default:
				break;
			}

			if (namespace_bits & (Zd|Zdt|Va)) switch(key)
			{
				case NAME_Xpanningfloor:
					sec->SetXOffset(sector_t::floor, CheckFixed(key));
					continue;

				case NAME_Ypanningfloor:
					sec->SetYOffset(sector_t::floor, CheckFixed(key));
					continue;

				case NAME_Xpanningceiling:
					sec->SetXOffset(sector_t::ceiling, CheckFixed(key));
					continue;

				case NAME_Ypanningceiling:
					sec->SetYOffset(sector_t::ceiling, CheckFixed(key));
					continue;

				case NAME_Xscalefloor:
					sec->SetXScale(sector_t::floor, CheckFixed(key));
					continue;

				case NAME_Yscalefloor:
					sec->SetYScale(sector_t::floor, CheckFixed(key));
					continue;

				case NAME_Xscaleceiling:
					sec->SetXScale(sector_t::ceiling, CheckFixed(key));
					continue;

				case NAME_Yscaleceiling:
					sec->SetYScale(sector_t::ceiling, CheckFixed(key));
					continue;

				case NAME_Rotationfloor:
					sec->SetAngle(sector_t::floor, CheckAngle(key));
					continue;

				case NAME_Rotationceiling:
					sec->SetAngle(sector_t::ceiling, CheckAngle(key));
					continue;

				case NAME_Lightfloor:
					sec->SetPlaneLight(sector_t::floor, CheckInt(key));
					continue;

				case NAME_Lightceiling:
					sec->SetPlaneLight(sector_t::ceiling, CheckInt(key));
					continue;

				case NAME_Alphafloor:
					sec->SetAlpha(sector_t::floor, CheckFixed(key));
					continue;

				case NAME_Alphaceiling:
					sec->SetAlpha(sector_t::ceiling, CheckFixed(key));
					continue;

				case NAME_Renderstylefloor:
				{
					const char *str = CheckString(key);
					if (!stricmp(str, "translucent")) sec->ChangeFlags(sector_t::floor, PLANEF_ADDITIVE, 0);
					else if (!stricmp(str, "add")) sec->ChangeFlags(sector_t::floor, 0, PLANEF_ADDITIVE);
					else sc.ScriptMessage("Unknown value \"%s\" for 'renderstylefloor'\n", str);
					continue;
				}

				case NAME_Renderstyleceiling:
				{
					const char *str = CheckString(key);
					if (!stricmp(str, "translucent")) sec->ChangeFlags(sector_t::ceiling, PLANEF_ADDITIVE, 0);
					else if (!stricmp(str, "add")) sec->ChangeFlags(sector_t::ceiling, 0, PLANEF_ADDITIVE);
					else sc.ScriptMessage("Unknown value \"%s\" for 'renderstyleceiling'\n", str);
					continue;
				}

				case NAME_Lightfloorabsolute:
					if (CheckBool(key)) sec->ChangeFlags(sector_t::floor, 0, PLANEF_ABSLIGHTING);
					else sec->ChangeFlags(sector_t::floor, PLANEF_ABSLIGHTING, 0);
					continue;

				case NAME_Lightceilingabsolute:
					if (CheckBool(key)) sec->ChangeFlags(sector_t::ceiling, 0, PLANEF_ABSLIGHTING);
					else sec->ChangeFlags(sector_t::ceiling, PLANEF_ABSLIGHTING, 0);
					continue;

				case NAME_Gravity:
					sec->gravity = float(CheckFloat(key));
					continue;

				case NAME_Lightcolor:
					lightcolor = CheckInt(key);
					continue;

				case NAME_Fadecolor:
					fadecolor = CheckInt(key);
					continue;

				case NAME_Desaturation:
					desaturation = int(255*CheckFloat(key));
					continue;

				case NAME_Silent:
					Flag(sec->Flags, SECF_SILENT, key);
					continue;

				case NAME_NoRespawn:
					Flag(sec->Flags, SECF_NORESPAWN, key);
					continue;

				case NAME_Nofallingdamage:
					Flag(sec->Flags, SECF_NOFALLINGDAMAGE, key);
					continue;

				case NAME_Dropactors:
					Flag(sec->Flags, SECF_FLOORDROP, key);
					continue;

				case NAME_SoundSequence:
					sec->SeqName = CheckString(key);
					sec->seqType = -1;
					continue;

				case NAME_hidden:
					Flag(sec->MoreFlags, SECF_HIDDEN, key);
					break;

				case NAME_Waterzone:
					Flag(sec->MoreFlags, SECF_UNDERWATER, key);
					break;

				case NAME_floorplane_a:
					fplaneflags |= 1;
					fp[0] = CheckFloat(key);
					break;

				case NAME_floorplane_b:
					fplaneflags |= 2;
					fp[1] = CheckFloat(key);
					break;

				case NAME_floorplane_c:
					fplaneflags |= 4;
					fp[2] = CheckFloat(key);
					break;

				case NAME_floorplane_d:
					fplaneflags |= 8;
					fp[3] = CheckFloat(key);
					break;

				case NAME_ceilingplane_a:
					cplaneflags |= 1;
					cp[0] = CheckFloat(key);
					break;

				case NAME_ceilingplane_b:
					cplaneflags |= 2;
					cp[1] = CheckFloat(key);
					break;

				case NAME_ceilingplane_c:
					cplaneflags |= 4;
					cp[2] = CheckFloat(key);
					break;

				case NAME_ceilingplane_d:
					cplaneflags |= 8;
					cp[3] = CheckFloat(key);
					break;

				default:
					break;
			}
				
			if (!strnicmp("user_", key.GetChars(), 5))
			{
				AddUserKey(key, UDMF_Sector, index);
			}
		}

		sec->secretsector = !!(sec->special&SECRET_MASK);
		
		// Reset the planes to their defaults if not all of the plane equation's parameters were found.
		if (fplaneflags != 15)
		{
			sec->floorplane.a = sec->floorplane.b = 0;
			sec->floorplane.d = -sec->GetPlaneTexZ(sector_t::floor);
			sec->floorplane.c = FRACUNIT;
			sec->floorplane.ic = FRACUNIT;
		}
		else
		{
			double ulen = TVector3<double>(fp[0], fp[1], fp[2]).Length();

			// normalize the vector, it must have a length of 1
			sec->floorplane.a = FLOAT2FIXED(fp[0] / ulen);
			sec->floorplane.b = FLOAT2FIXED(fp[1] / ulen);
			sec->floorplane.c = FLOAT2FIXED(fp[2] / ulen);
			sec->floorplane.d = FLOAT2FIXED(fp[3] / ulen);
			sec->floorplane.ic = FLOAT2FIXED(ulen / fp[2]);
		}
		if (cplaneflags != 15)
		{
			sec->ceilingplane.a = sec->ceilingplane.b = 0;
			sec->ceilingplane.d = sec->GetPlaneTexZ(sector_t::ceiling);
			sec->ceilingplane.c = -FRACUNIT;
			sec->ceilingplane.ic = -FRACUNIT;
		}
		else
		{
			double ulen = TVector3<double>(cp[0], cp[1], cp[2]).Length();

			// normalize the vector, it must have a length of 1
			sec->floorplane.a = FLOAT2FIXED(cp[0] / ulen);
			sec->floorplane.b = FLOAT2FIXED(cp[1] / ulen);
			sec->floorplane.c = FLOAT2FIXED(cp[2] / ulen);
			sec->floorplane.d = FLOAT2FIXED(cp[3] / ulen);
			sec->floorplane.ic = FLOAT2FIXED(ulen / cp[2]);
		}

		if (lightcolor == -1 && fadecolor == -1 && desaturation == -1)
		{
			// [RH] Sectors default to white light with the default fade.
			//		If they are outside (have a sky ceiling), they use the outside fog.
			if (level.outsidefog != 0xff000000 && (sec->GetTexture(sector_t::ceiling) == skyflatnum || (sec->special&0xff) == Sector_Outside))
			{
				if (fogMap == NULL)
					fogMap = GetSpecialLights (PalEntry (255,255,255), level.outsidefog, 0);
				sec->ColorMap = fogMap;
			}
			else
			{
				if (normMap == NULL)
					normMap = GetSpecialLights (PalEntry (255,255,255), level.fadeto, NormalLight.Desaturate);
				sec->ColorMap = normMap;
			}
		}
		else
		{
			if (lightcolor == -1) lightcolor = PalEntry(255,255,255);
			if (fadecolor == -1) 
			{
				if (level.outsidefog != 0xff000000 && (sec->GetTexture(sector_t::ceiling) == skyflatnum || (sec->special&0xff) == Sector_Outside))
					fadecolor = level.outsidefog;
				else
					fadecolor = level.fadeto;
			}
			if (desaturation == -1) desaturation = NormalLight.Desaturate;

			sec->ColorMap = GetSpecialLights (lightcolor, fadecolor, desaturation);
		}
	}
Пример #18
0
void FMapInfoParser::ParseGameInfo()
{
	sc.MustGetToken('{');
	while(sc.GetToken())
	{
		if (sc.TokenType == '}') return;

		sc.TokenMustBe(TK_Identifier);
		FString nextKey = sc.String;
		sc.MustGetToken('=');

		if (nextKey.CompareNoCase("weaponslot") == 0)
		{
			sc.MustGetToken(TK_IntConst);
			if (sc.Number < 0 || sc.Number >= 10)
			{
				sc.ScriptError("Weapon slot index must be in range [0..9].\n");
			}
			int i = sc.Number;
			gameinfo.DefaultWeaponSlots[i].Clear();
			sc.MustGetToken(',');
			do
			{
				sc.MustGetString();
				FName val = sc.String;
				gameinfo.DefaultWeaponSlots[i].Push(val);

			}
			while (sc.CheckToken(','));
		}
		else if(nextKey.CompareNoCase("border") == 0)
		{
			if(sc.CheckToken(TK_Identifier))
			{
				switch(sc.MustMatchString(GameInfoBorders))
				{
					default:
						gameinfo.border = &DoomBorder;
						break;
					case 1:
						gameinfo.border = &HereticBorder;
						break;
					case 2:
						gameinfo.border = &StrifeBorder;
						break;
				}
			}
			else
			{
				// border = {size, offset, tr, t, tl, r, l ,br, b, bl};
				char *graphics[8] = {DoomBorder.tr, DoomBorder.t, DoomBorder.tl, DoomBorder.r, DoomBorder.l, DoomBorder.br, DoomBorder.b, DoomBorder.bl};
				sc.MustGetToken(TK_IntConst);
				DoomBorder.offset = sc.Number;
				sc.MustGetToken(',');
				sc.MustGetToken(TK_IntConst);
				DoomBorder.size = sc.Number;
				for(int i = 0;i < 8;i++)
				{
					sc.MustGetToken(',');
					sc.MustGetToken(TK_StringConst);
					int len = int(strlen(sc.String));
					if(len > 8)
						sc.ScriptError("Border graphic can not be more than 8 characters long.\n");
					memcpy(graphics[i], sc.String, len);
					if(len < 8) // end with a null byte if the string is less than 8 chars.
						graphics[i][len] = 0;
				}
			}
		}
		else if(nextKey.CompareNoCase("armoricons") == 0)
		{
			sc.MustGetToken(TK_StringConst);
			strncpy(gameinfo.ArmorIcon1, sc.String, 8);
			gameinfo.ArmorIcon1[8] = 0;
			if (sc.CheckToken(','))
			{
				sc.MustGetToken(TK_FloatConst);
				gameinfo.Armor2Percent = FLOAT2FIXED(sc.Float);
				sc.MustGetToken(',');
				sc.MustGetToken(TK_StringConst);
				strncpy(gameinfo.ArmorIcon2, sc.String, 8);
				gameinfo.ArmorIcon2[8] = 0;
			}
		}
		else if(nextKey.CompareNoCase("maparrow") == 0)
		{
			sc.MustGetToken(TK_StringConst);
			gameinfo.mMapArrow = sc.String;
			if (sc.CheckToken(','))
			{
				sc.MustGetToken(TK_StringConst);
				gameinfo.mCheatMapArrow = sc.String;
			}
			else gameinfo.mCheatMapArrow = "";
		}
		// Insert valid keys here.
		GAMEINFOKEY_CSTRING(titlePage, "titlePage", 8)
		GAMEINFOKEY_STRINGARRAY(creditPages, "addcreditPage", 8, false)
		GAMEINFOKEY_STRINGARRAY(creditPages, "CreditPage", 8, true)
		GAMEINFOKEY_STRINGARRAY(PlayerClasses, "addplayerclasses", 0, false)
		GAMEINFOKEY_STRINGARRAY(PlayerClasses, "playerclasses", 0, true)
		GAMEINFOKEY_MUSIC(titleMusic, titleOrder, "titleMusic")
		GAMEINFOKEY_FLOAT(titleTime, "titleTime")
		GAMEINFOKEY_FLOAT(advisoryTime, "advisoryTime")
		GAMEINFOKEY_FLOAT(pageTime, "pageTime")
		GAMEINFOKEY_STRING(chatSound, "chatSound")
		GAMEINFOKEY_MUSIC(finaleMusic, finaleOrder, "finaleMusic")
		GAMEINFOKEY_CSTRING(finaleFlat, "finaleFlat", 8)
		GAMEINFOKEY_STRINGARRAY(finalePages, "finalePage", 8, true)
		GAMEINFOKEY_STRINGARRAY(infoPages, "addinfoPage", 8, false)
		GAMEINFOKEY_STRINGARRAY(infoPages, "infoPage", 8, true)
		GAMEINFOKEY_CSTRING(PauseSign, "pausesign", 8)
		GAMEINFOKEY_STRING(quitSound, "quitSound")
		GAMEINFOKEY_CSTRING(borderFlat, "borderFlat", 8)
		GAMEINFOKEY_FIXED(telefogheight, "telefogheight")
		GAMEINFOKEY_FIXED(gibfactor, "gibfactor")
		GAMEINFOKEY_INT(defKickback, "defKickback")
		GAMEINFOKEY_CSTRING(SkyFlatName, "SkyFlatName", 8)
		GAMEINFOKEY_STRING(translator, "translator")
		GAMEINFOKEY_COLOR(pickupcolor, "pickupcolor")
		GAMEINFOKEY_COLOR(defaultbloodcolor, "defaultbloodcolor")
		GAMEINFOKEY_COLOR(defaultbloodparticlecolor, "defaultbloodparticlecolor")
		GAMEINFOKEY_STRING(backpacktype, "backpacktype")
		GAMEINFOKEY_STRING(statusbar, "statusbar")
		GAMEINFOKEY_MUSIC(intermissionMusic, intermissionOrder, "intermissionMusic")
		GAMEINFOKEY_STRING(CursorPic, "CursorPic")
		GAMEINFOKEY_BOOL(noloopfinalemusic, "noloopfinalemusic")
		GAMEINFOKEY_BOOL(drawreadthis, "drawreadthis")
		GAMEINFOKEY_BOOL(swapmenu, "swapmenu")
		GAMEINFOKEY_BOOL(intermissioncounter, "intermissioncounter")
		GAMEINFOKEY_BOOL(nightmarefast, "nightmarefast")
		GAMEINFOKEY_COLOR(dimcolor, "dimcolor")
		GAMEINFOKEY_FLOAT(dimamount, "dimamount")
		GAMEINFOKEY_INT(definventorymaxamount, "definventorymaxamount")
		GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime")
		GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime")
		GAMEINFOKEY_INT(defaultdropstyle, "defaultdropstyle")
		GAMEINFOKEY_CSTRING(Endoom, "endoom", 8)
		GAMEINFOKEY_INT(player5start, "player5start")
		GAMEINFOKEY_STRINGARRAY(quitmessages, "addquitmessages", 0, false)
		GAMEINFOKEY_STRINGARRAY(quitmessages, "quitmessages", 0, true)
		GAMEINFOKEY_STRING(mTitleColor, "menufontcolor_title")
		GAMEINFOKEY_STRING(mFontColor, "menufontcolor_label")
		GAMEINFOKEY_STRING(mFontColorValue, "menufontcolor_value")
		GAMEINFOKEY_STRING(mFontColorMore, "menufontcolor_action")
		GAMEINFOKEY_STRING(mFontColorHeader, "menufontcolor_header")
		GAMEINFOKEY_STRING(mFontColorHighlight, "menufontcolor_highlight")
		GAMEINFOKEY_STRING(mFontColorSelection, "menufontcolor_selection")
		GAMEINFOKEY_CSTRING(mBackButton, "menubackbutton", 8)
		GAMEINFOKEY_INT(TextScreenX, "textscreenx")
		GAMEINFOKEY_INT(TextScreenY, "textscreeny")
		GAMEINFOKEY_STRING(DefaultEndSequence, "defaultendsequence")
		GAMEINFOKEY_FONT(mStatscreenMapNameFont, "statscreen_mapnamefont")
		GAMEINFOKEY_FONT(mStatscreenFinishedFont, "statscreen_finishedfont")
		GAMEINFOKEY_FONT(mStatscreenEnteringFont, "statscreen_enteringfont")
		GAMEINFOKEY_PATCH(mStatscreenFinishedFont, "statscreen_finishedpatch")
		GAMEINFOKEY_PATCH(mStatscreenEnteringFont, "statscreen_enteringpatch")
		GAMEINFOKEY_BOOL(norandomplayerclass, "norandomplayerclass")

		else
		{
			// ignore unkown keys.
			sc.UnGet();
			SkipToNext();
		}
	}
}
Пример #19
0
void FMapInfoParser::ParseSkill ()
{
	FSkillInfo skill;

	skill.AmmoFactor = FRACUNIT;
	skill.DoubleAmmoFactor = 2*FRACUNIT;
	skill.DropAmmoFactor = -1;
	skill.DamageFactor = FRACUNIT;
	skill.FastMonsters = false;
	skill.DisableCheats = false;
	skill.EasyBossBrain = false;
	skill.AutoUseHealth = false;
	skill.RespawnCounter = 0;
	skill.RespawnLimit = 0;
	skill.Aggressiveness = FRACUNIT;
	skill.SpawnFilter = 0;
	skill.ACSReturn = AllSkills.Size();
	skill.MenuNameIsLump = false;
	skill.MustConfirm = false;
	skill.Shortcut = 0;
	skill.TextColor = "";

	sc.MustGetString();
	skill.Name = sc.String;

	ParseOpenBrace();

	while (sc.GetString ())
	{
		if (sc.Compare ("ammofactor"))
		{
			ParseAssign();
			sc.MustGetFloat ();
			skill.AmmoFactor = FLOAT2FIXED(sc.Float);
		}
		else if (sc.Compare ("doubleammofactor"))
		{
			ParseAssign();
			sc.MustGetFloat ();
			skill.DoubleAmmoFactor = FLOAT2FIXED(sc.Float);
		}
		else if (sc.Compare ("dropammofactor"))
		{
			ParseAssign();
			sc.MustGetFloat ();
			skill.DropAmmoFactor = FLOAT2FIXED(sc.Float);
		}
		else if (sc.Compare ("damagefactor"))
		{
			ParseAssign();
			sc.MustGetFloat ();
			skill.DamageFactor = FLOAT2FIXED(sc.Float);
		}
		else if (sc.Compare ("fastmonsters"))
		{
			skill.FastMonsters = true;
		}
		else if (sc.Compare ("disablecheats"))
		{
			skill.DisableCheats = true;
		}
		else if (sc.Compare ("easybossbrain"))
		{
			skill.EasyBossBrain = true;
		}
		else if (sc.Compare("autousehealth"))
		{
			skill.AutoUseHealth = true;
		}
		else if (sc.Compare("respawntime"))
		{
			ParseAssign();
			sc.MustGetFloat ();
			skill.RespawnCounter = int(sc.Float*TICRATE);
		}
		else if (sc.Compare("respawnlimit"))
		{
			ParseAssign();
			sc.MustGetNumber ();
			skill.RespawnLimit = sc.Number;
		}
		else if (sc.Compare("Aggressiveness"))
		{
			ParseAssign();
			sc.MustGetFloat ();
			skill.Aggressiveness = FRACUNIT - FLOAT2FIXED(clamp(sc.Float, 0.,1.));
		}
		else if (sc.Compare("SpawnFilter"))
		{
			ParseAssign();
			if (sc.CheckNumber())
			{
				if (sc.Number > 0) skill.SpawnFilter |= (1<<(sc.Number-1));
			}
			else
			{
				sc.MustGetString ();
				if (sc.Compare("baby")) skill.SpawnFilter |= 1;
				else if (sc.Compare("easy")) skill.SpawnFilter |= 2;
				else if (sc.Compare("normal")) skill.SpawnFilter |= 4;
				else if (sc.Compare("hard")) skill.SpawnFilter |= 8;
				else if (sc.Compare("nightmare")) skill.SpawnFilter |= 16;
			}
		}
		else if (sc.Compare("ACSReturn"))
		{
			ParseAssign();
			sc.MustGetNumber ();
			skill.ACSReturn = sc.Number;
		}
		else if (sc.Compare("Name"))
		{
			ParseAssign();
			sc.MustGetString ();
			skill.MenuName = sc.String;
			skill.MenuNameIsLump = false;
		}
		else if (sc.Compare("PlayerClassName"))
		{
			ParseAssign();
			sc.MustGetString ();
			FName pc = sc.String;
			ParseComma();
			sc.MustGetString ();
			skill.MenuNamesForPlayerClass[pc]=sc.String;
		}
		else if (sc.Compare("PicName"))
		{
			ParseAssign();
			sc.MustGetString ();
			skill.MenuName = sc.String;
			skill.MenuNameIsLump = true;
		}
		else if (sc.Compare("MustConfirm"))
		{
			skill.MustConfirm = true;
			if (format_type == FMT_New) 
			{
				if (CheckAssign())
				{
					sc.MustGetString();
					skill.MustConfirmText = sc.String;
				}
			}
			else
			{
				if (sc.CheckToken(TK_StringConst))
				{
					skill.MustConfirmText = sc.String;
				}
			}
		}
		else if (sc.Compare("Key"))
		{
			ParseAssign();
			sc.MustGetString();
			skill.Shortcut = tolower(sc.String[0]);
		}
		else if (sc.Compare("TextColor"))
		{
			ParseAssign();
			sc.MustGetString();
			skill.TextColor.Format("[%s]", sc.String);
		}
		else if (!ParseCloseBrace())
		{
			// Unknown
			sc.ScriptMessage("Unknown property '%s' found in skill definition\n", sc.String);
			SkipToNext();
		}
		else
		{
			break;
		}
	}
	CheckEndOfFile("skill");
	for(unsigned int i = 0; i < AllSkills.Size(); i++)
	{
		if (AllSkills[i].Name == skill.Name)
		{
			AllSkills[i] = skill;
			return;
		}
	}
	AllSkills.Push(skill);
}
Пример #20
0
 void SetOffset(float* ft) { m_X = FLOAT2FIXED(ft[0]); m_Y = FLOAT2FIXED(ft[1]); m_Z = FLOAT2FIXED(ft[2]); }
Пример #21
0
void ParseCompatibility()
{
	TArray<FMD5Holder> md5array;
	FMD5Holder md5;
	FCompatValues flags;
	int i, x;
	unsigned int j;

	BCompatMap.Clear();
	CompatParams.Clear();

	// The contents of this file are not cumulative, as it should not
	// be present in user-distributed maps.
	FScanner sc(Wads.GetNumForFullName("compatibility.txt"));

	while (sc.GetString())	// Get MD5 signature
	{
		do
		{
			if (strlen(sc.String) != 32)
			{
				sc.ScriptError("MD5 signature must be exactly 32 characters long");
			}
			for (i = 0; i < 32; ++i)
			{
				if (sc.String[i] >= '0' && sc.String[i] <= '9')
				{
					x = sc.String[i] - '0';
				}
				else
				{
					sc.String[i] |= 'a' ^ 'A';
					if (sc.String[i] >= 'a' && sc.String[i] <= 'f')
					{
						x = sc.String[i] - 'a' + 10;
					}
					else
					{
						x = 0;
						sc.ScriptError("MD5 signature must be a hexadecimal value");
					}
				}
				if (!(i & 1))
				{
					md5.Bytes[i / 2] = x << 4;
				}
				else
				{
					md5.Bytes[i / 2] |= x;
				}
			}
			md5array.Push(md5);
			sc.MustGetString();
		} while (!sc.Compare("{"));
		memset(flags.CompatFlags, 0, sizeof(flags.CompatFlags));
		flags.ExtCommandIndex = ~0u;
		while (sc.GetString())
		{
			if ((i = sc.MatchString(&Options[0].Name, sizeof(*Options))) >= 0)
			{
				flags.CompatFlags[Options[i].WhichSlot] |= Options[i].CompatFlags;
			}
			else if (sc.Compare("clearlineflags"))
			{
				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
				CompatParams.Push(CP_CLEARFLAGS);
				sc.MustGetNumber();
				CompatParams.Push(sc.Number);
				sc.MustGetNumber();
				CompatParams.Push(sc.Number);
			}
			else if (sc.Compare("setlineflags"))
			{
				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
				CompatParams.Push(CP_SETFLAGS);
				sc.MustGetNumber();
				CompatParams.Push(sc.Number);
				sc.MustGetNumber();
				CompatParams.Push(sc.Number);
			}
			else if (sc.Compare("setlinespecial"))
			{
				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
				CompatParams.Push(CP_SETSPECIAL);
				sc.MustGetNumber();
				CompatParams.Push(sc.Number);

				sc.MustGetString();
				CompatParams.Push(P_FindLineSpecial(sc.String, NULL, NULL));
				for (int i = 0; i < 5; i++)
				{
					sc.MustGetNumber();
					CompatParams.Push(sc.Number);
				}
			}
			else if (sc.Compare("clearlinespecial"))
			{
				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
				CompatParams.Push(CP_CLEARSPECIAL);
				sc.MustGetNumber();
				CompatParams.Push(sc.Number);
			}
			else if (sc.Compare("setactivation"))
			{
				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
				CompatParams.Push(CP_SETACTIVATION);
				sc.MustGetNumber();
				CompatParams.Push(sc.Number);
				sc.MustGetNumber();
				CompatParams.Push(sc.Number);
			}
			else if (sc.Compare("sectorflooroffset"))
			{
				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
				CompatParams.Push(CP_SECTORFLOOROFFSET);
				sc.MustGetNumber();
				CompatParams.Push(sc.Number);
				sc.MustGetFloat();
				CompatParams.Push(FLOAT2FIXED(sc.Float));
			}
			else if (sc.Compare("setwallyscale"))
			{
				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
				CompatParams.Push(CP_SETWALLYSCALE);
				sc.MustGetNumber();
				CompatParams.Push(sc.Number);
				sc.MustGetString();
				CompatParams.Push(sc.MustMatchString(LineSides));
				sc.MustGetString();
				CompatParams.Push(sc.MustMatchString(WallTiers));
				sc.MustGetFloat();
				CompatParams.Push(FLOAT2FIXED(sc.Float));
			}
			else if (sc.Compare("setthingz"))
			{
				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
				CompatParams.Push(CP_SETTHINGZ);
				sc.MustGetNumber();
				CompatParams.Push(sc.Number);
				sc.MustGetFloat();
				CompatParams.Push(FLOAT2FIXED(sc.Float));
			}
			else if (sc.Compare("setsectortag"))
			{
				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
				CompatParams.Push(CP_SETTAG);
				sc.MustGetNumber();
				CompatParams.Push(sc.Number);
				sc.MustGetNumber();
				CompatParams.Push(sc.Number);
			}
			else if (sc.Compare("setthingflags"))
			{
				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
				CompatParams.Push(CP_SETTHINGFLAGS);
				sc.MustGetNumber();
				CompatParams.Push(sc.Number);
				sc.MustGetNumber();
				CompatParams.Push(sc.Number);
			}
			else 
			{
				sc.UnGet();
				break;
			}
		}
		if (flags.ExtCommandIndex != ~0u) 
		{
			CompatParams.Push(CP_END);
		}
		sc.MustGetStringName("}");
		for (j = 0; j < md5array.Size(); ++j)
		{
			BCompatMap[md5array[j]] = flags;
		}
		md5array.Clear();
	}
}
Пример #22
0
void R_SetView()
{
	viewx = FLOAT2FIXED(ViewPos.X);
	viewy = FLOAT2FIXED(ViewPos.Y);
}
Пример #23
0
	VisiblePlane *VisiblePlaneList::FindPlane(const secplane_t &height, FTextureID picnum, int lightlevel, double Alpha, bool additive, const FTransform &xxform, int sky, FSectorPortal *portal, FDynamicColormap *basecolormap, Fake3DOpaque::Type fakeFloorType, fixed_t fakeAlpha)
	{
		secplane_t plane;
		VisiblePlane *check;
		unsigned hash;						// killough
		bool isskybox;
		const FTransform *xform = &xxform;
		fixed_t alpha = FLOAT2FIXED(Alpha);
		//angle_t angle = (xform.Angle + xform.baseAngle).BAMs();

		FTransform nulltransform;

		RenderPortal *renderportal = Thread->Portal.get();

		if (picnum == skyflatnum)	// killough 10/98
		{ // most skies map together
			lightlevel = 0;
			xform = &nulltransform;
			nulltransform.xOffs = nulltransform.yOffs = nulltransform.baseyOffs = 0;
			nulltransform.xScale = nulltransform.yScale = 1;
			nulltransform.Angle = nulltransform.baseAngle = 0.0;
			additive = false;
			// [RH] Map floor skies and ceiling skies to separate visplanes. This isn't
			// always necessary, but it is needed if a floor and ceiling sky are in the
			// same column but separated by a wall. If they both try to reside in the
			// same visplane, then only the floor sky will be drawn.
			plane.set(0., 0., height.fC(), 0.);
			isskybox = portal != nullptr && !renderportal->InSkyBox(portal);
		}
		else if (portal != nullptr && !renderportal->InSkyBox(portal))
		{
			plane = height;
			isskybox = true;
		}
		else
		{
			plane = height;
			isskybox = false;
			// kg3D - hack, store alpha in sky
			// i know there is ->alpha, but this also allows to identify fake plane
			// and ->alpha is for stacked sectors
			if (fakeFloorType == Fake3DOpaque::FakeFloor || fakeFloorType == Fake3DOpaque::FakeCeiling) sky = 0x80000000 | fakeAlpha;
			else sky = 0;	// not skyflatnum so it can't be a sky
			portal = nullptr;
			alpha = OPAQUE;
		}

		// New visplane algorithm uses hash table -- killough
		hash = isskybox ? ((unsigned)MAXVISPLANES) : CalcHash(picnum.GetIndex(), lightlevel, height);
		
		for (check = visplanes[hash]; check; check = check->next)	// killough
		{
			if (isskybox)
			{
				if (portal == check->portal && plane == check->height)
				{
					if (portal->mType != PORTS_SKYVIEWPOINT)
					{ // This skybox is really a stacked sector, so we need to
					  // check even more.
						if (check->extralight == renderportal->stacked_extralight &&
							check->visibility == renderportal->stacked_visibility &&
							check->viewpos == renderportal->stacked_viewpos &&
							(
								// headache inducing logic... :(
								(portal->mType != PORTS_STACKEDSECTORTHING) ||
								(
									check->Alpha == alpha &&
									check->Additive == additive &&
									(alpha == 0 ||	// if alpha is > 0 everything needs to be checked
									(plane == check->height &&
										picnum == check->picnum &&
										lightlevel == check->lightlevel &&
										basecolormap == check->colormap &&	// [RH] Add more checks
										*xform == check->xform
										)
										) &&
									check->viewangle == renderportal->stacked_angle.Yaw
									)
								)
							)
						{
							return check;
						}
					}
					else
					{
						return check;
					}
				}
			}
			else
				if (plane == check->height &&
					picnum == check->picnum &&
					lightlevel == check->lightlevel &&
					basecolormap == check->colormap &&	// [RH] Add more checks
					*xform == check->xform &&
					sky == check->sky &&
					renderportal->CurrentPortalUniq == check->CurrentPortalUniq &&
					renderportal->MirrorFlags == check->MirrorFlags &&
					Thread->Clip3D->CurrentSkybox == check->CurrentSkybox &&
					Thread->Viewport->viewpoint.Pos == check->viewpos
					)
				{
					return check;
				}
		}

		check = Add(hash);		// killough

		check->height = plane;
		check->picnum = picnum;
		check->lightlevel = lightlevel;
		check->xform = *xform;
		check->colormap = basecolormap;		// [RH] Save colormap
		check->sky = sky;
		check->portal = portal;
		check->extralight = renderportal->stacked_extralight;
		check->visibility = renderportal->stacked_visibility;
		check->viewpos = renderportal->stacked_viewpos;
		check->viewangle = renderportal->stacked_angle.Yaw;
		check->Alpha = alpha;
		check->Additive = additive;
		check->CurrentPortalUniq = renderportal->CurrentPortalUniq;
		check->MirrorFlags = renderportal->MirrorFlags;
		check->CurrentSkybox = Thread->Clip3D->CurrentSkybox;

		return check;
	}
Пример #24
0
int PolyCull::PointOnSide(const DVector2 &pos, const node_t *node)
{
	return DMulScale32(FLOAT2FIXED(pos.Y) - node->y, node->dx, node->x - FLOAT2FIXED(pos.X), node->dy) > 0;
}
Пример #25
0
void FMapInfoParser::ParseSkill ()
{
	FSkillInfo skill;
	bool thisisdefault = false;
	bool acsreturnisset = false;

	skill.AmmoFactor = FRACUNIT;
	skill.DoubleAmmoFactor = 2*FRACUNIT;
	skill.DropAmmoFactor = -1;
	skill.DamageFactor = FRACUNIT;
	skill.FastMonsters = false;
	skill.SlowMonsters = false;
	skill.DisableCheats = false;
	skill.EasyBossBrain = false;
	skill.EasyKey = false;
	skill.AutoUseHealth = false;
	skill.RespawnCounter = 0;
	skill.RespawnLimit = 0;
	skill.Aggressiveness = FRACUNIT;
	skill.SpawnFilter = 0;
	skill.ACSReturn = 0;
	skill.MustConfirm = false;
	skill.Shortcut = 0;
	skill.TextColor = "";
	skill.Replace.Clear();
	skill.Replaced.Clear();
	skill.MonsterHealth = FRACUNIT;
	skill.FriendlyHealth = FRACUNIT;
	skill.NoPain = false;
	skill.ArmorFactor = FRACUNIT;
	skill.Infighting = 0;
	skill.HealthFactor = FRACUNIT;

	sc.MustGetString();
	skill.Name = sc.String;

	ParseOpenBrace();

	while (sc.GetString ())
	{
		if (sc.Compare ("ammofactor"))
		{
			ParseAssign();
			sc.MustGetFloat ();
			skill.AmmoFactor = FLOAT2FIXED(sc.Float);
		}
		else if (sc.Compare ("doubleammofactor"))
		{
			ParseAssign();
			sc.MustGetFloat ();
			skill.DoubleAmmoFactor = FLOAT2FIXED(sc.Float);
		}
		else if (sc.Compare ("dropammofactor"))
		{
			ParseAssign();
			sc.MustGetFloat ();
			skill.DropAmmoFactor = FLOAT2FIXED(sc.Float);
		}
		else if (sc.Compare ("damagefactor"))
		{
			ParseAssign();
			sc.MustGetFloat ();
			skill.DamageFactor = FLOAT2FIXED(sc.Float);
		}
		else if (sc.Compare ("fastmonsters"))
		{
			skill.FastMonsters = true;
		}
		else if (sc.Compare ("slowmonsters"))
		{
			skill.SlowMonsters = true;
		}
		else if (sc.Compare ("disablecheats"))
		{
			skill.DisableCheats = true;
		}
		else if (sc.Compare ("easybossbrain"))
		{
			skill.EasyBossBrain = true;
		}
		else if (sc.Compare ("easykey"))
		{
			skill.EasyKey = true;
		}
		else if (sc.Compare("autousehealth"))
		{
			skill.AutoUseHealth = true;
		}
		else if (sc.Compare("respawntime"))
		{
			ParseAssign();
			sc.MustGetFloat ();
			skill.RespawnCounter = int(sc.Float*TICRATE);
		}
		else if (sc.Compare("respawnlimit"))
		{
			ParseAssign();
			sc.MustGetNumber ();
			skill.RespawnLimit = sc.Number;
		}
		else if (sc.Compare("Aggressiveness"))
		{
			ParseAssign();
			sc.MustGetFloat ();
			skill.Aggressiveness = FRACUNIT - FLOAT2FIXED(clamp(sc.Float, 0.,1.));
		}
		else if (sc.Compare("SpawnFilter"))
		{
			ParseAssign();
			if (sc.CheckNumber())
			{
				if (sc.Number > 0) skill.SpawnFilter |= (1<<(sc.Number-1));
			}
			else
			{
				sc.MustGetString ();
				if (sc.Compare("baby")) skill.SpawnFilter |= 1;
				else if (sc.Compare("easy")) skill.SpawnFilter |= 2;
				else if (sc.Compare("normal")) skill.SpawnFilter |= 4;
				else if (sc.Compare("hard")) skill.SpawnFilter |= 8;
				else if (sc.Compare("nightmare")) skill.SpawnFilter |= 16;
			}
		}
		else if (sc.Compare("ACSReturn"))
		{
			ParseAssign();
			sc.MustGetNumber ();
			skill.ACSReturn = sc.Number;
			acsreturnisset = true;
		}
		else if (sc.Compare("ReplaceActor"))
		{
			ParseAssign();
			sc.MustGetString();
			FName replaced = sc.String;
			ParseComma();
			sc.MustGetString();
			FName replacer = sc.String;
			skill.SetReplacement(replaced, replacer);
			skill.SetReplacedBy(replacer, replaced);
		}
		else if (sc.Compare("Name"))
		{
			ParseAssign();
			sc.MustGetString ();
			skill.MenuName = sc.String;
		}
		else if (sc.Compare("PlayerClassName"))
		{
			ParseAssign();
			sc.MustGetString ();
			FName pc = sc.String;
			ParseComma();
			sc.MustGetString ();
			skill.MenuNamesForPlayerClass[pc]=sc.String;
		}
		else if (sc.Compare("PicName"))
		{
			ParseAssign();
			sc.MustGetString ();
			skill.PicName = sc.String;
		}
		else if (sc.Compare("MustConfirm"))
		{
			skill.MustConfirm = true;
			if (format_type == FMT_New) 
			{
				if (CheckAssign())
				{
					sc.MustGetString();
					skill.MustConfirmText = sc.String;
				}
			}
			else
			{
				if (sc.CheckToken(TK_StringConst))
				{
					skill.MustConfirmText = sc.String;
				}
			}
		}
		else if (sc.Compare("Key"))
		{
			ParseAssign();
			sc.MustGetString();
			skill.Shortcut = tolower(sc.String[0]);
		}
		else if (sc.Compare("TextColor"))
		{
			ParseAssign();
			sc.MustGetString();
			skill.TextColor.Format("[%s]", sc.String);
		}
		else if (sc.Compare("MonsterHealth"))
		{
			ParseAssign();
			sc.MustGetFloat();
			skill.MonsterHealth = FLOAT2FIXED(sc.Float);				
		}
		else if (sc.Compare("FriendlyHealth"))
		{
			ParseAssign();
			sc.MustGetFloat();
			skill.FriendlyHealth = FLOAT2FIXED(sc.Float);
		}
		else if (sc.Compare("NoPain"))
		{
			skill.NoPain = true;
		}
		else if (sc.Compare("ArmorFactor"))
		{
			ParseAssign();
			sc.MustGetFloat();
			skill.ArmorFactor = FLOAT2FIXED(sc.Float);
		}
		else if (sc.Compare("HealthFactor"))
		{
			ParseAssign();
			sc.MustGetFloat();
			skill.HealthFactor = FLOAT2FIXED(sc.Float);
		}
		else if (sc.Compare("NoInfighting"))
		{
			skill.Infighting = LEVEL2_NOINFIGHTING;
		}
		else if (sc.Compare("TotalInfighting"))
		{
			skill.Infighting = LEVEL2_TOTALINFIGHTING;
		}
		else if (sc.Compare("DefaultSkill"))
		{
			if (DefaultSkill >= 0)
			{
				sc.ScriptError("%s is already the default skill\n", AllSkills[DefaultSkill].Name.GetChars());
			}
			thisisdefault = true;
		}
		else if (!ParseCloseBrace())
		{
			// Unknown
			sc.ScriptMessage("Unknown property '%s' found in skill definition\n", sc.String);
			SkipToNext();
		}
		else
		{
			break;
		}
	}
	CheckEndOfFile("skill");
	for(unsigned int i = 0; i < AllSkills.Size(); i++)
	{
		if (AllSkills[i].Name == skill.Name)
		{
			if (!acsreturnisset)
			{ // Use the ACS return for the skill we are overwriting.
				skill.ACSReturn = AllSkills[i].ACSReturn;
			}
			AllSkills[i] = skill;
			if (thisisdefault)
			{
				DefaultSkill = i;
			}
			return;
		}
	}
	if (!acsreturnisset)
	{
		skill.ACSReturn = AllSkills.Size();
	}
	if (thisisdefault)
	{
		DefaultSkill = AllSkills.Size();
	}
	AllSkills.Push(skill);
}
Пример #26
0
visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightlevel, double Alpha, bool additive,
						const FTransform &xxform,
						 int sky, FSectorPortal *portal)
{
	secplane_t plane;
	visplane_t *check;
	unsigned hash;						// killough
	bool isskybox;
	const FTransform *xform = &xxform;
	fixed_t alpha = FLOAT2FIXED(Alpha);
	//angle_t angle = (xform.Angle + xform.baseAngle).BAMs();

	FTransform nulltransform;

	if (picnum == skyflatnum)	// killough 10/98
	{ // most skies map together
		lightlevel = 0;
		xform = &nulltransform;
		nulltransform.xOffs = nulltransform.yOffs = nulltransform.baseyOffs = 0;
		nulltransform.xScale = nulltransform.yScale = 1;
		nulltransform.Angle = nulltransform.baseAngle = 0.0;
		additive = false;
		// [RH] Map floor skies and ceiling skies to separate visplanes. This isn't
		// always necessary, but it is needed if a floor and ceiling sky are in the
		// same column but separated by a wall. If they both try to reside in the
		// same visplane, then only the floor sky will be drawn.
		plane.set(0., 0., height.fC(), 0.);
		isskybox = portal != NULL && !(portal->mFlags & PORTSF_INSKYBOX);
	}
	else if (portal != NULL && !(portal->mFlags & PORTSF_INSKYBOX))
	{
		plane = height;
		isskybox = true;
	}
	else
	{
		plane = height;
		isskybox = false;
		// kg3D - hack, store alpha in sky
		// i know there is ->alpha, but this also allows to identify fake plane
		// and ->alpha is for stacked sectors
		if (fake3D & (FAKE3D_FAKEFLOOR|FAKE3D_FAKECEILING)) sky = 0x80000000 | fakeAlpha;
		else sky = 0;	// not skyflatnum so it can't be a sky
		portal = NULL;
		alpha = OPAQUE;
	}

	// New visplane algorithm uses hash table -- killough
	hash = isskybox ? MAXVISPLANES : visplane_hash (picnum.GetIndex(), lightlevel, height);

	for (check = visplanes[hash]; check; check = check->next)	// killough
	{
		if (isskybox)
		{
			if (portal == check->portal && plane == check->height)
			{
				if (portal->mType != PORTS_SKYVIEWPOINT)
				{ // This skybox is really a stacked sector, so we need to
				  // check even more.
					if (check->extralight == stacked_extralight &&
						check->visibility == stacked_visibility &&
						check->viewpos == stacked_viewpos &&
						(
							// headache inducing logic... :(
							(portal->mType != PORTS_STACKEDSECTORTHING) ||
							(
								check->Alpha == alpha &&
								check->Additive == additive &&
								(alpha == 0 ||	// if alpha is > 0 everything needs to be checked
									(plane == check->height &&
									 picnum == check->picnum &&
									 lightlevel == check->lightlevel &&
									 basecolormap == check->colormap &&	// [RH] Add more checks
									 *xform == check->xform
									)
								) &&
								check->viewangle == stacked_angle
							)
						)
					   )
					{
						return check;
					}
				}
				else
				{
					return check;
				}
			}
		}
		else
		if (plane == check->height &&
			picnum == check->picnum &&
			lightlevel == check->lightlevel &&
			basecolormap == check->colormap &&	// [RH] Add more checks
			*xform == check->xform &&
			sky == check->sky &&
			CurrentPortalUniq == check->CurrentPortalUniq &&
			MirrorFlags == check->MirrorFlags &&
			CurrentSkybox == check->CurrentSkybox &&
			ViewPos == check->viewpos
			)
		{
		  return check;
		}
	}

	check = new_visplane (hash);		// killough

	check->height = plane;
	check->picnum = picnum;
	check->lightlevel = lightlevel;
	check->xform = *xform;
	check->colormap = basecolormap;		// [RH] Save colormap
	check->sky = sky;
	check->portal = portal;
	check->left = viewwidth;			// Was SCREENWIDTH -- killough 11/98
	check->right = 0;
	check->extralight = stacked_extralight;
	check->visibility = stacked_visibility;
	check->viewpos = stacked_viewpos;
	check->viewangle = stacked_angle;
	check->Alpha = alpha;
	check->Additive = additive;
	check->CurrentPortalUniq = CurrentPortalUniq;
	check->MirrorFlags = MirrorFlags;
	check->CurrentSkybox = CurrentSkybox;

	fillshort (check->top, viewwidth, 0x7fff);

	return check;
}
Пример #27
0
void R_InitSkins (void)
{
	FSoundID playersoundrefs[NUMSKINSOUNDS];
	spritedef_t temp;
	int sndlumps[NUMSKINSOUNDS];
	char key[65];
	DWORD intname, crouchname;
	size_t i;
	int j, k, base;
	int lastlump;
	int aliasid;
	bool remove;
	const PClass *basetype, *transtype;

	key[sizeof(key)-1] = 0;
	i = PlayerClasses.Size () - 1;
	lastlump = 0;

	for (j = 0; j < NUMSKINSOUNDS; ++j)
	{
		playersoundrefs[j] = skinsoundnames[j][1];
	}

	while ((base = Wads.FindLump ("S_SKIN", &lastlump, true)) != -1)
	{
		// The player sprite has 23 frames. This means that the S_SKIN
		// marker needs a minimum of 23 lumps after it.
		if (base >= Wads.GetNumLumps() - 23 || base == -1)
			continue;

		i++;
		for (j = 0; j < NUMSKINSOUNDS; j++)
			sndlumps[j] = -1;
		skins[i].namespc = Wads.GetLumpNamespace (base);

		FScanner sc(base);
		intname = 0;
		crouchname = 0;

		remove = false;
		basetype = NULL;
		transtype = NULL;

		// Data is stored as "key = data".
		while (sc.GetString ())
		{
			strncpy (key, sc.String, sizeof(key)-1);
			if (!sc.GetString() || sc.String[0] != '=')
			{
				Printf (PRINT_BOLD, "Bad format for skin %d: %s\n", (int)i, key);
				break;
			}
			sc.GetString ();
			if (0 == stricmp (key, "name"))
			{
				strncpy (skins[i].name, sc.String, 16);
				for (j = 0; (size_t)j < i; j++)
				{
					if (stricmp (skins[i].name, skins[j].name) == 0)
					{
						mysnprintf (skins[i].name, countof(skins[i].name), "skin%d", (int)i);
						Printf (PRINT_BOLD, "Skin %s duplicated as %s\n",
							skins[j].name, skins[i].name);
						break;
					}
				}
			}
			else if (0 == stricmp (key, "sprite"))
			{
				for (j = 3; j >= 0; j--)
					sc.String[j] = toupper (sc.String[j]);
				intname = *((DWORD *)sc.String);
			}
			else if (0 == stricmp (key, "crouchsprite"))
			{
				for (j = 3; j >= 0; j--)
					sc.String[j] = toupper (sc.String[j]);
				crouchname = *((DWORD *)sc.String);
			}
			else if (0 == stricmp (key, "face"))
			{
				for (j = 2; j >= 0; j--)
					skins[i].face[j] = toupper (sc.String[j]);
				skins[i].face[3] = '\0';
			}
			else if (0 == stricmp (key, "gender"))
			{
				skins[i].gender = D_GenderToInt (sc.String);
			}
			else if (0 == stricmp (key, "scale"))
			{
				skins[i].ScaleX = clamp<fixed_t> (FLOAT2FIXED(atof (sc.String)), 1, 256*FRACUNIT);
				skins[i].ScaleY = skins[i].ScaleX;
			}
			else if (0 == stricmp (key, "game"))
			{
				if (gameinfo.gametype == GAME_Heretic)
					basetype = PClass::FindClass (NAME_HereticPlayer);
				else if (gameinfo.gametype == GAME_Strife)
					basetype = PClass::FindClass (NAME_StrifePlayer);
				else
					basetype = PClass::FindClass (NAME_DoomPlayer);

				transtype = basetype;

				if (stricmp (sc.String, "heretic") == 0)
				{
					if (gameinfo.gametype & GAME_DoomChex)
					{
						transtype = PClass::FindClass (NAME_HereticPlayer);
						skins[i].othergame = true;
					}
					else if (gameinfo.gametype != GAME_Heretic)
					{
						remove = true;
					}
				}
				else if (stricmp (sc.String, "strife") == 0)
				{
					if (gameinfo.gametype != GAME_Strife)
					{
						remove = true;
					}
				}
				else
				{
					if (gameinfo.gametype == GAME_Heretic)
					{
						transtype = PClass::FindClass (NAME_DoomPlayer);
						skins[i].othergame = true;
					}
					else if (!(gameinfo.gametype & GAME_DoomChex))
					{
						remove = true;
					}
				}

				if (remove)
					break;
			}
			else if (0 == stricmp (key, "class"))
			{ // [GRB] Define the skin for a specific player class
				int pclass = D_PlayerClassToInt (sc.String);

				if (pclass < 0)
				{
					remove = true;
					break;
				}

				basetype = transtype = PlayerClasses[pclass].Type;
			}
			else if (key[0] == '*')
			{ // Player sound replacment (ZDoom extension)
				int lump = Wads.CheckNumForName (sc.String, skins[i].namespc);
				if (lump == -1)
				{
					lump = Wads.CheckNumForFullName (sc.String, true, ns_sounds);
				}
				if (lump != -1)
				{
					if (stricmp (key, "*pain") == 0)
					{ // Replace all pain sounds in one go
						aliasid = S_AddPlayerSound (skins[i].name, skins[i].gender,
							playersoundrefs[0], lump, true);
						for (int l = 3; l > 0; --l)
						{
							S_AddPlayerSoundExisting (skins[i].name, skins[i].gender,
								playersoundrefs[l], aliasid, true);
						}
					}
					else
					{
						int sndref = S_FindSoundNoHash (key);
						if (sndref != 0)
						{
							S_AddPlayerSound (skins[i].name, skins[i].gender, sndref, lump, true);
						}
					}
				}
			}
			else
			{
				for (j = 0; j < NUMSKINSOUNDS; j++)
				{
					if (stricmp (key, skinsoundnames[j][0]) == 0)
					{
						sndlumps[j] = Wads.CheckNumForName (sc.String, skins[i].namespc);
						if (sndlumps[j] == -1)
						{ // Replacement not found, try finding it in the global namespace
							sndlumps[j] = Wads.CheckNumForFullName (sc.String, true, ns_sounds);
						}
					}
				}
				//if (j == 8)
				//	Printf ("Funny info for skin %i: %s = %s\n", i, key, sc.String);
			}
		}

		// [GRB] Assume Doom skin by default
		if (!remove && basetype == NULL)
		{
			if (gameinfo.gametype & GAME_DoomChex)
			{
				basetype = transtype = PClass::FindClass (NAME_DoomPlayer);
			}
			else if (gameinfo.gametype == GAME_Heretic)
			{
				basetype = PClass::FindClass (NAME_HereticPlayer);
				transtype = PClass::FindClass (NAME_DoomPlayer);
				skins[i].othergame = true;
			}
			else
			{
				remove = true;
			}
		}

		if (!remove)
		{
			skins[i].range0start = transtype->Meta.GetMetaInt (APMETA_ColorRange) & 0xff;
			skins[i].range0end = transtype->Meta.GetMetaInt (APMETA_ColorRange) >> 8;

			remove = true;
			for (j = 0; j < (int)PlayerClasses.Size (); j++)
			{
				const PClass *type = PlayerClasses[j].Type;

				if (type->IsDescendantOf (basetype) &&
					GetDefaultByType (type)->SpawnState->sprite == GetDefaultByType (basetype)->SpawnState->sprite &&
					type->Meta.GetMetaInt (APMETA_ColorRange) == basetype->Meta.GetMetaInt (APMETA_ColorRange))
				{
					PlayerClasses[j].Skins.Push ((int)i);
					remove = false;
				}
			}
		}

		if (!remove)
		{
			if (skins[i].name[0] == 0)
				mysnprintf (skins[i].name, countof(skins[i].name), "skin%d", (int)i);

			// Now collect the sprite frames for this skin. If the sprite name was not
			// specified, use whatever immediately follows the specifier lump.
			if (intname == 0)
			{
				char name[9];
				Wads.GetLumpName (name, base+1);
				memcpy(&intname, name, 4);
			}

			int basens = Wads.GetLumpNamespace(base);

			for(int spr = 0; spr<2; spr++)
			{
				memset (sprtemp, 0xFFFF, sizeof(sprtemp));
				for (k = 0; k < MAX_SPRITE_FRAMES; ++k)
				{
					sprtemp[k].Flip = 0;
					sprtemp[k].Voxel = NULL;
				}
				maxframe = -1;

				if (spr == 1)
				{
					if (crouchname !=0 && crouchname != intname)
					{
						intname = crouchname;
					}
					else
					{
						skins[i].crouchsprite = -1;
						break;
					}
				}

				for (k = base + 1; Wads.GetLumpNamespace(k) == basens; k++)
				{
					char lname[9];
					DWORD lnameint;
					Wads.GetLumpName (lname, k);
					memcpy(&lnameint, lname, 4);
					if (lnameint == intname)
					{
						FTextureID picnum = TexMan.CreateTexture(k, FTexture::TEX_SkinSprite);
						bool res = R_InstallSpriteLump (picnum, lname[4] - 'A', lname[5], false);

						if (lname[6] && res)
							R_InstallSpriteLump (picnum, lname[6] - 'A', lname[7], true);
					}
				}

				if (spr == 0 && maxframe <= 0)
				{
					Printf (PRINT_BOLD, "Skin %s (#%d) has no frames. Removing.\n", skins[i].name, (int)i);
					remove = true;
					break;
				}

				Wads.GetLumpName (temp.name, base+1);
				temp.name[4] = 0;
				int sprno = (int)sprites.Push (temp);
				if (spr==0)	skins[i].sprite = sprno;
				else skins[i].crouchsprite = sprno;
				R_InstallSprite (sprno);
			}
		}

		if (remove)
		{
			if (i < numskins-1)
				memmove (&skins[i], &skins[i+1], sizeof(skins[0])*(numskins-i-1));
			i--;
			continue;
		}

		// Register any sounds this skin provides
		aliasid = 0;
		for (j = 0; j < NUMSKINSOUNDS; j++)
		{
			if (sndlumps[j] != -1)
			{
				if (j == 0 || sndlumps[j] != sndlumps[j-1])
				{
					aliasid = S_AddPlayerSound (skins[i].name, skins[i].gender,
						playersoundrefs[j], sndlumps[j], true);
				}
				else
				{
					S_AddPlayerSoundExisting (skins[i].name, skins[i].gender,
						playersoundrefs[j], aliasid, true);
				}
			}
		}

		// Make sure face prefix is a full 3 chars
		if (skins[i].face[1] == 0 || skins[i].face[2] == 0)
		{
			skins[i].face[0] = 0;
		}
	}
Пример #28
0
void Stereo3D::render(FGLRenderer& renderer, GL_IRECT * bounds, float fov0, float ratio0, float fovratio0, bool toscreen, sector_t * viewsector, player_t * player) 
{
	if (doBufferHud)
		LocalHudRenderer::unbind();

	// Reset pitch and roll when leaving Rift mode
	if ( (mode == OCULUS_RIFT) && ((int)mode != vr_mode) ) {
		renderer.mAngles.Roll = 0;
		renderer.mAngles.Pitch = 0;
	}
	setMode(vr_mode);

	// Restore actual screen, instead of offscreen single-eye buffer,
	// in case we just exited Rift mode.
	adaptScreenSize = false;

	GLboolean supportsStereo = false;
	GLboolean supportsBuffered = false;
	// Task: manually calibrate oculusFov by slowly yawing view. 
	// If subjects approach center of view too fast, oculusFov is too small.
	// If subjects approach center of view too slowly, oculusFov is too large.
	// If subjects approach correctly , oculusFov is just right.
	// 90 is too large, 80 is too small.
	// float oculusFov = 85 * fovratio; // Hard code probably wider fov for oculus // use vr_rift_fov

	if (mode == OCULUS_RIFT) {
	// if (false) {
		renderer.mCurrentFoV = vr_rift_fov; // needed for Frustum angle calculation
		// Adjust player eye height, but only in oculus rift mode...
		if (player != NULL) { // null check to avoid aliens crash
			if (savedPlayerViewHeight == 0) {
				savedPlayerViewHeight = player->mo->ViewHeight;
			}
			fixed_t testHeight = savedPlayerViewHeight + FLOAT2FIXED(vr_view_yoffset);
			if (player->mo->ViewHeight != testHeight) {
				player->mo->ViewHeight = testHeight;
				P_CalcHeight(player);
			}
		}
	} else {
		// Revert player eye height when leaving Rift mode
		if ( (savedPlayerViewHeight != 0) && (player->mo->ViewHeight != savedPlayerViewHeight) ) {
			player->mo->ViewHeight = savedPlayerViewHeight;
			savedPlayerViewHeight = 0;
			P_CalcHeight(player);
		}
	}

	angle_t a1 = renderer.FrustumAngle();

	switch(mode) 
	{

	case MONO:
		setViewportFull(renderer, bounds);
		setMonoView(renderer, fov0, ratio0, fovratio0, player);
		renderer.RenderOneEye(a1, toscreen, true);
		renderer.EndDrawScene(viewsector);
		break;

	case GREEN_MAGENTA:
		setViewportFull(renderer, bounds);
		{ // Local scope for color mask
			// Left eye green
			LocalScopeGLColorMask colorMask(0,1,0,1); // green
			setLeftEyeView(renderer, fov0, ratio0, fovratio0, player);
			{
				ViewShifter vs(EYE_VIEW_LEFT, player, renderer);
				renderer.RenderOneEye(a1, toscreen, false);
			}

			// Right eye magenta
			colorMask.setColorMask(1,0,1,1); // magenta
			setRightEyeView(renderer, fov0, ratio0, fovratio0, player);
			{
				ViewShifter vs(EYE_VIEW_RIGHT, player, renderer);
				renderer.RenderOneEye(a1, toscreen, true);
			}
		} // close scope to auto-revert glColorMask
		renderer.EndDrawScene(viewsector);
		break;

	case RED_CYAN:
		setViewportFull(renderer, bounds);
		{ // Local scope for color mask
			// Left eye red
			LocalScopeGLColorMask colorMask(1,0,0,1); // red
			setLeftEyeView(renderer, fov0, ratio0, fovratio0, player);
			{
				ViewShifter vs(EYE_VIEW_LEFT, player, renderer);
				renderer.RenderOneEye(a1, toscreen, false);
			}

			// Right eye cyan
			colorMask.setColorMask(0,1,1,1); // cyan
			setRightEyeView(renderer, fov0, ratio0, fovratio0, player);
			{
				ViewShifter vs(EYE_VIEW_RIGHT, player, renderer);
				renderer.RenderOneEye(a1, toscreen, true);
			}
		} // close scope to auto-revert glColorMask
		renderer.EndDrawScene(viewsector);
		break;

	case SIDE_BY_SIDE:
		{
			// FIRST PASS - 3D
			// Temporarily modify global variables, so HUD could draw correctly
			// each view is half width
			int oldViewwidth = viewwidth;
			viewwidth = viewwidth/2;
			// left
			setViewportLeft(renderer, bounds);
			setLeftEyeView(renderer, fov0, ratio0/2, fovratio0, player); // TODO is that fovratio?
			{
				ViewShifter vs(EYE_VIEW_LEFT, player, renderer);
				renderer.RenderOneEye(a1, false, false); // False, to not swap yet
			}
			// right
			// right view is offset to right
			int oldViewwindowx = viewwindowx;
			viewwindowx += viewwidth;
			setViewportRight(renderer, bounds);
			setRightEyeView(renderer, fov0, ratio0/2, fovratio0, player);
			{
				ViewShifter vs(EYE_VIEW_RIGHT, player, renderer);
				renderer.RenderOneEye(a1, toscreen, true);
			}
			//
			// SECOND PASS weapon sprite
			renderer.EndDrawScene(viewsector); // right view
			viewwindowx -= viewwidth;
			renderer.EndDrawScene(viewsector); // left view
			//
			// restore global state
			viewwidth = oldViewwidth;
			viewwindowx = oldViewwindowx;
			break;
		}

	case SIDE_BY_SIDE_SQUISHED:
		{
			// FIRST PASS - 3D
			// Temporarily modify global variables, so HUD could draw correctly
			// each view is half width
			int oldViewwidth = viewwidth;
			viewwidth = viewwidth/2;
			// left
			setViewportLeft(renderer, bounds);
			setLeftEyeView(renderer, fov0, ratio0, fovratio0*2, player);
			{
				ViewShifter vs(EYE_VIEW_LEFT, player, renderer);
				renderer.RenderOneEye(a1, toscreen, false);
			}
			// right
			// right view is offset to right
			int oldViewwindowx = viewwindowx;
			viewwindowx += viewwidth;
			setViewportRight(renderer, bounds);
			setRightEyeView(renderer, fov0, ratio0, fovratio0*2, player);
			{
				ViewShifter vs(EYE_VIEW_RIGHT, player, renderer);
				renderer.RenderOneEye(a1, false, true);
			}
			//
			// SECOND PASS weapon sprite
			renderer.EndDrawScene(viewsector); // right view
			viewwindowx -= viewwidth;
			renderer.EndDrawScene(viewsector); // left view
			//
			// restore global state
			viewwidth = oldViewwidth;
			viewwindowx = oldViewwindowx;
			break;
		}

	case OCULUS_RIFT:
		{
			if ( (oculusTexture == NULL) || (! oculusTexture->checkSize(SCREENWIDTH, SCREENHEIGHT)) ) {
				if (oculusTexture)
					delete(oculusTexture);
				oculusTexture = new OculusTexture(SCREENWIDTH, SCREENHEIGHT);
			}
			if ( (hudTexture == NULL) || (! hudTexture->checkSize(SCREENWIDTH/2, SCREENHEIGHT)) ) {
				if (hudTexture)
					delete(hudTexture);
				hudTexture = new HudTexture(SCREENWIDTH/2, SCREENHEIGHT);
				hudTexture->bindToFrameBuffer();
				glClearColor(0, 0, 0, 0);
				glClear(GL_COLOR_BUFFER_BIT);
				hudTexture->unbind();
			}
			// Render unwarped image to offscreen frame buffer
			if (doBufferOculus) {
				oculusTexture->bindToFrameBuffer();
			}
			// FIRST PASS - 3D
			// Temporarily modify global variables, so HUD could draw correctly
			// each view is half width
			int oldViewwidth = viewwidth;
			viewwidth = viewwidth/2;
			int oldScreenBlocks = screenblocks;
			screenblocks = 12; // full screen
			//
			// TODO correct geometry for oculus
			//
			float ratio = vr_rift_aspect;
			float fovy = 2.0*atan(tan(0.5*vr_rift_fov*3.14159/180.0)/ratio) * 180.0/3.14159;
			float fovratio = vr_rift_fov/fovy;
			//
			// left
			GL_IRECT riftBounds; // Always use full screen with Oculus Rift
			riftBounds.width = SCREENWIDTH;
			riftBounds.height = SCREENHEIGHT;
			riftBounds.left = 0;
			riftBounds.top = 0;
			setViewportLeft(renderer, &riftBounds);
			setLeftEyeView(renderer, vr_rift_fov, ratio, fovratio, player, false);
			glEnable(GL_DEPTH_TEST);
			{
				ViewShifter vs(EYE_VIEW_LEFT, player, renderer);
				renderer.RenderOneEye(a1, false, false);
			}
			// right
			// right view is offset to right
			int oldViewwindowx = viewwindowx;
			viewwindowx += viewwidth;
			setViewportRight(renderer, &riftBounds);
			setRightEyeView(renderer, vr_rift_fov, ratio, fovratio, player, false);
			{
				ViewShifter vs(EYE_VIEW_RIGHT, player, renderer);
				renderer.RenderOneEye(a1, false, true);
			}

			// Second pass sprites (especially weapon)
			int oldViewwindowy = viewwindowy;
			const bool showSprites = true;
			if (showSprites) {
				// SECOND PASS weapon sprite
				glEnable(GL_TEXTURE_2D);
				screenblocks = 12;
				float fullWidth = SCREENWIDTH / 2.0;
				viewwidth = RIFT_HUDSCALE * fullWidth;
				float left = (1.0 - RIFT_HUDSCALE) * fullWidth * 0.5; // left edge of scaled viewport
				// TODO Sprite needs some offset to appear at correct distance, rather than at infinity.
				int spriteOffsetX = (int)(0.021*fullWidth); // kludge to set weapon distance
				viewwindowx = left + fullWidth - spriteOffsetX;
				int spriteOffsetY = (int)(-0.01 * vr_weapon_height * viewheight); // nudge gun up/down
				// Counteract effect of status bar on weapon position
				if (oldScreenBlocks <= 10) { // lower weapon in status mode
					spriteOffsetY += 0.227 * viewwidth; // empirical - lines up brutal doom down sight in 1920x1080 Rift mode
				}
				viewwindowy += spriteOffsetY;
				renderer.EndDrawScene(viewsector); // right view
				setViewportLeft(renderer, &riftBounds);
				viewwindowx = left + spriteOffsetX;
				renderer.EndDrawScene(viewsector); // left view
			}

			// Third pass HUD
			if (doBufferHud) {
				screenblocks = max(oldScreenBlocks, 10); // Don't vignette main 3D view
				// Draw HUD again, to avoid flashing? - and render to screen
				blitHudTextureToScreen(true); // HUD pass now occurs in main doom loop! Since I delegated screen->Update to stereo3d.updateScreen().
			}

			//
			// restore global state
			viewwidth = oldViewwidth;
			viewwindowx = oldViewwindowx;
			viewwindowy = oldViewwindowy;
			// Update orientation for NEXT frame, after expensive render has occurred this frame
			setViewDirection(renderer);
			// Set up 2D rendering to write to our hud renderbuffer
			if (doBufferHud) {
				bindHudTexture(true);
				glClearColor(0, 0, 0, 0);
				glClear(GL_COLOR_BUFFER_BIT);
				bindHudTexture(false);
				LocalHudRenderer::bind();
			}
			break;
		}

	case LEFT_EYE_VIEW:
		setViewportFull(renderer, bounds);
		setLeftEyeView(renderer, fov0, ratio0, fovratio0, player);
		{
			ViewShifter vs(EYE_VIEW_LEFT, player, renderer);
			renderer.RenderOneEye(a1, toscreen, true);
		}
		renderer.EndDrawScene(viewsector);
		break;

	case RIGHT_EYE_VIEW:
		setViewportFull(renderer, bounds);
		setRightEyeView(renderer, fov0, ratio0, fovratio0, player);
		{
			ViewShifter vs(EYE_VIEW_RIGHT, player, renderer);
			renderer.RenderOneEye(a1, toscreen, true);
		}
		renderer.EndDrawScene(viewsector);
		break;

	case QUAD_BUFFERED:
		setViewportFull(renderer, bounds);
		glGetBooleanv(GL_STEREO, &supportsStereo);
		glGetBooleanv(GL_DOUBLEBUFFER, &supportsBuffered);
		if (supportsStereo && supportsBuffered && toscreen)
		{ 
			// Right first this time, so more generic GL_BACK_LEFT will remain for other modes
			glDrawBuffer(GL_BACK_RIGHT);
			setRightEyeView(renderer, fov0, ratio0, fovratio0, player);
			{
				ViewShifter vs(EYE_VIEW_RIGHT, player, renderer);
				renderer.RenderOneEye(a1, toscreen, false);
			}
			// Left
			glDrawBuffer(GL_BACK_LEFT);
			setLeftEyeView(renderer, fov0, ratio0, fovratio0, player);
			{
				ViewShifter vs(EYE_VIEW_LEFT, player, renderer);
				renderer.RenderOneEye(a1, toscreen, true);
			}
			// Want HUD in both views
			glDrawBuffer(GL_BACK);
		} else { // mono view, in case hardware stereo is not supported
			setMonoView(renderer, fov0, ratio0, fovratio0, player);
			renderer.RenderOneEye(a1, toscreen, true);			
		}
		renderer.EndDrawScene(viewsector);
		break;

	default:
		setViewportFull(renderer, bounds);
		setMonoView(renderer, fov0, ratio0, fovratio0, player);
		renderer.RenderOneEye(a1, toscreen, true);			
		renderer.EndDrawScene(viewsector);
		break;

	}
}
Пример #29
0
bool APathFollower::Interpolate ()
{
	fixed_t dx = 0, dy = 0, dz = 0;

	if ((args[2] & 8) && Time > 0.f)
	{
		dx = x;
		dy = y;
		dz = z;
	}

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

	UnlinkFromWorld ();
	if (args[2] & 1)
	{	// linear
		x = FLOAT2FIXED(Lerp (FIXED2FLOAT(CurrNode->x), FIXED2FLOAT(CurrNode->Next->x)));
		y = FLOAT2FIXED(Lerp (FIXED2FLOAT(CurrNode->y), FIXED2FLOAT(CurrNode->Next->y)));
		z = FLOAT2FIXED(Lerp (FIXED2FLOAT(CurrNode->z), FIXED2FLOAT(CurrNode->Next->z)));
	}
	else
	{	// spline
		if (CurrNode->Next->Next==NULL) return false;

		x = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->x), FIXED2FLOAT(CurrNode->x),
								FIXED2FLOAT(CurrNode->Next->x), FIXED2FLOAT(CurrNode->Next->Next->x)));
		y = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->y), FIXED2FLOAT(CurrNode->y),
								FIXED2FLOAT(CurrNode->Next->y), FIXED2FLOAT(CurrNode->Next->Next->y)));
		z = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->z), FIXED2FLOAT(CurrNode->z),
								FIXED2FLOAT(CurrNode->Next->z), FIXED2FLOAT(CurrNode->Next->Next->z)));
	}
	LinkToWorld ();

	if (args[2] & 6)
	{
		if (args[2] & 8)
		{
			if (args[2] & 1)
			{ // linear
				dx = CurrNode->Next->x - CurrNode->x;
				dy = CurrNode->Next->y - CurrNode->y;
				dz = CurrNode->Next->z - CurrNode->z;
			}
			else if (Time > 0.f)
			{ // spline
				dx = x - dx;
				dy = y - dy;
				dz = z - dz;
			}
			else
			{
				int realarg = args[2];
				args[2] &= ~(2|4|8);
				Time += 0.1f;
				dx = x;
				dy = y;
				dz = z;
				Interpolate ();
				Time -= 0.1f;
				args[2] = realarg;
				dx = x - dx;
				dy = y - dy;
				dz = z - dz;
				x -= dx;
				y -= dy;
				z -= dz;
			}
			if (args[2] & 2)
			{ // adjust yaw
				angle = R_PointToAngle2 (0, 0, dx, dy);
			}
			if (args[2] & 4)
			{ // adjust pitch; use floats for precision
				float fdx = FIXED2FLOAT(dx);
				float fdy = FIXED2FLOAT(dy);
				float fdz = FIXED2FLOAT(-dz);
				float dist = (float)sqrt (fdx*fdx + fdy*fdy);
				float ang = dist != 0.f ? (float)atan2 (fdz, dist) : 0;
				pitch = (angle_t)(ang * 2147483648.f / PI);
			}
		}
		else
		{
			if (args[2] & 2)
			{ // interpolate angle
				float angle1 = (float)CurrNode->angle;
				float angle2 = (float)CurrNode->Next->angle;
				if (angle2 - angle1 <= -2147483648.f)
				{
					float lerped = Lerp (angle1, angle2 + 4294967296.f);
					if (lerped >= 4294967296.f)
					{
						angle = (angle_t)(lerped - 4294967296.f);
					}
					else
					{
						angle = (angle_t)lerped;
					}
				}
				else if (angle2 - angle1 >= 2147483648.f)
				{
					float lerped = Lerp (angle1, angle2 - 4294967296.f);
					if (lerped < 0.f)
					{
						angle = (angle_t)(lerped + 4294967296.f);
					}
					else
					{
						angle = (angle_t)lerped;
					}
				}
				else
				{
					angle = (angle_t)Lerp (angle1, angle2);
				}
			}
			if (args[2] & 1)
			{ // linear
				if (args[2] & 4)
				{ // interpolate pitch
					pitch = FLOAT2FIXED(Lerp (FIXED2FLOAT(CurrNode->pitch), FIXED2FLOAT(CurrNode->Next->pitch)));
				}
			}
			else
			{ // spline
				if (args[2] & 4)
				{ // interpolate pitch
					pitch = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->pitch), FIXED2FLOAT(CurrNode->pitch),
						FIXED2FLOAT(CurrNode->Next->pitch), FIXED2FLOAT(CurrNode->Next->Next->pitch)));
				}
			}
		}
	}

	return true;
}
Пример #30
0
// Returns the amount of damage actually inflicted upon the target, or -1 if
// the damage was cancelled.
int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, FName mod, int flags)
{
	unsigned ang;
	player_t *player = NULL;
	fixed_t thrust;
	int temp;
	int painchance = 0;
	FState * woundstate = NULL;
	PainChanceList * pc = NULL;
	bool justhit = false;
	bool plrDontThrust = false;
	bool invulpain = false;
	bool fakedPain = false;
	bool forcedPain = false;
	int fakeDamage = 0;
	int holdDamage = 0;
	int rawdamage = damage; 
	
	if (damage < 0) damage = 0;

	if (target == NULL || !((target->flags & MF_SHOOTABLE) || (target->flags6 & MF6_VULNERABLE)))
	{ // Shouldn't happen
		return -1;
	}

	//Rather than unnecessarily call the function over and over again, let's be a little more efficient.
	fakedPain = (isFakePain(target, inflictor, damage)); 
	forcedPain = (MustForcePain(target, inflictor));

	// Spectral targets only take damage from spectral projectiles.
	if (target->flags4 & MF4_SPECTRAL && damage < TELEFRAG_DAMAGE)
	{
		if (inflictor == NULL || !(inflictor->flags4 & MF4_SPECTRAL))
		{
			return -1;
		}
	}
	if (target->health <= 0)
	{
		if (inflictor && mod == NAME_Ice)
		{
			return -1;
		}
		else if (target->flags & MF_ICECORPSE) // frozen
		{
			target->tics = 1;
			target->flags6 |= MF6_SHATTERING;
			target->velx = target->vely = target->velz = 0;
		}
		return -1;
	}
	// [MC] Changed it to check rawdamage here for consistency, even though that doesn't actually do anything
	// different here. At any rate, invulnerable is being checked before type factoring, which is then being 
	// checked by player cheats/invul/buddha followed by monster buddha. This is inconsistent. Don't let the 
	// original telefrag damage CHECK (rawdamage) be influenced by outside factors when looking at cheats/invul.
	if ((target->flags2 & MF2_INVULNERABLE) && (rawdamage < TELEFRAG_DAMAGE) && (!(flags & DMG_FORCED)))
	{ // actor is invulnerable
		if (target->player == NULL)
		{
			if (inflictor == NULL || (!(inflictor->flags3 & MF3_FOILINVUL) && !(flags & DMG_FOILINVUL)))
			{
				if (fakedPain)
				{
					// big mess here: What do we use for the pain threshold?
					// We cannot run the various damage filters below so for consistency it needs to be 0.
					damage = 0;
					invulpain = true;
					goto fakepain;
				}
				else
					return -1;
			}
		}
		else
		{
			// Players are optionally excluded from getting thrust by damage.
			if (static_cast<APlayerPawn *>(target)->PlayerFlags & PPF_NOTHRUSTWHENINVUL)
			{
				if (fakedPain)
					plrDontThrust = 1;
				else
					return -1;
			}
		}
		
	}

	if (inflictor != NULL)
	{
		if (inflictor->flags5 & MF5_PIERCEARMOR)
			flags |= DMG_NO_ARMOR;
	}
	
	MeansOfDeath = mod;
	FriendlyFire = false;
	// [RH] Andy Baker's Stealth monsters
	if (target->flags & MF_STEALTH)
	{
		target->alpha = OPAQUE;
		target->visdir = -1;
	}
	if (target->flags & MF_SKULLFLY)
	{
		target->velx = target->vely = target->velz = 0;
	}

	player = target->player;
	if (!(flags & DMG_FORCED))	// DMG_FORCED skips all special damage checks, TELEFRAG_DAMAGE may not be reduced at all
	{
		if (target->flags2 & MF2_DORMANT)
		{
			// Invulnerable, and won't wake up
			return -1;
		}

		if ((rawdamage < TELEFRAG_DAMAGE) || (target->flags7 & MF7_LAXTELEFRAGDMG)) // TELEFRAG_DAMAGE may only be reduced with NOTELEFRAGPIERCE or it may not guarantee its effect.
		{
			if (player && damage > 1)
			{
				// Take half damage in trainer mode
				damage = FixedMul(damage, G_SkillProperty(SKILLP_DamageFactor));
			}
			// Special damage types
			if (inflictor)
			{
				if (inflictor->flags4 & MF4_SPECTRAL)
				{
					if (player != NULL)
					{
						if (!deathmatch && inflictor->FriendPlayer > 0)
							return -1;
					}
					else if (target->flags4 & MF4_SPECTRAL)
					{
						if (inflictor->FriendPlayer == 0 && !target->IsHostile(inflictor))
							return -1;
					}
				}

				damage = inflictor->DoSpecialDamage(target, damage, mod);
				if (damage < 0)
				{
					return -1;
				}
			}

			int olddam = damage;

			if (damage > 0 && source != NULL)
			{
				damage = FixedMul(damage, source->DamageMultiply);

				// Handle active damage modifiers (e.g. PowerDamage)
				if (damage > 0 && source->Inventory != NULL)
				{
					source->Inventory->ModifyDamage(damage, mod, damage, false);
				}
			}
			// Handle passive damage modifiers (e.g. PowerProtection), provided they are not afflicted with protection penetrating powers.
			if (damage > 0 && (target->Inventory != NULL) && !(flags & DMG_NO_PROTECT))
			{
				target->Inventory->ModifyDamage(damage, mod, damage, true);
			}
			if (damage > 0 && !(flags & DMG_NO_FACTOR))
			{
				damage = FixedMul(damage, target->DamageFactor);
				if (damage > 0)
				{
					damage = DamageTypeDefinition::ApplyMobjDamageFactor(damage, mod, target->GetClass()->ActorInfo->DamageFactors);
				}
			}

			if (damage >= 0)
			{
				damage = target->TakeSpecialDamage(inflictor, source, damage, mod);
			}

			// '<0' is handled below. This only handles the case where damage gets reduced to 0.
			if (damage == 0 && olddam > 0)
			{
				{ // Still allow FORCEPAIN
					if (forcedPain)
					{
						goto dopain;
					}
					else if (fakedPain)
					{
						goto fakepain;
					}
					return -1;
				}
			}
		}
		if (target->flags5 & MF5_NODAMAGE)
		{
			damage = 0;
		}
	}
	if (damage < 0)
	{
		// any negative value means that something in the above chain has cancelled out all damage and all damage effects, including pain.
		return -1;
	}
	// Push the target unless the source's weapon's kickback is 0.
	// (i.e. Gauntlets/Chainsaw)
	if (!plrDontThrust && inflictor && inflictor != target	// [RH] Not if hurting own self
		&& !(target->flags & MF_NOCLIP)
		&& !(inflictor->flags2 & MF2_NODMGTHRUST)
		&& !(flags & DMG_THRUSTLESS)
		&& !(target->flags7 & MF7_DONTTHRUST)
		&& (source == NULL || source->player == NULL || !(source->flags2 & MF2_NODMGTHRUST)))
	{
		int kickback;

		if (inflictor && inflictor->projectileKickback)
			kickback = inflictor->projectileKickback;
		else if (!source || !source->player || !source->player->ReadyWeapon)
			kickback = gameinfo.defKickback;
		else
			kickback = source->player->ReadyWeapon->Kickback;

		if (kickback)
		{
			AActor *origin = (source && (flags & DMG_INFLICTOR_IS_PUFF))? source : inflictor;

			// If the origin and target are in exactly the same spot, choose a random direction.
			// (Most likely cause is from telefragging somebody during spawning because they
			// haven't moved from their spawn spot at all.)
			if (origin->x == target->x && origin->y == target->y)
			{
				ang = pr_kickbackdir.GenRand32();
			}
			else
			{
				ang = R_PointToAngle2 (origin->x, origin->y, target->x, target->y);
			}

			// Calculate this as float to avoid overflows so that the
			// clamping that had to be done here can be removed.
            double fltthrust;

            fltthrust = mod == NAME_MDK ? 10 : 32;
            if (target->Mass > 0)
            {
                fltthrust = clamp((damage * 0.125 * kickback) / target->Mass, 0., fltthrust);
            }

			thrust = FLOAT2FIXED(fltthrust);

			// Don't apply ultra-small damage thrust
			if (thrust < FRACUNIT/100) thrust = 0;

			// make fall forwards sometimes
			if ((damage < 40) && (damage > target->health)
				 && (target->z - origin->z > 64*FRACUNIT)
				 && (pr_damagemobj()&1)
				 // [RH] But only if not too fast and not flying
				 && thrust < 10*FRACUNIT
				 && !(target->flags & MF_NOGRAVITY)
				 && (inflictor == NULL || !(inflictor->flags5 & MF5_NOFORWARDFALL))
				 )
			{
				ang += ANG180;
				thrust *= 4;
			}
			ang >>= ANGLETOFINESHIFT;
			if (source && source->player && (flags & DMG_INFLICTOR_IS_PUFF)
				&& source->player->ReadyWeapon != NULL &&
				(source->player->ReadyWeapon->WeaponFlags & WIF_STAFF2_KICKBACK))
			{
				// Staff power level 2
				target->velx += FixedMul (10*FRACUNIT, finecosine[ang]);
				target->vely += FixedMul (10*FRACUNIT, finesine[ang]);
				if (!(target->flags & MF_NOGRAVITY))
				{
					target->velz += 5*FRACUNIT;
				}
			}
			else
			{
				target->velx += FixedMul (thrust, finecosine[ang]);
				target->vely += FixedMul (thrust, finesine[ang]);
			}
		}
	}