mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-27 06:12:19 +00:00
Merge branch 'master' of https://github.com/rheit/zdoom
# Conflicts: # src/posix/sdl/hardware.cpp
This commit is contained in:
commit
0bcbacea53
30 changed files with 759 additions and 923 deletions
|
@ -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 ())
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"; }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
159
src/p_trace.cpp
159
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<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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
174
src/portal.cpp
174
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;
|
||||
|
|
11
src/portal.h
11
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<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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ()
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue