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(); }
//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; }
// 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); }
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++; }
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]; } }
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)); }
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; } } }
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); }
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; }
//========================================================================== // // // //========================================================================== 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(); } } }
//========================================================================== // // // //========================================================================== 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(); } } }
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) }
//----------------------------------------------------------------------------- // // 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--; }
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; }
fixed_t UDMFParserBase::CheckFixed(const char *key) { return FLOAT2FIXED(CheckFloat(key)); }
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 {
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); } }
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(); } } }
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); }
void SetOffset(float* ft) { m_X = FLOAT2FIXED(ft[0]); m_Y = FLOAT2FIXED(ft[1]); m_Z = FLOAT2FIXED(ft[2]); }
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(); } }
void R_SetView() { viewx = FLOAT2FIXED(ViewPos.X); viewy = FLOAT2FIXED(ViewPos.Y); }
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; }
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; }
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); }
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; }
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; } }
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; } }
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; }
// 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]); } } }