# Conflicts:
#	src/posix/sdl/hardware.cpp
This commit is contained in:
Christoph Oelckers 2016-03-04 01:21:59 +01:00
commit 0bcbacea53
30 changed files with 759 additions and 923 deletions

View file

@ -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 ())
{

View file

@ -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<PClassPointer *>(ptype);
}

View file

@ -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)

View file

@ -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"; }

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}
}
}

View file

@ -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);

View file

@ -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<F3DFloor*> &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;i<ff.Size();i++)
{
F3DFloor * rover=ff[i];
if (!(rover->flags&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 (bf<ff_top)
{
sector->floorplane=*rover->top.plane;
sector->SetTexture(sector_t::floor, *rover->top.texture, false);
bf=ff_top;
}
}
else if (z<ff_bottom)
{
//below
if (bc>ff_bottom)
{
sector->ceilingplane=*rover->bottom.plane;
sector->SetTexture(sector_t::ceiling, *rover->bottom.texture, false);
bc=ff_bottom;
}
}
else
{
// inside
if (bf<ff_bottom)
{
sector->floorplane=*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<F3DFloor*> &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 (bf<ff_top)
{
CurSector->floorplane = *rover->top.plane;
CurSector->SetTexture(sector_t::floor, *rover->top.texture, false);
CurSector->SkyBoxes[sector_t::floor] == NULL;
bf = ff_top;
}
}
else if (z<ff_bottom)
{
//below
if (bc>ff_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 (bf<ff_bottom)
{
CurSector->floorplane = *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;

View file

@ -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

View file

@ -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;

View file

@ -173,6 +173,9 @@ struct FLinePortal
BYTE mFlags;
BYTE mDefFlags;
BYTE mAlign;
angle_t mAngleDiff;
fixed_t mSinRot;
fixed_t mCosRot;
};
extern TArray<FLinePortal> 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);

View file

@ -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;

View file

@ -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 <SDL.h>
#include <signal.h>
#include <time.h>
#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 <SDL.h>
#include <signal.h>
#include <time.h>
#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 <limit>/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 <limit>/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);
}

View file

@ -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 }
};

View file

@ -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];

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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;

View file

@ -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 ()

View file

@ -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__

View file

@ -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"

View file

@ -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 },

View file

@ -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<Actor> missiletype, float spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true);
action native A_Burst(class<Actor> chunktype);
action native A_Blast(int flags = 0, int strength = 255, int radius = 255, float speed = 20, class<Actor> blasteffect = "BlastEffect", sound blastsound = "BlastRadius");
action native A_Blast(int flags = 0, int strength = 255, float radius = 255, float speed = 20, class<Actor> 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<Actor> 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<Weapon> whichweapon);

View file

@ -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

View file

@ -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";

View file

@ -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"
}