diff --git a/src/b_game.cpp b/src/b_game.cpp index be827eaca..9681aa7a8 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -60,6 +60,7 @@ Everything that is changed is marked (maybe commented) with "Added by MC" #include "d_net.h" #include "d_netinf.h" #include "d_player.h" +#include "doomerrors.h" static FRandom pr_botspawn ("BotSpawn"); @@ -496,7 +497,15 @@ bool FCajunMaster::LoadBots () DPrintf ("No " BOTFILENAME ", so no bots\n"); return false; } - sc.OpenFile(tmp); + try + { + sc.OpenFile(tmp); + } + catch (CRecoverableError &err) + { + Printf("%s. So no bots\n", err.GetMessage()); + return false; + } while (sc.GetString ()) { diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 3647de77c..b8a5cbcf9 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -496,7 +496,7 @@ void PType::StaticInit() RUNTIME_CLASS(PSound)->TypeTableType = RUNTIME_CLASS(PSound); RUNTIME_CLASS(PColor)->TypeTableType = RUNTIME_CLASS(PColor); RUNTIME_CLASS(PPointer)->TypeTableType = RUNTIME_CLASS(PPointer); - RUNTIME_CLASS(PClassPointer)->TypeTableType = RUNTIME_CLASS(PPointer); // not sure about this yet + RUNTIME_CLASS(PClassPointer)->TypeTableType = RUNTIME_CLASS(PClassPointer); RUNTIME_CLASS(PEnum)->TypeTableType = RUNTIME_CLASS(PEnum); RUNTIME_CLASS(PArray)->TypeTableType = RUNTIME_CLASS(PArray); RUNTIME_CLASS(PDynArray)->TypeTableType = RUNTIME_CLASS(PDynArray); @@ -1430,11 +1430,11 @@ void PClassPointer::GetTypeIDs(intptr_t &id1, intptr_t &id2) const PClassPointer *NewClassPointer(PClass *restrict) { size_t bucket; - PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PPointer), (intptr_t)RUNTIME_CLASS(PClass), (intptr_t)restrict, &bucket); + PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PClassPointer), (intptr_t)RUNTIME_CLASS(PClass), (intptr_t)restrict, &bucket); if (ptype == NULL) { ptype = new PClassPointer(restrict); - TypeTable.AddType(ptype, RUNTIME_CLASS(PPointer), (intptr_t)RUNTIME_CLASS(PClass), (intptr_t)restrict, bucket); + TypeTable.AddType(ptype, RUNTIME_CLASS(PClassPointer), (intptr_t)RUNTIME_CLASS(PClass), (intptr_t)restrict, bucket); } return static_cast(ptype); } diff --git a/src/g_game.cpp b/src/g_game.cpp index 2532acd0f..627853acb 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -2064,6 +2064,7 @@ FString G_BuildSaveName (const char *prefix, int slot) CVAR (Int, autosavenum, 0, CVAR_NOSET|CVAR_ARCHIVE|CVAR_GLOBALCONFIG) static int nextautosave = -1; CVAR (Int, disableautosave, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CVAR (Bool, saveloadconfirmation, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // [mxd] CUSTOM_CVAR (Int, autosavecount, 4, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) { if (self < 0) diff --git a/src/g_hexen/a_blastradius.cpp b/src/g_hexen/a_blastradius.cpp index 7c148cd89..f7fbee36a 100644 --- a/src/g_hexen/a_blastradius.cpp +++ b/src/g_hexen/a_blastradius.cpp @@ -100,7 +100,7 @@ DEFINE_ACTION_FUNCTION_PARAMS (AActor, A_Blast) PARAM_ACTION_PROLOGUE; PARAM_INT_OPT (blastflags) { blastflags = 0; } PARAM_INT_OPT (strength) { strength = 255; } - PARAM_INT_OPT (radius) { radius = 255; } + PARAM_FIXED_OPT (radius) { radius = 255*FRACUNIT; } PARAM_FIXED_OPT (speed) { speed = 20; } PARAM_CLASS_OPT (blasteffect, AActor) { blasteffect = PClass::FindActor("BlastEffect"); } PARAM_SOUND_OPT (blastsound) { blastsound = "BlastRadius"; } diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index dabddbaa0..d0153a98f 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -1058,7 +1058,7 @@ void DBaseStatusBar::RefreshBackground () const int x, x2, y, ratio; ratio = CheckRatio (SCREENWIDTH, SCREENHEIGHT); - x = (!(ratio & 3) || !Scaled) ? ST_X : SCREENWIDTH*(48-BaseRatioSizes[ratio][3])/(48*2); + x = (!IsRatioWidescreen(ratio) || !Scaled) ? ST_X : SCREENWIDTH*(48-BaseRatioSizes[ratio][3])/(48*2); y = x == ST_X && x > 0 ? ST_Y : ::ST_Y; if(!CompleteBorder) @@ -1078,7 +1078,7 @@ void DBaseStatusBar::RefreshBackground () const { if(!CompleteBorder) { - x2 = !(ratio & 3) || !Scaled ? ST_X+HorizontalResolution : + x2 = !IsRatioWidescreen(ratio) || !Scaled ? ST_X+HorizontalResolution : SCREENWIDTH - (SCREENWIDTH*(48-BaseRatioSizes[ratio][3])+48*2-1)/(48*2); } else diff --git a/src/menu/listmenu.cpp b/src/menu/listmenu.cpp index 45b46b623..bcb61d6eb 100644 --- a/src/menu/listmenu.cpp +++ b/src/menu/listmenu.cpp @@ -156,7 +156,9 @@ bool DListMenu::Responder (event_t *ev) bool DListMenu::MenuEvent (int mkey, bool fromcontroller) { + int oldSelect = mDesc->mSelectedItem; int startedAt = mDesc->mSelectedItem; + if (startedAt < 0) startedAt = 0; switch (mkey) { @@ -166,6 +168,7 @@ bool DListMenu::MenuEvent (int mkey, bool fromcontroller) if (--mDesc->mSelectedItem < 0) mDesc->mSelectedItem = mDesc->mItems.Size()-1; } while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt); + if (mDesc->mSelectedItem == startedAt) mDesc->mSelectedItem = oldSelect; S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE); return true; @@ -175,6 +178,7 @@ bool DListMenu::MenuEvent (int mkey, bool fromcontroller) if (++mDesc->mSelectedItem >= (int)mDesc->mItems.Size()) mDesc->mSelectedItem = 0; } while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt); + if (mDesc->mSelectedItem == startedAt) mDesc->mSelectedItem = oldSelect; S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE); return true; diff --git a/src/menu/messagebox.cpp b/src/menu/messagebox.cpp index 2d07ee51d..601c3e736 100644 --- a/src/menu/messagebox.cpp +++ b/src/menu/messagebox.cpp @@ -47,6 +47,7 @@ extern FSaveGameNode *quickSaveSlot; +EXTERN_CVAR (Bool, saveloadconfirmation) // [mxd] class DMessageBoxMenu : public DMenu { @@ -588,13 +589,22 @@ CCMD (quicksave) if (gamestate != GS_LEVEL) return; - S_Sound (CHAN_VOICE | CHAN_UI, "menu/activate", snd_menuvolume, ATTN_NONE); if (quickSaveSlot == NULL) { + S_Sound(CHAN_VOICE | CHAN_UI, "menu/activate", snd_menuvolume, ATTN_NONE); M_StartControlPanel(false); M_SetMenu(NAME_Savegamemenu); return; } + + // [mxd]. Just save the game, no questions asked. + if (!saveloadconfirmation) + { + G_SaveGame(quickSaveSlot->Filename.GetChars(), quickSaveSlot->Title); + return; + } + + S_Sound(CHAN_VOICE | CHAN_UI, "menu/activate", snd_menuvolume, ATTN_NONE); DMenu *newmenu = new DQuickSaveMenu(false); newmenu->mParentMenu = DMenu::CurrentMenu; M_ActivateMenu(newmenu); @@ -666,22 +676,30 @@ void DQuickLoadMenu::HandleResult(bool res) CCMD (quickload) { // F9 - M_StartControlPanel (true); - if (netgame) { + M_StartControlPanel(true); M_StartMessage (GStrings("QLOADNET"), 1); return; } if (quickSaveSlot == NULL) { - M_StartControlPanel(false); + M_StartControlPanel(true); // signal that whatever gets loaded should be the new quicksave quickSaveSlot = (FSaveGameNode *)1; M_SetMenu(NAME_Loadgamemenu); return; } + + // [mxd]. Just load the game, no questions asked. + if (!saveloadconfirmation) + { + G_LoadGame(quickSaveSlot->Filename.GetChars()); + return; + } + + M_StartControlPanel(true); DMenu *newmenu = new DQuickLoadMenu(false); newmenu->mParentMenu = DMenu::CurrentMenu; M_ActivateMenu(newmenu); diff --git a/src/menu/optionmenuitems.h b/src/menu/optionmenuitems.h index 89334dc90..0f315d5f6 100644 --- a/src/menu/optionmenuitems.h +++ b/src/menu/optionmenuitems.h @@ -230,6 +230,10 @@ public: SetSelection(Selection); S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE); } + else + { + return FOptionMenuItem::MenuEvent(mkey, fromcontroller); + } return true; } diff --git a/src/menu/videomenu.cpp b/src/menu/videomenu.cpp index 59f794fc0..1328e2f7a 100644 --- a/src/menu/videomenu.cpp +++ b/src/menu/videomenu.cpp @@ -85,7 +85,7 @@ static BYTE BitTranslate[32]; CUSTOM_CVAR (Int, menu_screenratios, -1, CVAR_ARCHIVE) { - if (self < -1 || self > 4) + if (self < -1 || self > 6) { self = -1; } @@ -216,7 +216,7 @@ static void BuildModesList (int hiwidth, int hiheight, int hi_bits) bool letterbox=false; int ratiomatch; - if (menu_screenratios >= 0 && menu_screenratios <= 4) + if (menu_screenratios >= 0 && menu_screenratios <= 6) { ratiomatch = menu_screenratios; } diff --git a/src/p_map.cpp b/src/p_map.cpp index 0fe73229c..09a209496 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1041,8 +1041,8 @@ static bool PIT_CheckPortal(FMultiBlockLinesIterator &mit, FMultiBlockLinesItera line_t *lp = cres.line->getPortalDestination(); fixed_t zofs = 0; - P_TranslatePortalXY(cres.line, lp, cres.position.x, cres.position.y); - P_TranslatePortalZ(cres.line, lp, zofs); + P_TranslatePortalXY(cres.line, cres.position.x, cres.position.y); + P_TranslatePortalZ(cres.line, zofs); // fudge a bit with the portal line so that this gets included in the checks that normally only get run on two-sided lines sector_t *sec = lp->backsector; @@ -2325,14 +2325,13 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y, } else if (!portalcrossed) { - line_t *out = port->mDestination; fixedvec3 pos = { tm.x, tm.y, thing->Z() }; fixedvec3 oldthingpos = thing->Pos(); fixedvec2 thingpos = oldthingpos; - P_TranslatePortalXY(ld, out, pos.x, pos.y); - P_TranslatePortalXY(ld, out, thingpos.x, thingpos.y); - P_TranslatePortalZ(ld, out, pos.z); + P_TranslatePortalXY(ld, pos.x, pos.y); + P_TranslatePortalXY(ld, thingpos.x, thingpos.y); + P_TranslatePortalZ(ld, pos.z); thing->SetXYZ(thingpos.x, thingpos.y, pos.z); if (!P_CheckPosition(thing, pos.x, pos.y, true)) // check if some actor blocks us on the other side. (No line checks, because of the mess that'd create.) { @@ -2342,8 +2341,8 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y, } thing->UnlinkFromWorld(); thing->SetXYZ(pos); - P_TranslatePortalVXVY(ld, out, thing->velx, thing->vely); - P_TranslatePortalAngle(ld, out, thing->angle); + P_TranslatePortalVXVY(ld, thing->velx, thing->vely); + P_TranslatePortalAngle(ld, thing->angle); thing->LinkToWorld(); P_FindFloorCeiling(thing); thing->ClearInterpolation(); @@ -2355,7 +2354,6 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y, { divline_t dl1 = { besthit.oldrefpos.x,besthit. oldrefpos.y, besthit.refpos.x - besthit.oldrefpos.x, besthit.refpos.y - besthit.oldrefpos.y }; fixedvec3a hit = { dl1.x + FixedMul(dl1.dx, bestfrac), dl1.y + FixedMul(dl1.dy, bestfrac), 0, 0 }; - line_t *out = port->mDestination; R_AddInterpolationPoint(hit); if (port->mType == PORTT_LINKED) @@ -2365,10 +2363,10 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y, } else { - P_TranslatePortalXY(ld, out, hit.x, hit.y); - P_TranslatePortalZ(ld, out, hit.z); + P_TranslatePortalXY(ld, hit.x, hit.y); + P_TranslatePortalZ(ld, hit.z); players[consoleplayer].viewz += hit.z; // needs to be done here because otherwise the renderer will not catch the change. - P_TranslatePortalAngle(ld, out, hit.angle); + P_TranslatePortalAngle(ld, hit.angle); } R_AddInterpolationPoint(hit); } @@ -3438,6 +3436,8 @@ bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop) // //============================================================================ +CVAR(Bool, aimdebug, false, 0) + struct AimTarget : public FTranslatedLineTarget { angle_t pitch; @@ -3680,12 +3680,14 @@ struct aim_t newtrace.startfrac = frac + FixedDiv(FRACUNIT, attackrange); // this is to skip the transition line to the portal which would produce a bogus opening newtrace.lastsector = P_PointInSector(newtrace.startpos.x + FixedMul(aimtrace.x, newtrace.startfrac) , newtrace.startpos.y + FixedMul(aimtrace.y, newtrace.startfrac)); newtrace.limitz = portal->threshold; - Printf("-----Entering %s portal from sector %d to sector %d\n", position ? "ceiling" : "floor", lastsector->sectornum, newtrace.lastsector->sectornum); + if (aimdebug) + Printf("-----Entering %s portal from sector %d to sector %d\n", position ? "ceiling" : "floor", lastsector->sectornum, newtrace.lastsector->sectornum); newtrace.AimTraverse(); SetResult(linetarget, newtrace.linetarget); SetResult(thing_friend, newtrace.thing_friend); SetResult(thing_other, newtrace.thing_other); - Printf("-----Exiting %s portal\n", position ? "ceiling" : "floor"); + if (aimdebug) + Printf("-----Exiting %s portal\n", position ? "ceiling" : "floor"); } //============================================================================ @@ -3700,7 +3702,7 @@ struct aim_t aim_t newtrace = Clone(); FLinePortal *port = li->getPortal(); - line_t *dest = port->mDestination; + if (port->mType != PORTT_LINKED && (flags & ALF_PORTALRESTRICT)) return; newtrace.toppitch = toppitch; newtrace.bottompitch = bottompitch; @@ -3708,9 +3710,9 @@ struct aim_t newtrace.unlinked = (port->mType != PORTT_LINKED); newtrace.startpos = startpos; newtrace.aimtrace = aimtrace; - P_TranslatePortalXY(li, dest, newtrace.startpos.x, newtrace.startpos.y); - P_TranslatePortalZ(li, dest, newtrace.startpos.z); - P_TranslatePortalVXVY(li, dest, newtrace.aimtrace.x, newtrace.aimtrace.y); + P_TranslatePortalXY(li, newtrace.startpos.x, newtrace.startpos.y); + P_TranslatePortalZ(li, newtrace.startpos.z); + P_TranslatePortalVXVY(li, newtrace.aimtrace.x, newtrace.aimtrace.y); newtrace.startfrac = frac + FixedDiv(FRACUNIT, attackrange); // this is to skip the transition line to the portal which would produce a bogus opening @@ -3718,8 +3720,9 @@ struct aim_t fixed_t y = newtrace.startpos.y + FixedMul(newtrace.aimtrace.y, newtrace.startfrac); newtrace.lastsector = P_PointInSector(x, y); - P_TranslatePortalZ(li, dest, limitz); - Printf("-----Entering line portal from sector %d to sector %d\n", lastsector->sectornum, newtrace.lastsector->sectornum); + P_TranslatePortalZ(li, limitz); + if (aimdebug) + Printf("-----Entering line portal from sector %d to sector %d\n", lastsector->sectornum, newtrace.lastsector->sectornum); newtrace.AimTraverse(); SetResult(linetarget, newtrace.linetarget); SetResult(thing_friend, newtrace.thing_friend); @@ -3774,9 +3777,11 @@ struct aim_t FPathTraverse it(startpos.x, startpos.y, aimtrace.x, aimtrace.y, PT_ADDLINES | PT_ADDTHINGS | PT_COMPATIBLE | PT_DELTA, startfrac); intercept_t *in; - Printf("Start AimTraverse, start = %f,%f,%f, vect = %f,%f,%f\n", - startpos.x / 65536., startpos.y / 65536., startpos.y / 65536., - aimtrace.x / 65536., aimtrace.y / 65536.); + if (aimdebug) + Printf("Start AimTraverse, start = %f,%f,%f, vect = %f,%f,%f\n", + startpos.x / 65536., startpos.y / 65536., startpos.y / 65536., + aimtrace.x / 65536., aimtrace.y / 65536.); + while ((in = it.Next())) { line_t* li; @@ -3794,7 +3799,8 @@ struct aim_t li = in->d.line; int frontflag = P_PointOnLineSidePrecise(startpos.x, startpos.y, li); - Printf("Found line %d: toppitch = %f, bottompitch = %f\n", int(li - lines), ANGLE2DBL(toppitch), ANGLE2DBL(bottompitch)); + if (aimdebug) + Printf("Found line %d: toppitch = %f, bottompitch = %f\n", int(li - lines), ANGLE2DBL(toppitch), ANGLE2DBL(bottompitch)); if (li->isLinePortal() && frontflag == 0) { @@ -3837,7 +3843,8 @@ struct aim_t if (!AimTraverse3DFloors(it.Trace(), in, frontflag, &planestocheck)) return; - Printf("After line %d: toppitch = %f, bottompitch = %f, planestocheck = %d\n", int(li - lines), ANGLE2DBL(toppitch), ANGLE2DBL(bottompitch), planestocheck); + if (aimdebug) + Printf("After line %d: toppitch = %f, bottompitch = %f, planestocheck = %d\n", int(li - lines), ANGLE2DBL(toppitch), ANGLE2DBL(bottompitch), planestocheck); sector_t *entersec = frontflag ? li->frontsector : li->backsector; sector_t *exitsec = frontflag ? li->backsector : li->frontsector; @@ -3993,20 +4000,23 @@ struct aim_t if (sv_smartaim < 3) { // don't autoaim at barrels and other shootable stuff unless no monsters have been found - Printf("Hit other %s at %f,%f,%f\n", th->GetClass()->TypeName.GetChars(), th->X() / 65536., th->Y() / 65536., th->Z() / 65536.); + if (aimdebug) + Printf("Hit other %s at %f,%f,%f\n", th->GetClass()->TypeName.GetChars(), th->X() / 65536., th->Y() / 65536., th->Z() / 65536.); SetResult(thing_other, in->frac, th, thingpitch); } } else { - Printf("Hit target %s at %f,%f,%f\n", th->GetClass()->TypeName.GetChars(), th->X() / 65536., th->Y() / 65536., th->Z() / 65536.); + if (aimdebug) + Printf("Hit target %s at %f,%f,%f\n", th->GetClass()->TypeName.GetChars(), th->X() / 65536., th->Y() / 65536., th->Z() / 65536.); SetResult(linetarget, in->frac, th, thingpitch); return; } } else { - Printf("Hit target %s at %f,%f,%f\n", th->GetClass()->TypeName.GetChars(), th->X() / 65536., th->Y() / 65536., th->Z() / 65536.); + if (aimdebug) + Printf("Hit target %s at %f,%f,%f\n", th->GetClass()->TypeName.GetChars(), th->X() / 65536., th->Y() / 65536., th->Z() / 65536.); SetResult(linetarget, in->frac, th, thingpitch); return; } @@ -4272,12 +4282,7 @@ AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance, trace.Sector->heightsec == NULL && trace.HitType == TRACE_HitFloor) { - // Using the puff's position is not accurate enough. - // Instead make it splash at the actual hit position - hitx = t1->X() + FixedMul(vx, trace.Distance); - hity = t1->Y() + FixedMul(vy, trace.Distance); - hitz = shootz + FixedMul(vz, trace.Distance); - P_HitWater(puff, P_PointInSector(hitx, hity), hitx, hity, hitz); + P_HitWater(puff, trace.Sector, trace.X, trace.Y, trace.Z); } } else @@ -4456,7 +4461,7 @@ AActor *P_LinePickActor(AActor *t1, angle_t angle, fixed_t distance, int pitch, TData.hitGhosts = true; if (Trace(t1->X(), t1->Y(), shootz, t1->Sector, vx, vy, vz, distance, - actorMask, wallMask, t1, trace, TRACE_NoSky, CheckForActor, &TData)) + actorMask, wallMask, t1, trace, TRACE_NoSky | TRACE_PortalRestrict, CheckForActor, &TData)) { if (trace.HitType == TRACE_HitActor) { @@ -4843,8 +4848,7 @@ void P_RailAttack(AActor *source, int damage, int offset_xy, fixed_t offset_z, i trace.CrossedWater == NULL && trace.Sector->heightsec == NULL) { - thepuff->SetOrigin(trace.X, trace.Y, trace.Z, false); - P_HitWater(thepuff, trace.Sector); + P_HitWater(thepuff, trace.Sector, trace.X, trace.Y, trace.Z); } if (trace.Crossed3DWater || trace.CrossedWater) { @@ -6449,11 +6453,10 @@ static void SpawnDeepSplash(AActor *t1, const FTraceResults &trace, AActor *puff if (hitdist >= 0 && hitdist <= trace.Distance) { - fixed_t hitx = t1->X() + FixedMul(vx, hitdist); - fixed_t hity = t1->Y() + FixedMul(vy, hitdist); + fixedvec2 hitpos = t1->Vec2Offset(FixedMul(vx, hitdist), FixedMul(vy, hitdist)); fixed_t hitz = shootz + FixedMul(vz, hitdist); - P_HitWater(puff != NULL ? puff : t1, P_PointInSector(hitx, hity), hitx, hity, hitz); + P_HitWater(puff != NULL ? puff : t1, P_PointInSector(hitpos.x, hitpos.y), hitpos.x, hitpos.y, hitz); } } } diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 2a8c0efda..c6453285e 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -1660,14 +1660,13 @@ int FPathTraverse::PortalRelocate(intercept_t *in, int flags, fixedvec3 *optpos) fixed_t hity = trace.y; fixed_t endx = trace.x + trace.dx; fixed_t endy = trace.y + trace.dy; - line_t *out = in->d.line->getPortalDestination(); - - P_TranslatePortalXY(in->d.line, out, hitx, hity); - P_TranslatePortalXY(in->d.line, out, endx, endy); + + P_TranslatePortalXY(in->d.line, hitx, hity); + P_TranslatePortalXY(in->d.line, endx, endy); if (optpos != NULL) { - P_TranslatePortalXY(in->d.line, out, optpos->x, optpos->y); - P_TranslatePortalZ(in->d.line, out, optpos->z); + P_TranslatePortalXY(in->d.line, optpos->x, optpos->y); + P_TranslatePortalZ(in->d.line, optpos->z); } intercepts.Resize(intercept_index); init(hitx, hity, endx, endy, flags, in->frac); diff --git a/src/p_trace.cpp b/src/p_trace.cpp index c283b7b12..297bf52bc 100644 --- a/src/p_trace.cpp +++ b/src/p_trace.cpp @@ -56,6 +56,7 @@ struct FTraceInfo void *TraceCallbackData; DWORD TraceFlags; int inshootthrough; + fixed_t startfrac; // These are required for 3D-floor checking // to create a fake sector with a floor @@ -108,78 +109,8 @@ bool Trace (fixed_t x, fixed_t y, fixed_t z, sector_t *sector, res.Crossed3DWater = NULL; */ - // Do a 3D floor check in the starting sector - TDeletingArray &ff = sector->e->XFloor.ffloors; - - if (ff.Size()) - { - memcpy(&inf.DummySector[0],sector,sizeof(sector_t)); - inf.CurSector=sector=&inf.DummySector[0]; - inf.sectorsel=1; - fixed_t bf = sector->floorplane.ZatPoint (x, y); - fixed_t bc = sector->ceilingplane.ZatPoint (x, y); - - for(unsigned int i=0;iflags&FF_EXISTS)) - continue; - - if (rover->flags&FF_SWIMMABLE && res.Crossed3DWater == NULL) - { - if (inf.Check3DFloorPlane(rover, false)) - res.Crossed3DWater = rover; - } - - if (!(rover->flags&FF_SHOOTTHROUGH)) - { - fixed_t ff_bottom=rover->bottom.plane->ZatPoint(x, y); - fixed_t ff_top=rover->top.plane->ZatPoint(x, y); - // clip to the part of the sector we are in - if (z>ff_top) - { - // above - if (bffloorplane=*rover->top.plane; - sector->SetTexture(sector_t::floor, *rover->top.texture, false); - bf=ff_top; - } - } - else if (zff_bottom) - { - sector->ceilingplane=*rover->bottom.plane; - sector->SetTexture(sector_t::ceiling, *rover->bottom.texture, false); - bc=ff_bottom; - } - } - else - { - // inside - if (bffloorplane=*rover->bottom.plane; - sector->SetTexture(sector_t::floor, *rover->bottom.texture, false); - bf=ff_bottom; - } - - if (bc>ff_top) - { - sector->ceilingplane=*rover->top.plane; - sector->SetTexture(sector_t::ceiling, *rover->top.texture, false); - bc=ff_top; - } - inf.inshootthrough = false; - } - } - } - } - // check for overflows and clip if necessary - SQWORD xd = (SQWORD)x + ( ( SQWORD(vx) * SQWORD(maxDist) )>>16); + SQWORD xd = (SQWORD)x + ((SQWORD(vx) * SQWORD(maxDist)) >> 16); if (xd>SQWORD(32767)*FRACUNIT) { @@ -191,15 +122,15 @@ bool Trace (fixed_t x, fixed_t y, fixed_t z, sector_t *sector, } - SQWORD yd = (SQWORD)y + ( ( SQWORD(vy) * SQWORD(maxDist) )>>16); + SQWORD yd = (SQWORD)y + ((SQWORD(vy) * SQWORD(maxDist)) >> 16); if (yd>SQWORD(32767)*FRACUNIT) { - maxDist = inf.MaxDist=FixedDiv(FIXED_MAX-y,vy); + maxDist = inf.MaxDist = FixedDiv(FIXED_MAX - y, vy); } else if (yd<-SQWORD(32767)*FRACUNIT) { - maxDist = inf.MaxDist=FixedDiv(FIXED_MIN-y,vy); + maxDist = inf.MaxDist = FixedDiv(FIXED_MIN - y, vy); } // recalculate the trace's end points for robustness @@ -250,6 +181,86 @@ bool Trace (fixed_t x, fixed_t y, fixed_t z, sector_t *sector, bool FTraceInfo::TraceTraverse (int ptflags) { + // Do a 3D floor check in the starting sector + TDeletingArray &ff = CurSector->e->XFloor.ffloors; + + if (ff.Size()) + { + memcpy(&DummySector[0], CurSector, sizeof(sector_t)); + CurSector = &DummySector[0]; + sectorsel = 1; + + fixed_t sdist = FixedMul(MaxDist, startfrac); + fixed_t x = StartX + FixedMul(Vx, sdist); + fixed_t y = StartY + FixedMul(Vy, sdist); + fixed_t z = StartZ + FixedMul(Vz, sdist); + + fixed_t bf = CurSector->floorplane.ZatPoint(x, y); + fixed_t bc = CurSector->ceilingplane.ZatPoint(x, y); + + for (auto rover : ff) + { + if (!(rover->flags&FF_EXISTS)) + continue; + + if (rover->flags&FF_SWIMMABLE && Results->Crossed3DWater == NULL) + { + if (Check3DFloorPlane(rover, false)) + Results->Crossed3DWater = rover; + } + + if (!(rover->flags&FF_SHOOTTHROUGH)) + { + fixed_t ff_bottom = rover->bottom.plane->ZatPoint(x, y); + fixed_t ff_top = rover->top.plane->ZatPoint(x, y); + // clip to the part of the sector we are in + if (z>ff_top) + { + // above + if (bffloorplane = *rover->top.plane; + CurSector->SetTexture(sector_t::floor, *rover->top.texture, false); + CurSector->SkyBoxes[sector_t::floor] == NULL; + bf = ff_top; + } + } + else if (zff_bottom) + { + CurSector->ceilingplane = *rover->bottom.plane; + CurSector->SetTexture(sector_t::ceiling, *rover->bottom.texture, false); + bc = ff_bottom; + CurSector->SkyBoxes[sector_t::ceiling] == NULL; + } + } + else + { + // inside + if (bffloorplane = *rover->bottom.plane; + CurSector->SetTexture(sector_t::floor, *rover->bottom.texture, false); + CurSector->SkyBoxes[sector_t::floor] == NULL; + bf = ff_bottom; + } + + if (bc>ff_top) + { + CurSector->ceilingplane = *rover->top.plane; + CurSector->SetTexture(sector_t::ceiling, *rover->top.texture, false); + CurSector->SkyBoxes[sector_t::ceiling] == NULL; + bc = ff_top; + } + inshootthrough = false; + } + } + } + } + + FPathTraverse it(StartX, StartY, FixedMul (Vx, MaxDist), FixedMul (Vy, MaxDist), ptflags | PT_DELTA); intercept_t *in; diff --git a/src/p_trace.h b/src/p_trace.h index 55447e021..1b0815833 100644 --- a/src/p_trace.h +++ b/src/p_trace.h @@ -65,6 +65,9 @@ struct FTraceResults sector_t *Sector; FTextureID HitTexture; fixed_t X, Y, Z; + fixedvec3 SrcFromTarget; + angle_t SrcAngleToTarget; + fixed_t Distance; fixed_t Fraction; @@ -84,6 +87,7 @@ enum TRACE_NoSky = 1, // Hitting the sky returns TRACE_HitNone TRACE_PCross = 2, // Trigger SPAC_PCROSS lines TRACE_Impact = 4, // Trigger SPAC_IMPACT lines + TRACE_PortalRestrict= 8, // Cannot go through portals without a static link offset. }; // return values from callback diff --git a/src/portal.cpp b/src/portal.cpp index 01afb0bc4..49a1592a3 100644 --- a/src/portal.cpp +++ b/src/portal.cpp @@ -265,9 +265,17 @@ void P_SpawnLinePortal(line_t* line) if (port->mDestination != NULL) { port->mDefFlags = port->mType == PORTT_VISUAL ? PORTF_VISIBLE : port->mType == PORTT_TELEPORT ? PORTF_TYPETELEPORT : PORTF_TYPEINTERACTIVE; - - } + + // Get the angle between the two linedefs, for rotating + // orientation and velocity. Rotate 180 degrees, and flip + // the position across the exit linedef, if reversed. + + double angle = atan2(dst->dy, dst->dx) - atan2(line->dy, line->dx) + M_PI; + port->mSinRot = FLOAT2FIXED(sin(angle)); + port->mCosRot = FLOAT2FIXED(cos(angle)); + port->mAngleDiff = RAD2ANGLE(angle); + } else if (line->args[2] == PORTT_LINKEDEE && line->args[0] == 0) { @@ -460,47 +468,6 @@ void P_ClearPortals() } -//============================================================================ -// -// Calculate the intersection between two lines. -// [ZZ] lots of floats here to avoid overflowing a lot -// -//============================================================================ - -bool P_IntersectLines(fixed_t o1x, fixed_t o1y, fixed_t p1x, fixed_t p1y, - fixed_t o2x, fixed_t o2y, fixed_t p2x, fixed_t p2y, - fixed_t& rx, fixed_t& ry) -{ - double xx = FIXED2DBL(o2x) - FIXED2DBL(o1x); - double xy = FIXED2DBL(o2y) - FIXED2DBL(o1y); - - double d1x = FIXED2DBL(p1x) - FIXED2DBL(o1x); - double d1y = FIXED2DBL(p1y) - FIXED2DBL(o1y); - - if (d1x > d1y) - { - d1y = d1y / d1x * 32767.0f; - d1x = 32767.0; - } - else - { - d1x = d1x / d1y * 32767.0f; - d1y = 32767.0; - } - - double d2x = FIXED2DBL(p2x) - FIXED2DBL(o2x); - double d2y = FIXED2DBL(p2y) - FIXED2DBL(o2y); - - double cross = d1x*d2y - d1y*d2x; - if (fabs(cross) < 1e-8) - return false; - - double t1 = (xx * d2y - xy * d2x)/cross; - rx = o1x + FLOAT2FIXED(d1x * t1); - ry = o1y + FLOAT2FIXED(d1y * t1); - return true; -} - inline int P_PointOnLineSideExplicit (fixed_t x, fixed_t y, fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2) { return DMulScale32 (y-y1, x2-x1, x1-x, y2-y1) > 0; @@ -509,35 +476,52 @@ inline int P_PointOnLineSideExplicit (fixed_t x, fixed_t y, fixed_t x1, fixed_t //============================================================================ // // check if this line is between portal and the viewer. clip away if it is. -// (this may need some fixing) // //============================================================================ +inline int P_GetLineSide(fixed_t x, fixed_t y, const line_t *line) +{ + return DMulScale32(y - line->v1->y, line->dx, line->v1->x - x, line->dy); +} + bool P_ClipLineToPortal(line_t* line, line_t* portal, fixed_t viewx, fixed_t viewy, bool partial, bool samebehind) { - bool behind1 = !!P_PointOnLineSidePrecise(line->v1->x, line->v1->y, portal); - bool behind2 = !!P_PointOnLineSidePrecise(line->v2->x, line->v2->y, portal); + int behind1 = P_GetLineSide(line->v1->x, line->v1->y, portal); + int behind2 = P_GetLineSide(line->v2->x, line->v2->y, portal); - // [ZZ] update 16.12.2014: if a vertex equals to one of portal's vertices, it's treated as being behind the portal. - // this is required in order to clip away diagonal lines around the portal (example: 1-sided triangle shape with a mirror on it's side) - if ((line->v1->x == portal->v1->x && line->v1->y == portal->v1->y) || - (line->v1->x == portal->v2->x && line->v1->y == portal->v2->y)) - behind1 = samebehind; - if ((line->v2->x == portal->v1->x && line->v2->y == portal->v1->y) || - (line->v2->x == portal->v2->x && line->v2->y == portal->v2->y)) - behind2 = samebehind; - - if (behind1 && behind2) + if (behind1 == 0 && behind2 == 0) { - // line is behind the portal plane. now check if it's in front of two view plane borders (i.e. if it will get in the way of rendering) - fixed_t dummyx, dummyy; - bool infront1 = P_IntersectLines(line->v1->x, line->v1->y, line->v2->x, line->v2->y, viewx, viewy, portal->v1->x, portal->v1->y, dummyx, dummyy); - bool infront2 = P_IntersectLines(line->v1->x, line->v1->y, line->v2->x, line->v2->y, viewx, viewy, portal->v2->x, portal->v2->y, dummyx, dummyy); - if (infront1 && infront2) - return true; + // The line is parallel to the portal and cannot possibly be visible. + return true; } + // If one point lies on the same straight line than the portal, the other vertex will determine sidedness alone. + else if (behind2 == 0) behind2 = behind1; + else if (behind1 == 0) behind1 = behind2; - return false; + if (behind1 > 0 && behind2 > 0) + { + // The line is behind the portal, i.e. between viewer and portal line, and must be rejected + return true; + } + else if (behind1 < 0 && behind2 < 0) + { + // The line is in front of the portal, i.e. the portal is between viewer and line. This line must not be rejected + return false; + } + else + { + // The line intersects with the portal straight, so we need to do another check to see how both ends of the portal lie in relation to the viewer. + int viewside = P_PointOnLineSidePrecise(viewx, viewy, line); + int p1side = P_GetLineSide(portal->v1->x, portal->v1->y, line); + int p2side = P_GetLineSide(portal->v2->x, portal->v2->y, line); + // Do the same handling of points on the portal straight than above. + if (p1side == 0) p1side = p2side; + else if (p2side == 0) p2side = p1side; + p1side = p1side > 0; + p2side = p2side > 0; + // If the portal is on the other side of the line than the viewpoint, there is no possibility to see this line inside the portal. + return (p1side == p2side && viewside != p1side); + } } //============================================================================ @@ -546,30 +530,22 @@ bool P_ClipLineToPortal(line_t* line, line_t* portal, fixed_t viewx, fixed_t vie // //============================================================================ -void P_TranslatePortalXY(line_t* src, line_t* dst, fixed_t& x, fixed_t& y) +void P_TranslatePortalXY(line_t* src, fixed_t& x, fixed_t& y) { - if (!src || !dst) - return; + if (!src) return; + FLinePortal *port = src->getPortal(); + if (!port) return; - fixed_t nposx, nposy; // offsets from line - - // Get the angle between the two linedefs, for rotating - // orientation and velocity. Rotate 180 degrees, and flip - // the position across the exit linedef, if reversed. - - double angle = atan2(dst->dy, dst->dx) - atan2(src->dy, src->dx) + M_PI; - fixed_t s = FLOAT2FIXED(sin(angle)); - fixed_t c = FLOAT2FIXED(cos(angle)); - - nposx = x - src->v1->x; - nposy = y - src->v1->y; + // offsets from line + fixed_t nposx = x - src->v1->x; + fixed_t nposy = y - src->v1->y; // Rotate position along normal to match exit linedef - fixed_t tx = FixedMul(nposx, c) - FixedMul(nposy, s); - fixed_t ty = FixedMul(nposy, c) + FixedMul(nposx, s); + fixed_t tx = FixedMul(nposx, port->mCosRot) - FixedMul(nposy, port->mSinRot); + fixed_t ty = FixedMul(nposy, port->mCosRot) + FixedMul(nposx, port->mSinRot); - tx += dst->v2->x; - ty += dst->v2->y; + tx += port->mDestination->v2->x; + ty += port->mDestination->v2->y; x = tx; y = ty; @@ -581,16 +557,16 @@ void P_TranslatePortalXY(line_t* src, line_t* dst, fixed_t& x, fixed_t& y) // //============================================================================ -void P_TranslatePortalVXVY(line_t* src, line_t* dst, fixed_t& vx, fixed_t& vy) +void P_TranslatePortalVXVY(line_t* src, fixed_t& vx, fixed_t& vy) { - double angle = atan2(dst->dy, dst->dx) - atan2(src->dy, src->dx) + M_PI; - fixed_t s = FLOAT2FIXED(sin(angle)); - fixed_t c = FLOAT2FIXED(cos(angle)); + if (!src) return; + FLinePortal *port = src->getPortal(); + if (!port) return; fixed_t orig_velx = vx; fixed_t orig_vely = vy; - vx = FixedMul(orig_velx, c) - FixedMul(orig_vely, s); - vy = FixedMul(orig_vely, c) + FixedMul(orig_velx, s); + vx = FixedMul(orig_velx, port->mCosRot) - FixedMul(orig_vely, port->mSinRot); + vy = FixedMul(orig_vely, port->mCosRot) + FixedMul(orig_velx, port->mSinRot); } //============================================================================ @@ -599,15 +575,12 @@ void P_TranslatePortalVXVY(line_t* src, line_t* dst, fixed_t& vx, fixed_t& vy) // //============================================================================ -void P_TranslatePortalAngle(line_t* src, line_t* dst, angle_t& angle) +void P_TranslatePortalAngle(line_t* src, angle_t& angle) { - if (!src || !dst) - return; - - // Get the angle between the two linedefs, for rotating - // orientation and velocity. Rotate 180 degrees, and flip - // the position across the exit linedef, if reversed. - angle += RAD2ANGLE(atan2(dst->dy, dst->dx) - atan2(src->dy, src->dx)) + ANGLE_180; + if (!src) return; + FLinePortal *port = src->getPortal(); + if (!port) return; + angle += port->mAngleDiff; } //============================================================================ @@ -616,12 +589,14 @@ void P_TranslatePortalAngle(line_t* src, line_t* dst, angle_t& angle) // //============================================================================ -void P_TranslatePortalZ(line_t* src, line_t* dst, fixed_t& z) +void P_TranslatePortalZ(line_t* src, fixed_t& z) { // args[2] = 0 - no adjustment // args[2] = 1 - adjust by floor difference // args[2] = 2 - adjust by ceiling difference + // This cannot be precalculated because heights may change. + line_t *dst = src->getPortalDestination(); switch (src->getPortalAlignment()) { case PORG_FLOOR: @@ -704,7 +679,6 @@ fixedvec2 P_GetOffsetPosition(fixed_t x, fixed_t y, fixed_t dx, fixed_t dy) // hit a portal line. line_t *line = in->d.line; FLinePortal *port = line->getPortal(); - line_t* out = port->mDestination; // Teleport portals are intentionally ignored since skipping this stuff is their entire reason for existence. if (port->mFlags & PORTF_INTERACTIVE) @@ -723,8 +697,8 @@ fixedvec2 P_GetOffsetPosition(fixed_t x, fixed_t y, fixed_t dx, fixed_t dy) { // interactive ones are more complex because the vector may be rotated. // Note: There is no z-translation here, there's just too much code in the engine that wouldn't be able to handle interactive portals with a height difference. - P_TranslatePortalXY(line, out, hit.x, hit.y); - P_TranslatePortalXY(line, out, dest.x, dest.y); + P_TranslatePortalXY(line, hit.x, hit.y); + P_TranslatePortalXY(line, dest.x, dest.y); } // update the fields, end this trace and restart from the new position dx = dest.x - hit.x; diff --git a/src/portal.h b/src/portal.h index 127a9ec3b..b8a5d3ba3 100644 --- a/src/portal.h +++ b/src/portal.h @@ -173,6 +173,9 @@ struct FLinePortal BYTE mFlags; BYTE mDefFlags; BYTE mAlign; + angle_t mAngleDiff; + fixed_t mSinRot; + fixed_t mCosRot; }; extern TArray linePortals; @@ -192,10 +195,10 @@ inline int P_NumPortalGroups() /* code ported from prototype */ bool P_ClipLineToPortal(line_t* line, line_t* portal, fixed_t viewx, fixed_t viewy, bool partial = true, bool samebehind = true); -void P_TranslatePortalXY(line_t* src, line_t* dst, fixed_t& x, fixed_t& y); -void P_TranslatePortalVXVY(line_t* src, line_t* dst, fixed_t& vx, fixed_t& vy); -void P_TranslatePortalAngle(line_t* src, line_t* dst, angle_t& angle); -void P_TranslatePortalZ(line_t* src, line_t* dst, fixed_t& z); +void P_TranslatePortalXY(line_t* src, fixed_t& x, fixed_t& y); +void P_TranslatePortalVXVY(line_t* src, fixed_t& vx, fixed_t& vy); +void P_TranslatePortalAngle(line_t* src, angle_t& angle); +void P_TranslatePortalZ(line_t* src, fixed_t& z); void P_NormalizeVXVY(fixed_t& vx, fixed_t& vy); fixed_t P_PointLineDistance(line_t* line, fixed_t x, fixed_t y); fixedvec2 P_GetOffsetPosition(fixed_t x, fixed_t y, fixed_t dx, fixed_t dy); diff --git a/src/posix/cocoa/i_video.mm b/src/posix/cocoa/i_video.mm index 2d10a9ccb..89b3714d1 100644 --- a/src/posix/cocoa/i_video.mm +++ b/src/posix/cocoa/i_video.mm @@ -357,6 +357,7 @@ VideoModes[] = { 1152, 648 }, // 16:9 { 1152, 720 }, // 16:10 { 1152, 864 }, + { 1280, 540 }, // 21:9 { 1280, 720 }, // 16:9 { 1280, 854 }, { 1280, 800 }, // 16:10 @@ -379,15 +380,18 @@ VideoModes[] = { 2048, 1152 }, // 16:9, iMac Retina 4K 21.5", HiDPI off { 2048, 1536 }, { 2304, 1440 }, // 16:10, MacBook Retina 12" + { 2560, 1080 }, // 21:9 { 2560, 1440 }, { 2560, 1600 }, { 2560, 2048 }, { 2880, 1800 }, // 16:10, MacBook Pro Retina 15" { 3200, 1800 }, + { 3440, 1440 }, // 21:9 { 3840, 2160 }, { 3840, 2400 }, { 4096, 2160 }, { 4096, 2304 }, // 16:9, iMac Retina 4K 21.5" + { 5120, 2160 }, // 21:9 { 5120, 2880 } // 16:9, iMac Retina 5K 27" }; @@ -1170,7 +1174,7 @@ CCMD(vid_listmodes) return; } - static const char* const ratios[5] = { "", " - 16:9", " - 16:10", " - 17:10", " - 5:4" }; + static const char* const ratios[7] = { "", " - 16:9", " - 16:10", " - 17:10", " - 5:4", "", " - 21:9" }; int width, height; bool letterbox; diff --git a/src/posix/sdl/hardware.cpp b/src/posix/sdl/hardware.cpp index 83c855de5..b7cb7fe65 100644 --- a/src/posix/sdl/hardware.cpp +++ b/src/posix/sdl/hardware.cpp @@ -1,110 +1,110 @@ -/* -** hardware.cpp -** Somewhat OS-independant interface to the screen, mouse, keyboard, and stick -** -**--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#include -#include -#include - -#include "version.h" -#include "hardware.h" -#include "i_video.h" -#include "i_system.h" -#include "c_console.h" -#include "c_cvars.h" -#include "c_dispatch.h" -#include "sdlvideo.h" -#include "v_text.h" -#include "doomstat.h" -#include "m_argv.h" -#include "sdlglvideo.h" -#include "r_renderer.h" -#include "r_swrenderer.h" - -EXTERN_CVAR (Bool, ticker) -EXTERN_CVAR (Bool, fullscreen) -EXTERN_CVAR (Float, vid_winscale) - -IVideo *Video; - -extern int NewWidth, NewHeight, NewBits, DisplayBits; -bool V_DoModeSetup (int width, int height, int bits); -void I_RestartRenderer(); - -int currentrenderer; - -// [ZDoomGL] -CUSTOM_CVAR (Int, vid_renderer, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) -{ - // 0: Software renderer - // 1: OpenGL renderer - - if (self != currentrenderer) - { - switch (self) - { - case 0: - Printf("Switching to software renderer...\n"); - break; - case 1: - Printf("Switching to OpenGL renderer...\n"); - break; - default: - Printf("Unknown renderer (%d). Falling back to software renderer...\n", (int) vid_renderer); - self = 0; // make sure to actually switch to the software renderer - break; - } - Printf("You must restart " GAMENAME " to switch the renderer\n"); - } -} - -void I_ShutdownGraphics () -{ - if (screen) - { - DFrameBuffer *s = screen; - screen = NULL; - s->ObjectFlags |= OF_YesReallyDelete; - delete s; - } - if (Video) - delete Video, Video = NULL; +/* +** hardware.cpp +** Somewhat OS-independant interface to the screen, mouse, keyboard, and stick +** +**--------------------------------------------------------------------------- +** Copyright 1998-2006 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include +#include +#include + +#include "version.h" +#include "hardware.h" +#include "i_video.h" +#include "i_system.h" +#include "c_console.h" +#include "c_cvars.h" +#include "c_dispatch.h" +#include "sdlvideo.h" +#include "v_text.h" +#include "doomstat.h" +#include "m_argv.h" +#include "sdlglvideo.h" +#include "r_renderer.h" +#include "r_swrenderer.h" + +EXTERN_CVAR (Bool, ticker) +EXTERN_CVAR (Bool, fullscreen) +EXTERN_CVAR (Float, vid_winscale) + +IVideo *Video; + +extern int NewWidth, NewHeight, NewBits, DisplayBits; +bool V_DoModeSetup (int width, int height, int bits); +void I_RestartRenderer(); + +int currentrenderer; + +// [ZDoomGL] +CUSTOM_CVAR (Int, vid_renderer, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) +{ + // 0: Software renderer + // 1: OpenGL renderer + + if (self != currentrenderer) + { + switch (self) + { + case 0: + Printf("Switching to software renderer...\n"); + break; + case 1: + Printf("Switching to OpenGL renderer...\n"); + break; + default: + Printf("Unknown renderer (%d). Falling back to software renderer...\n", (int) vid_renderer); + self = 0; // make sure to actually switch to the software renderer + break; + } + Printf("You must restart " GAMENAME " to switch the renderer\n"); + } +} + +void I_ShutdownGraphics () +{ + if (screen) + { + DFrameBuffer *s = screen; + screen = NULL; + s->ObjectFlags |= OF_YesReallyDelete; + delete s; + } + if (Video) + delete Video, Video = NULL; SDL_QuitSubSystem (SDL_INIT_VIDEO); -} - -void I_InitGraphics () -{ +} + +void I_InitGraphics () +{ if (SDL_InitSubSystem (SDL_INIT_VIDEO) < 0) { I_FatalError ("Could not initialize SDL video:\n%s\n", SDL_GetError()); @@ -113,266 +113,266 @@ void I_InitGraphics () Printf("Using video driver %s\n", SDL_GetCurrentVideoDriver()); - UCVarValue val; - - val.Bool = !!Args->CheckParm ("-devparm"); - ticker.SetGenericRepDefault (val, CVAR_Bool); - - //currentrenderer = vid_renderer; - if (currentrenderer==1) Video = new SDLGLVideo(0); - else Video = new SDLVideo (0); - - if (Video == NULL) - I_FatalError ("Failed to initialize display"); - - atterm (I_ShutdownGraphics); - - Video->SetWindowedScale (vid_winscale); -} - -static void I_DeleteRenderer() -{ - if (Renderer != NULL) delete Renderer; -} - -void I_CreateRenderer() -{ - currentrenderer = vid_renderer; - if (Renderer == NULL) - { - if (currentrenderer==1) Renderer = gl_CreateInterface(); - else Renderer = new FSoftwareRenderer; - atterm(I_DeleteRenderer); - } -} - - -/** Remaining code is common to Win32 and Linux **/ - -// VIDEO WRAPPERS --------------------------------------------------------- - -DFrameBuffer *I_SetMode (int &width, int &height, DFrameBuffer *old) -{ - bool fs = false; - switch (Video->GetDisplayType ()) - { - case DISPLAY_WindowOnly: - fs = false; - break; - case DISPLAY_FullscreenOnly: - fs = true; - break; - case DISPLAY_Both: - fs = fullscreen; - break; - } - DFrameBuffer *res = Video->CreateFrameBuffer (width, height, fs, old); - - /* Right now, CreateFrameBuffer cannot return NULL - if (res == NULL) - { - I_FatalError ("Mode %dx%d is unavailable\n", width, height); - } - */ - return res; -} - -bool I_CheckResolution (int width, int height, int bits) -{ - int twidth, theight; - - Video->StartModeIterator (bits, screen ? screen->IsFullscreen() : fullscreen); - while (Video->NextMode (&twidth, &theight, NULL)) - { - if (width == twidth && height == theight) - return true; - } - return false; -} - -void I_ClosestResolution (int *width, int *height, int bits) -{ - int twidth, theight; - int cwidth = 0, cheight = 0; - int iteration; - DWORD closest = 4294967295u; - - for (iteration = 0; iteration < 2; iteration++) - { - Video->StartModeIterator (bits, screen ? screen->IsFullscreen() : fullscreen); - while (Video->NextMode (&twidth, &theight, NULL)) - { - if (twidth == *width && theight == *height) - return; - - if (iteration == 0 && (twidth < *width || theight < *height)) - continue; - - DWORD dist = (twidth - *width) * (twidth - *width) - + (theight - *height) * (theight - *height); - - if (dist < closest) - { - closest = dist; - cwidth = twidth; - cheight = theight; - } - } - if (closest != 4294967295u) - { - *width = cwidth; - *height = cheight; - return; - } - } -} - -//========================================================================== -// -// SetFPSLimit -// -// Initializes an event timer to fire at a rate of /sec. The video -// update will wait for this timer to trigger before updating. -// -// Pass 0 as the limit for unlimited. -// Pass a negative value for the limit to use the value of vid_maxfps. -// -//========================================================================== - -EXTERN_CVAR(Int, vid_maxfps); -EXTERN_CVAR(Bool, cl_capfps); - -#ifndef __APPLE__ -Semaphore FPSLimitSemaphore; - -static void FPSLimitNotify(sigval val) -{ - SEMAPHORE_SIGNAL(FPSLimitSemaphore) -} - -void I_SetFPSLimit(int limit) -{ - static sigevent FPSLimitEvent; - static timer_t FPSLimitTimer; - static bool FPSLimitTimerEnabled = false; - static bool EventSetup = false; - if(!EventSetup) - { - EventSetup = true; - FPSLimitEvent.sigev_notify = SIGEV_THREAD; - FPSLimitEvent.sigev_signo = 0; - FPSLimitEvent.sigev_value.sival_int = 0; - FPSLimitEvent.sigev_notify_function = FPSLimitNotify; - FPSLimitEvent.sigev_notify_attributes = NULL; - - SEMAPHORE_INIT(FPSLimitSemaphore, 0, 0) - } - - if (limit < 0) - { - limit = vid_maxfps; - } - // Kill any leftover timer. - if (FPSLimitTimerEnabled) - { - timer_delete(FPSLimitTimer); - FPSLimitTimerEnabled = false; - } - if (limit == 0) - { // no limit - DPrintf("FPS timer disabled\n"); - } - else - { - FPSLimitTimerEnabled = true; - if(timer_create(CLOCK_REALTIME, &FPSLimitEvent, &FPSLimitTimer) == -1) - Printf("Failed to create FPS limitter event\n"); - itimerspec period = { {0, 0}, {0, 0} }; - period.it_value.tv_nsec = period.it_interval.tv_nsec = 1000000000 / limit; - if(timer_settime(FPSLimitTimer, 0, &period, NULL) == -1) - Printf("Failed to set FPS limitter timer\n"); - DPrintf("FPS timer set to %u ms\n", (unsigned int) period.it_interval.tv_nsec / 1000000); - } -} -#else -// So Apple doesn't support POSIX timers and I can't find a good substitute short of -// having Objective-C Cocoa events or something like that. -void I_SetFPSLimit(int limit) -{ -} -#endif - -CUSTOM_CVAR (Int, vid_maxfps, 200, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -{ - if (vid_maxfps < TICRATE && vid_maxfps != 0) - { - vid_maxfps = TICRATE; - } - else if (vid_maxfps > 1000) - { - vid_maxfps = 1000; - } - else if (cl_capfps == 0) - { - I_SetFPSLimit(vid_maxfps); - } -} - -extern int NewWidth, NewHeight, NewBits, DisplayBits; - -CUSTOM_CVAR (Bool, fullscreen, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -{ - NewWidth = screen->GetWidth(); - NewHeight = screen->GetHeight(); - NewBits = DisplayBits; - setmodeneeded = true; -} - -CUSTOM_CVAR (Float, vid_winscale, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -{ - if (self < 1.f) - { - self = 1.f; - } - else if (Video) - { - Video->SetWindowedScale (self); - NewWidth = screen->GetWidth(); - NewHeight = screen->GetHeight(); - NewBits = DisplayBits; - setmodeneeded = true; - } -} - -CCMD (vid_listmodes) -{ - static const char *ratios[5] = { "", " - 16:9", " - 16:10", "", " - 5:4" }; - int width, height, bits; - bool letterbox; - - if (Video == NULL) - { - return; - } - for (bits = 1; bits <= 32; bits++) - { - Video->StartModeIterator (bits, screen->IsFullscreen()); - while (Video->NextMode (&width, &height, &letterbox)) - { - bool thisMode = (width == DisplayWidth && height == DisplayHeight && bits == DisplayBits); - int ratio = CheckRatio (width, height); - Printf (thisMode ? PRINT_BOLD : PRINT_HIGH, - "%s%4d x%5d x%3d%s%s\n", - thisMode || !(ratio & 3) ? "" : TEXTCOLOR_GOLD, - width, height, bits, - ratios[ratio], - thisMode || !letterbox ? "" : TEXTCOLOR_BROWN " LB" - ); - } - } -} - -CCMD (vid_currentmode) -{ - Printf ("%dx%dx%d\n", DisplayWidth, DisplayHeight, DisplayBits); -} + UCVarValue val; + + val.Bool = !!Args->CheckParm ("-devparm"); + ticker.SetGenericRepDefault (val, CVAR_Bool); + + //currentrenderer = vid_renderer; + if (currentrenderer==1) Video = new SDLGLVideo(0); + else Video = new SDLVideo (0); + + if (Video == NULL) + I_FatalError ("Failed to initialize display"); + + atterm (I_ShutdownGraphics); + + Video->SetWindowedScale (vid_winscale); +} + +static void I_DeleteRenderer() +{ + if (Renderer != NULL) delete Renderer; +} + +void I_CreateRenderer() +{ + currentrenderer = vid_renderer; + if (Renderer == NULL) + { + if (currentrenderer==1) Renderer = gl_CreateInterface(); + else Renderer = new FSoftwareRenderer; + atterm(I_DeleteRenderer); + } +} + + +/** Remaining code is common to Win32 and Linux **/ + +// VIDEO WRAPPERS --------------------------------------------------------- + +DFrameBuffer *I_SetMode (int &width, int &height, DFrameBuffer *old) +{ + bool fs = false; + switch (Video->GetDisplayType ()) + { + case DISPLAY_WindowOnly: + fs = false; + break; + case DISPLAY_FullscreenOnly: + fs = true; + break; + case DISPLAY_Both: + fs = fullscreen; + break; + } + DFrameBuffer *res = Video->CreateFrameBuffer (width, height, fs, old); + + /* Right now, CreateFrameBuffer cannot return NULL + if (res == NULL) + { + I_FatalError ("Mode %dx%d is unavailable\n", width, height); + } + */ + return res; +} + +bool I_CheckResolution (int width, int height, int bits) +{ + int twidth, theight; + + Video->StartModeIterator (bits, screen ? screen->IsFullscreen() : fullscreen); + while (Video->NextMode (&twidth, &theight, NULL)) + { + if (width == twidth && height == theight) + return true; + } + return false; +} + +void I_ClosestResolution (int *width, int *height, int bits) +{ + int twidth, theight; + int cwidth = 0, cheight = 0; + int iteration; + DWORD closest = 4294967295u; + + for (iteration = 0; iteration < 2; iteration++) + { + Video->StartModeIterator (bits, screen ? screen->IsFullscreen() : fullscreen); + while (Video->NextMode (&twidth, &theight, NULL)) + { + if (twidth == *width && theight == *height) + return; + + if (iteration == 0 && (twidth < *width || theight < *height)) + continue; + + DWORD dist = (twidth - *width) * (twidth - *width) + + (theight - *height) * (theight - *height); + + if (dist < closest) + { + closest = dist; + cwidth = twidth; + cheight = theight; + } + } + if (closest != 4294967295u) + { + *width = cwidth; + *height = cheight; + return; + } + } +} + +//========================================================================== +// +// SetFPSLimit +// +// Initializes an event timer to fire at a rate of /sec. The video +// update will wait for this timer to trigger before updating. +// +// Pass 0 as the limit for unlimited. +// Pass a negative value for the limit to use the value of vid_maxfps. +// +//========================================================================== + +EXTERN_CVAR(Int, vid_maxfps); +EXTERN_CVAR(Bool, cl_capfps); + +#ifndef __APPLE__ +Semaphore FPSLimitSemaphore; + +static void FPSLimitNotify(sigval val) +{ + SEMAPHORE_SIGNAL(FPSLimitSemaphore) +} + +void I_SetFPSLimit(int limit) +{ + static sigevent FPSLimitEvent; + static timer_t FPSLimitTimer; + static bool FPSLimitTimerEnabled = false; + static bool EventSetup = false; + if(!EventSetup) + { + EventSetup = true; + FPSLimitEvent.sigev_notify = SIGEV_THREAD; + FPSLimitEvent.sigev_signo = 0; + FPSLimitEvent.sigev_value.sival_int = 0; + FPSLimitEvent.sigev_notify_function = FPSLimitNotify; + FPSLimitEvent.sigev_notify_attributes = NULL; + + SEMAPHORE_INIT(FPSLimitSemaphore, 0, 0) + } + + if (limit < 0) + { + limit = vid_maxfps; + } + // Kill any leftover timer. + if (FPSLimitTimerEnabled) + { + timer_delete(FPSLimitTimer); + FPSLimitTimerEnabled = false; + } + if (limit == 0) + { // no limit + DPrintf("FPS timer disabled\n"); + } + else + { + FPSLimitTimerEnabled = true; + if(timer_create(CLOCK_REALTIME, &FPSLimitEvent, &FPSLimitTimer) == -1) + Printf("Failed to create FPS limitter event\n"); + itimerspec period = { {0, 0}, {0, 0} }; + period.it_value.tv_nsec = period.it_interval.tv_nsec = 1000000000 / limit; + if(timer_settime(FPSLimitTimer, 0, &period, NULL) == -1) + Printf("Failed to set FPS limitter timer\n"); + DPrintf("FPS timer set to %u ms\n", (unsigned int) period.it_interval.tv_nsec / 1000000); + } +} +#else +// So Apple doesn't support POSIX timers and I can't find a good substitute short of +// having Objective-C Cocoa events or something like that. +void I_SetFPSLimit(int limit) +{ +} +#endif + +CUSTOM_CVAR (Int, vid_maxfps, 200, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (vid_maxfps < TICRATE && vid_maxfps != 0) + { + vid_maxfps = TICRATE; + } + else if (vid_maxfps > 1000) + { + vid_maxfps = 1000; + } + else if (cl_capfps == 0) + { + I_SetFPSLimit(vid_maxfps); + } +} + +extern int NewWidth, NewHeight, NewBits, DisplayBits; + +CUSTOM_CVAR (Bool, fullscreen, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +{ + NewWidth = screen->GetWidth(); + NewHeight = screen->GetHeight(); + NewBits = DisplayBits; + setmodeneeded = true; +} + +CUSTOM_CVAR (Float, vid_winscale, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +{ + if (self < 1.f) + { + self = 1.f; + } + else if (Video) + { + Video->SetWindowedScale (self); + NewWidth = screen->GetWidth(); + NewHeight = screen->GetHeight(); + NewBits = DisplayBits; + setmodeneeded = true; + } +} + +CCMD (vid_listmodes) +{ + static const char *ratios[7] = { "", " - 16:9", " - 16:10", "", " - 5:4", "", " - 21:9" }; + int width, height, bits; + bool letterbox; + + if (Video == NULL) + { + return; + } + for (bits = 1; bits <= 32; bits++) + { + Video->StartModeIterator (bits, screen->IsFullscreen()); + while (Video->NextMode (&width, &height, &letterbox)) + { + bool thisMode = (width == DisplayWidth && height == DisplayHeight && bits == DisplayBits); + int ratio = CheckRatio (width, height); + Printf (thisMode ? PRINT_BOLD : PRINT_HIGH, + "%s%4d x%5d x%3d%s%s\n", + thisMode || !IsRatioWidescreen(ratio) ? "" : TEXTCOLOR_GOLD, + width, height, bits, + ratios[ratio], + thisMode || !letterbox ? "" : TEXTCOLOR_BROWN " LB" + ); + } + } +} + +CCMD (vid_currentmode) +{ + Printf ("%dx%dx%d\n", DisplayWidth, DisplayHeight, DisplayBits); +} diff --git a/src/posix/sdl/sdlvideo.cpp b/src/posix/sdl/sdlvideo.cpp index 9da52c2dd..04c3a3f2e 100644 --- a/src/posix/sdl/sdlvideo.cpp +++ b/src/posix/sdl/sdlvideo.cpp @@ -162,6 +162,7 @@ static MiniModeInfo WinModes[] = { 1152, 648 }, // 16:9 { 1152, 720 }, // 16:10 { 1152, 864 }, + { 1280, 540 }, // 21:9 { 1280, 720 }, // 16:9 { 1280, 854 }, { 1280, 800 }, // 16:10 @@ -182,14 +183,17 @@ static MiniModeInfo WinModes[] = { 1920, 1080 }, { 1920, 1200 }, { 2048, 1536 }, + { 2560, 1080 }, // 21:9 { 2560, 1440 }, { 2560, 1600 }, { 2560, 2048 }, { 2880, 1800 }, { 3200, 1800 }, + { 3440, 1440 }, // 21:9 { 3840, 2160 }, { 3840, 2400 }, { 4096, 2160 }, + { 5120, 2160 }, // 21:9 { 5120, 2880 } }; diff --git a/src/r_main.cpp b/src/r_main.cpp index 12dd3916b..43c22b0f9 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -363,7 +363,7 @@ void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, virtwidth = virtwidth2 = fullWidth; virtheight = virtheight2 = fullHeight; - if (trueratio & 4) + if (Is54Aspect(trueratio)) { virtheight2 = virtheight2 * BaseRatioSizes[trueratio][3] / 48; } @@ -372,7 +372,7 @@ void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, virtwidth2 = virtwidth2 * BaseRatioSizes[trueratio][3] / 48; } - if (WidescreenRatio & 4) + if (Is54Aspect(WidescreenRatio)) { virtheight = virtheight * BaseRatioSizes[WidescreenRatio][3] / 48; } @@ -732,9 +732,9 @@ void R_EnterPortal (PortalDrawseg* pds, int depth) } else { - P_TranslatePortalXY(pds->src, pds->dst, viewx, viewy); - P_TranslatePortalZ(pds->src, pds->dst, viewz); - P_TranslatePortalAngle(pds->src, pds->dst, viewangle); + P_TranslatePortalXY(pds->src, viewx, viewy); + P_TranslatePortalZ(pds->src, viewz); + P_TranslatePortalAngle(pds->src, viewangle); } viewsin = finesine[viewangle>>ANGLETOFINESHIFT]; diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 089c65379..d301b45fc 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -434,7 +434,7 @@ void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight) centery = viewheight/2; centerx = viewwidth/2; - if (WidescreenRatio & 4) + if (Is54Aspect(WidescreenRatio)) { centerxwide = centerx; } diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 8f5d563ef..98dd60f2d 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -3734,6 +3734,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) PARAM_FIXED_OPT (offsetheight) { offsetheight = 0; } PARAM_FIXED_OPT (offsetwidth) { offsetwidth = 0; } PARAM_INT_OPT (ptr_target) { ptr_target = AAPTR_DEFAULT; } + PARAM_FIXED_OPT (offsetforward) { offsetforward = 0; } target = COPY_AAPTR(self, ptr_target == AAPTR_DEFAULT ? AAPTR_TARGET|AAPTR_PLAYER_GETTARGET|AAPTR_NULL : ptr_target); // no player-support by default @@ -3751,6 +3752,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) } if (flags & CLOFF_MUL_WIDTH) { + offsetforward = FixedMul(self->radius, offsetforward); offsetwidth = FixedMul(self->radius, offsetwidth); } @@ -3798,8 +3800,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) ang >>= ANGLETOFINESHIFT; fixedvec2 xy = self->Vec2Offset( - FixedMul(offsetwidth, finesine[ang]), - -FixedMul(offsetwidth, finecosine[ang])); + FixedMul(offsetforward, finecosine[ang]) + FixedMul(offsetwidth, finesine[ang]), + FixedMul(offsetforward, finesine[ang]) - FixedMul(offsetwidth, finecosine[ang])); pos.x = xy.x; pos.y = xy.y; @@ -3826,8 +3828,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) angle_t ang = self->angle >> ANGLETOFINESHIFT; fixedvec2 xy = self->Vec2Offset( - FixedMul(offsetwidth, finesine[ang]), - -FixedMul(offsetwidth, finecosine[ang])); + FixedMul(offsetforward, finecosine[ang]) + FixedMul(offsetwidth, finesine[ang]), + FixedMul(offsetforward, finesine[ang]) - FixedMul(offsetwidth, finecosine[ang])); pos.x = xy.x; pos.y = xy.y; @@ -3868,7 +3870,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) lof_data.Flags = flags; lof_data.BadActor = false; - Trace(pos.x, pos.y, pos.z, sec, vx, vy, vz, range, ActorFlags::FromInt(0xFFFFFFFF), ML_BLOCKEVERYTHING, self, trace, 0, + Trace(pos.x, pos.y, pos.z, sec, vx, vy, vz, range, ActorFlags::FromInt(0xFFFFFFFF), ML_BLOCKEVERYTHING, self, trace, TRACE_PortalRestrict, CheckLOFTraceFunc, &lof_data); if (trace.HitType == TRACE_HitActor || @@ -6681,12 +6683,13 @@ The SET pointer flags only affect the caller, not the pointer. ===========================================================================*/ enum CBF { - CBF_NOLINES = 1 << 0, //Don't check actors. + CBF_NOLINES = 1 << 0, //Don't check lines. CBF_SETTARGET = 1 << 1, //Sets the caller/pointer's target to the actor blocking it. Actors only. CBF_SETMASTER = 1 << 2, //^ but with master. CBF_SETTRACER = 1 << 3, //^ but with tracer. CBF_SETONPTR = 1 << 4, //Sets the pointer change on the actor doing the checking instead of self. CBF_DROPOFF = 1 << 5, //Check for dropoffs. + CBF_NOACTORS = 1 << 6, //Don't check actors. }; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock) @@ -6729,8 +6732,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock) { ACTION_RETURN_STATE(NULL); } - //[MC] Easiest way to tell if an actor is blocking it, use the pointers. - if (mobj->BlockingMobj || (!(flags & CBF_NOLINES) && mobj->BlockingLine != NULL)) + //[MC] I don't know why I let myself be persuaded not to include a flag. + //If an actor is loaded with pointers, they don't really have any options to spare. + + if ((!(flags & CBF_NOACTORS) && (mobj->BlockingMobj)) || (!(flags & CBF_NOLINES) && mobj->BlockingLine != NULL)) { ACTION_RETURN_STATE(block); } diff --git a/src/v_draw.cpp b/src/v_draw.cpp index de096e3a9..bf3a65cdf 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -744,6 +744,13 @@ void DCanvas::VirtualToRealCoords(double &x, double &y, double &w, double &h, double vwidth, double vheight, bool vbottom, bool handleaspect) const { int myratio = handleaspect ? CheckRatio (Width, Height) : 0; + + // if 21:9 AR, map to 16:9 for all callers. + // this allows for black bars and stops the stretching of fullscreen images + if (myratio == 6) { + myratio = 2; + } + double right = x + w; double bottom = y + h; @@ -811,12 +818,19 @@ void DCanvas::VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, void DCanvas::FillBorder (FTexture *img) { int myratio = CheckRatio (Width, Height); + + // if 21:9 AR, fill borders akin to 16:9, since all fullscreen + // images are being drawn to that scale. + if (myratio == 6) { + myratio = 2; + } + if (myratio == 0) { // This is a 4:3 display, so no border to show return; } int bordtop, bordbottom, bordleft, bordright, bord; - if (myratio & 4) + if (Is54Aspect(myratio)) { // Screen is taller than it is wide bordleft = bordright = 0; bord = Height - Height * BaseRatioSizes[myratio][3] / 48; diff --git a/src/v_video.cpp b/src/v_video.cpp index 73681fdc2..52b8fdc86 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1397,7 +1397,7 @@ void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int real int cx1, cy1, cx2, cy2; ratio = CheckRatio(realwidth, realheight); - if (ratio & 4) + if (Is54Aspect(ratio)) { cwidth = realwidth; cheight = realheight * BaseRatioSizes[ratio][3] / 48; @@ -1645,12 +1645,14 @@ CUSTOM_CVAR (Int, vid_aspect, 0, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) // 2: 16:10 // 3: 17:10 // 4: 5:4 +// 5: 17:10 (redundant) +// 6: 21:9 int CheckRatio (int width, int height, int *trueratio) { int fakeratio = -1; int ratio; - if ((vid_aspect >= 1) && (vid_aspect <= 5)) + if ((vid_aspect >= 1) && (vid_aspect <= 6)) { // [SP] User wants to force aspect ratio; let them. fakeratio = int(vid_aspect); @@ -1661,7 +1663,7 @@ int CheckRatio (int width, int height, int *trueratio) else if (fakeratio == 5) { fakeratio = 3; - } + } } if (vid_nowidescreen) { @@ -1702,6 +1704,11 @@ int CheckRatio (int width, int height, int *trueratio) { ratio = 4; } + // test for 21:9 (actually 64:27, 21:9 is a semi-accurate ratio used in marketing) + else if (abs (height * 64/27 - width) < 30) + { + ratio = 6; + } // Assume anything else is 4:3. (Which is probably wrong these days...) else { @@ -1724,13 +1731,15 @@ int CheckRatio (int width, int height, int *trueratio) // base_width = 240 * x / y // multiplier = 320 / base_width // base_height = 200 * multiplier -const int BaseRatioSizes[5][4] = +const int BaseRatioSizes[7][4] = { { 960, 600, 0, 48 }, // 4:3 320, 200, multiplied by three { 1280, 450, 0, 48*3/4 }, // 16:9 426.6667, 150, multiplied by three { 1152, 500, 0, 48*5/6 }, // 16:10 386, 166.6667, multiplied by three { 1224, 471, 0, 48*40/51 }, // 17:10 408, 156.8627, multiplied by three - { 960, 640, (int)(6.5*FRACUNIT), 48*15/16 } // 5:4 320, 213.3333, multiplied by three + { 960, 640, (int)(6.5*FRACUNIT), 48*15/16 }, // 5:4 320, 213.3333, multiplied by three + { 1224, 471, 0, 48*40/51 }, // 17:10 408, 156.8627, multiplied by three (REDUNDANT) + { 1707, 338, 0, 48*9/16 } // 21:9 568.8889, 337.5, multiplied by three }; void IVideo::DumpAdapters () diff --git a/src/v_video.h b/src/v_video.h index 0497b607e..7e0b09258 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -503,8 +503,14 @@ extern "C" void ASM_PatchPitch (void); int CheckRatio (int width, int height, int *trueratio=NULL); static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); } -extern const int BaseRatioSizes[5][4]; +extern const int BaseRatioSizes[7][4]; +inline bool IsRatioWidescreen(int ratio) { + return (ratio & 3)!=0; +} +inline bool Is54Aspect(int ratio) { + return ratio == 4; +} #endif // __V_VIDEO_H__ diff --git a/src/win32/hardware.cpp b/src/win32/hardware.cpp index 251ed6788..fd92694cd 100644 --- a/src/win32/hardware.cpp +++ b/src/win32/hardware.cpp @@ -383,7 +383,7 @@ CUSTOM_CVAR (Float, vid_winscale, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CCMD (vid_listmodes) { - static const char *ratios[5] = { "", " - 16:9", " - 16:10", " - 17:10", " - 5:4" }; + static const char *ratios[7] = { "", " - 16:9", " - 16:10", " - 17:10", " - 5:4", " - 17:10", " - 21:9" }; int width, height, bits; bool letterbox; @@ -401,7 +401,7 @@ CCMD (vid_listmodes) int ratio = CheckRatio (width, height); Printf (thisMode ? PRINT_BOLD : PRINT_HIGH, "%s%4d x%5d x%3d%s%s\n", - thisMode || !(ratio & 3) ? "" : TEXTCOLOR_GOLD, + thisMode || !IsRatioWidescreen(ratio) ? "" : TEXTCOLOR_GOLD, width, height, bits, ratios[ratio], thisMode || !letterbox ? "" : TEXTCOLOR_BROWN " LB" diff --git a/src/zscript/zcc_expr.cpp b/src/zscript/zcc_expr.cpp index 3ab977a2f..69a25970b 100644 --- a/src/zscript/zcc_expr.cpp +++ b/src/zscript/zcc_expr.cpp @@ -181,142 +181,11 @@ ZCC_OpProto *ZCC_OpInfoType::FindBestProto( return best_proto; } -static ZCC_ExprConstant *EvalIncFloat64(ZCC_ExprConstant *val) -{ - val->DoubleVal++; - return val; -} - -static ZCC_ExprConstant *EvalIncInt32(ZCC_ExprConstant *val) -{ - val->IntVal++; - return val; -} - -static ZCC_ExprConstant *EvalDecFloat64(ZCC_ExprConstant *val) -{ - val->DoubleVal--; - return val; -} - -static ZCC_ExprConstant *EvalDecInt32(ZCC_ExprConstant *val) -{ - val->IntVal--; - return val; -} - -static ZCC_ExprConstant *EvalNegateFloat64(ZCC_ExprConstant *val) -{ - val->DoubleVal = -val->DoubleVal; - return val; -} - -static ZCC_ExprConstant *EvalNegateInt32(ZCC_ExprConstant *val) -{ - val->IntVal = -val->IntVal; - return val; -} - static ZCC_ExprConstant *EvalIdentity(ZCC_ExprConstant *val) { return val; } -static ZCC_ExprConstant *EvalBitNot(ZCC_ExprConstant *val) -{ - val->IntVal = ~val->IntVal; - return val; -} - -static ZCC_ExprConstant *EvalBoolNot(ZCC_ExprConstant *val) -{ - val->IntVal = !val->IntVal; - return val; -} - -static ZCC_ExprConstant *EvalAddFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->DoubleVal += r->DoubleVal; - return l; -} - -static ZCC_ExprConstant *EvalAddInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal += r->IntVal; - return l; -} - -static ZCC_ExprConstant *EvalSubFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->DoubleVal -= r->DoubleVal; - return l; -} - -static ZCC_ExprConstant *EvalSubInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal -= r->IntVal; - return l; -} - -static ZCC_ExprConstant *EvalMulFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->DoubleVal *= r->DoubleVal; - return l; -} - -static ZCC_ExprConstant *EvalMulUInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->UIntVal *= r->UIntVal; - return l; -} - -static ZCC_ExprConstant *EvalMulSInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal *= r->IntVal; - return l; -} - -static ZCC_ExprConstant *EvalDivFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->DoubleVal /= r->DoubleVal; - return l; -} - -static ZCC_ExprConstant *EvalDivUInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->UIntVal /= r->UIntVal; - return l; -} - -static ZCC_ExprConstant *EvalDivSInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal /= r->IntVal; - return l; -} - -static ZCC_ExprConstant *EvalModFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->DoubleVal = luai_nummod(l->DoubleVal, r->DoubleVal); - return l; -} - -static ZCC_ExprConstant *EvalModUInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->UIntVal %= r->UIntVal; - return l; -} - -static ZCC_ExprConstant *EvalModSInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal %= r->IntVal; - return l; -} - -static ZCC_ExprConstant *EvalPow(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->DoubleVal = pow(l->DoubleVal, r->DoubleVal); - return l; -} static ZCC_ExprConstant *EvalConcat(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &strings) { @@ -325,117 +194,6 @@ static ZCC_ExprConstant *EvalConcat(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FS return l; } -static ZCC_ExprConstant *EvalBitAnd(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal &= r->IntVal; - return l; -} - -static ZCC_ExprConstant *EvalBitOr(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal |= r->IntVal; - return l; -} - -static ZCC_ExprConstant *EvalBitXor(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal ^= r->IntVal; - return l; -} - -static ZCC_ExprConstant *EvalBoolAnd(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal = l->IntVal && r->IntVal; - return l; -} - -static ZCC_ExprConstant *EvalBoolOr(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal = l->IntVal || r->IntVal; - return l; -} - -static ZCC_ExprConstant *EvalSHL(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal <<= r->UIntVal; - return l; -} - -static ZCC_ExprConstant *EvalSHR_S(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal >>= r->UIntVal; - return l; -} - -static ZCC_ExprConstant *EvalSHR_U(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->UIntVal >>= r->UIntVal; - return l; -} - -static ZCC_ExprConstant *EvalLTSInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal = l->IntVal < r->IntVal; - l->Type = TypeBool; - return l; -} - -static ZCC_ExprConstant *EvalLTUInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal = l->UIntVal < r->UIntVal; - l->Type = TypeBool; - return l; -} - -static ZCC_ExprConstant *EvalLTFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal = l->DoubleVal < r->DoubleVal; - l->Type = TypeBool; - return l; -} - -static ZCC_ExprConstant *EvalLTEQSInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal = l->IntVal <= r->IntVal; - l->Type = TypeBool; - return l; -} - -static ZCC_ExprConstant *EvalLTEQUInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal = l->UIntVal <= r->UIntVal; - l->Type = TypeBool; - return l; -} - -static ZCC_ExprConstant *EvalLTEQFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal = l->DoubleVal <= r->DoubleVal; - l->Type = TypeBool; - return l; -} - -static ZCC_ExprConstant *EvalEQEQSInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal = l->IntVal == r->IntVal; - l->Type = TypeBool; - return l; -} - -static ZCC_ExprConstant *EvalEQEQUInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal = l->UIntVal == r->UIntVal; - l->Type = TypeBool; - return l; -} - -static ZCC_ExprConstant *EvalEQEQFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal = l->DoubleVal == r->DoubleVal; - l->Type = TypeBool; - return l; -} - static ZCC_ExprConstant *EvalLTGTEQSInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) { l->IntVal = l->IntVal < r->IntVal ? -1 : l->IntVal == r->IntVal ? 0 : 1; @@ -471,25 +229,25 @@ void ZCC_InitOperators() { PEX_PostDec , (PType **)&TypeUInt32, EvalIdentity }, { PEX_PostDec , (PType **)&TypeFloat64, EvalIdentity }, - { PEX_PreInc , (PType **)&TypeSInt32, EvalIncInt32 }, - { PEX_PreInc , (PType **)&TypeUInt32, EvalIncInt32 }, - { PEX_PreInc , (PType **)&TypeFloat64, EvalIncFloat64 }, + { PEX_PreInc , (PType **)&TypeSInt32, [](auto *val) { val->IntVal += 1; return val; } }, + { PEX_PreInc , (PType **)&TypeUInt32, [](auto *val) { val->UIntVal += 1; return val; } }, + { PEX_PreInc , (PType **)&TypeFloat64, [](auto *val) { val->DoubleVal += 1; return val; } }, - { PEX_PreDec , (PType **)&TypeSInt32, EvalDecInt32 }, - { PEX_PreDec , (PType **)&TypeUInt32, EvalDecInt32 }, - { PEX_PreDec , (PType **)&TypeFloat64, EvalDecFloat64 }, + { PEX_PreDec , (PType **)&TypeSInt32, [](auto *val) { val->IntVal -= 1; return val; } }, + { PEX_PreDec , (PType **)&TypeUInt32, [](auto *val) { val->UIntVal -= 1; return val; } }, + { PEX_PreDec , (PType **)&TypeFloat64, [](auto *val) { val->DoubleVal -= 1; return val; } }, - { PEX_Negate , (PType **)&TypeSInt32, EvalNegateInt32 }, - { PEX_Negate , (PType **)&TypeFloat64, EvalNegateFloat64 }, + { PEX_Negate , (PType **)&TypeSInt32, [](auto *val) { val->IntVal = -val->IntVal; return val; } }, + { PEX_Negate , (PType **)&TypeFloat64, [](auto *val) { val->DoubleVal = -val->DoubleVal; return val; } }, { PEX_AntiNegate , (PType **)&TypeSInt32, EvalIdentity }, { PEX_AntiNegate , (PType **)&TypeUInt32, EvalIdentity }, { PEX_AntiNegate , (PType **)&TypeFloat64, EvalIdentity }, - { PEX_BitNot , (PType **)&TypeSInt32, EvalBitNot }, - { PEX_BitNot , (PType **)&TypeUInt32, EvalBitNot }, + { PEX_BitNot , (PType **)&TypeSInt32, [](auto *val) { val->IntVal = ~val->IntVal; return val; } }, + { PEX_BitNot , (PType **)&TypeUInt32, [](auto *val) { val->UIntVal = ~val->UIntVal; return val; } }, - { PEX_BoolNot , (PType **)&TypeBool, EvalBoolNot }, + { PEX_BoolNot , (PType **)&TypeBool, [](auto *val) { val->IntVal = !val->IntVal; return val; } }, }; for (size_t i = 0; i < countof(UnaryOpInit); ++i) { @@ -499,62 +257,62 @@ void ZCC_InitOperators() // Binary operators static const OpProto2 BinaryOpInit[] = { - { PEX_Add , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalAddInt32 }, - { PEX_Add , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalAddInt32 }, - { PEX_Add , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalAddFloat64 }, + { PEX_Add , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal += r->IntVal; return l; } }, + { PEX_Add , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal += r->UIntVal; return l; } }, + { PEX_Add , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal += r->DoubleVal; return l; } }, - { PEX_Sub , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalSubInt32 }, - { PEX_Sub , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalSubInt32 }, - { PEX_Sub , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalSubFloat64 }, + { PEX_Sub , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal -= r->IntVal; return l; } }, + { PEX_Sub , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal -= r->UIntVal; return l; } }, + { PEX_Sub , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal -= r->DoubleVal; return l; } }, - { PEX_Mul , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalMulSInt32 }, - { PEX_Mul , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalMulUInt32 }, - { PEX_Mul , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalMulFloat64 }, + { PEX_Mul , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal *= r->IntVal; return l; } }, + { PEX_Mul , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal *= r->UIntVal; return l; } }, + { PEX_Mul , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal *= r->DoubleVal; return l; } }, - { PEX_Div , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalDivSInt32 }, - { PEX_Div , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalDivUInt32 }, - { PEX_Div , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalDivFloat64 }, + { PEX_Div , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal /= r->IntVal; return l; } }, + { PEX_Div , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal /= r->UIntVal; return l; } }, + { PEX_Div , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal /= r->DoubleVal; return l; } }, - { PEX_Mod , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalModSInt32 }, - { PEX_Mod , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalModUInt32 }, - { PEX_Mod , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalModFloat64 }, + { PEX_Mod , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal %= r->IntVal; return l; } }, + { PEX_Mod , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal %= r->UIntVal; return l; } }, + { PEX_Mod , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal = luai_nummod(l->DoubleVal, r->DoubleVal); return l; } }, - { PEX_Pow , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalPow }, + { PEX_Pow , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal = pow(l->DoubleVal, r->DoubleVal); return l; } }, { PEX_Concat , (PType **)&TypeString, (PType **)&TypeString, (PType **)&TypeString, EvalConcat }, - { PEX_BitAnd , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalBitAnd }, - { PEX_BitAnd , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalBitAnd }, + { PEX_BitAnd , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal &= r->IntVal; return l; } }, + { PEX_BitAnd , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal &= r->UIntVal; return l; } }, - { PEX_BitOr , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalBitOr }, - { PEX_BitOr , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalBitOr }, + { PEX_BitOr , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal |= r->IntVal; return l; } }, + { PEX_BitOr , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal |= r->UIntVal; return l; } }, - { PEX_BitXor , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalBitXor }, - { PEX_BitXor , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalBitXor }, + { PEX_BitXor , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal ^= r->IntVal; return l; } }, + { PEX_BitXor , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal ^= r->UIntVal; return l; } }, - { PEX_BoolAnd , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalBoolAnd }, - { PEX_BoolAnd , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalBoolAnd }, + { PEX_BoolAnd , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->IntVal && r->IntVal; l->Type = TypeBool; return l; } }, + { PEX_BoolAnd , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal && r->UIntVal; l->Type = TypeBool; return l; } }, - { PEX_BoolOr , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalBoolOr }, - { PEX_BoolOr , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalBoolOr }, + { PEX_BoolOr , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->IntVal || r->IntVal; l->Type = TypeBool; return l; } }, + { PEX_BoolOr , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal || r->UIntVal; l->Type = TypeBool; return l; } }, - { PEX_LeftShift , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeUInt32, EvalSHL }, - { PEX_LeftShift , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalSHL }, + { PEX_LeftShift , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal <<= r->UIntVal; return l; } }, + { PEX_LeftShift , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal <<= r->UIntVal; return l; } }, - { PEX_RightShift , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeUInt32, EvalSHR_S }, - { PEX_RightShift , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalSHR_U }, + { PEX_RightShift , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal >>= r->UIntVal; return l; } }, + { PEX_RightShift , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal >>= r->UIntVal; return l; } }, - { PEX_LT , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalLTSInt32 }, - { PEX_LT , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalLTUInt32 }, - { PEX_LT , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalLTFloat64 }, + { PEX_LT , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->IntVal < r->IntVal; l->Type = TypeBool; return l; } }, + { PEX_LT , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal < r->UIntVal; l->Type = TypeBool; return l; } }, + { PEX_LT , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->IntVal = l->DoubleVal < r->DoubleVal; l->Type = TypeBool; return l; } }, - { PEX_LTEQ , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalLTEQSInt32 }, - { PEX_LTEQ , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalLTEQUInt32 }, - { PEX_LTEQ , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalLTEQFloat64 }, + { PEX_LTEQ , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->IntVal <= r->IntVal; l->Type = TypeBool; return l; } }, + { PEX_LTEQ , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal <= r->UIntVal; l->Type = TypeBool; return l; } }, + { PEX_LTEQ , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->IntVal = l->DoubleVal <= r->DoubleVal; l->Type = TypeBool; return l; } }, - { PEX_EQEQ , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalEQEQSInt32 }, - { PEX_EQEQ , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalEQEQUInt32 }, - { PEX_EQEQ , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalEQEQFloat64 }, + { PEX_EQEQ , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->IntVal == r->IntVal; l->Type = TypeBool; return l; } }, + { PEX_EQEQ , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal == r->UIntVal; l->Type = TypeBool; return l; } }, + { PEX_EQEQ , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->IntVal = l->DoubleVal == r->DoubleVal; l->Type = TypeBool; return l; } }, { PEX_LTGTEQ , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalLTGTEQSInt32 }, { PEX_LTGTEQ , (PType **)&TypeSInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalLTGTEQUInt32 }, diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index ad7e9e930..d8f20dfe5 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -240,7 +240,7 @@ ACTOR Actor native //: Thinker action native A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true); action native A_CustomComboAttack(class missiletype, float spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true); action native A_Burst(class chunktype); - action native A_Blast(int flags = 0, int strength = 255, int radius = 255, float speed = 20, class blasteffect = "BlastEffect", sound blastsound = "BlastRadius"); + action native A_Blast(int flags = 0, int strength = 255, float radius = 255, float speed = 20, class blasteffect = "BlastEffect", sound blastsound = "BlastRadius"); action native A_RadiusThrust(int force = 128, int distance = -1, int flags = RTF_AFFECTSOURCE, int fullthrustdistance = 0); action native A_Explode(int damage = -1, int distance = -1, int flags = XF_HURTSOURCE, bool alert = false, int fulldamagedistance = 0, int nails = 0, int naildamage = 10, class pufftype = "BulletPuff"); action native A_Stop(); @@ -251,7 +251,7 @@ ACTOR Actor native //: Thinker action native A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = ""); action native A_ClearLastHeard(); action native A_ClearTarget(); - action native state A_CheckLOF(state jump, int flags = 0, float range = 0, float minrange = 0, float angle = 0, float pitch = 0, float offsetheight = 0, float offsetwidth = 0, int ptr_target = AAPTR_DEFAULT); + action native state A_CheckLOF(state jump, int flags = 0, float range = 0, float minrange = 0, float angle = 0, float pitch = 0, float offsetheight = 0, float offsetwidth = 0, int ptr_target = AAPTR_DEFAULT, float offsetforward = 0); action native state A_JumpIfTargetInLOS (state label, float/*angle*/ fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); action native state A_JumpIfInTargetLOS (state label, float/*angle*/ fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); action native bool A_SelectWeapon(class whichweapon); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index e5733e033..3060c2c2d 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -526,6 +526,7 @@ enum CBF_SETTRACER = 1 << 3, //^ but with tracer. CBF_SETONPTR = 1 << 4, //Sets the pointer change on the actor doing the checking instead of self. CBF_DROPOFF = 1 << 5, //Check for dropoffs. + CBF_NOACTORS = 1 << 6, //Don't check actors. }; enum diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index faf953784..6f1ef060d 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1853,6 +1853,7 @@ MISCMNU_QUERYIWAD = "Show IWAD selection dialog"; MISCMNU_ALLCHEATS = "Enable cheats from all games"; MISCMNU_ENABLEAUTOSAVES = "Enable autosaves"; MISCMNU_AUTOSAVECOUNT = "Number of autosaves"; +MISCMNU_SAVELOADCONFIRMATION = "Save/Load confirmation"; MISCMNU_DEHLOAD = "Load *.deh/*.bex lumps"; MISCMNU_CACHENODES = "Cache nodes"; MISCMNU_CACHETIME = "Time threshold for node caching"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 8a35edb62..c07ae9411 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -904,6 +904,7 @@ OptionMenu "MiscOptions" StaticText " " Option "$MISCMNU_ALLCHEATS", "allcheats", "OnOff" Option "$MISCMNU_ENABLEAUTOSAVES", "disableautosave", "Autosave" + Option "$MISCMNU_SAVELOADCONFIRMATION", "saveloadconfirmation", "OnOff" Slider "$MISCMNU_AUTOSAVECOUNT", "autosavecount", 1, 20, 1, 0 Option "$MISCMNU_DEHLOAD", "dehload", "dehopt" StaticText " " @@ -1689,6 +1690,7 @@ OptionValue ForceRatios 5.0, "17:10" 2.0, "16:10" 4.0, "5:4" + 6.0, "21:9" } OptionValue Ratios { @@ -1696,6 +1698,7 @@ OptionValue Ratios 1.0, "16:9" 2.0, "16:10" 3.0, "17:10" + 6.0, "21:9" -1, "$OPTVAL_ALL" } OptionValue RatiosTFT @@ -1705,6 +1708,7 @@ OptionValue RatiosTFT 1.0, "16:9" 2.0, "16:10" 3.0, "17:10" + 6.0, "21:9" -1, "$OPTVAL_ALL" }