mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-24 12:51:09 +00:00
Merge branch 'master' of https://github.com/rheit/zdoom
This commit is contained in:
commit
8bc7a0a24e
18 changed files with 269 additions and 222 deletions
|
@ -369,14 +369,6 @@ bool FCajunMaster::DoAddBot (BYTE *info, botskill_t skill)
|
||||||
|
|
||||||
D_ReadUserInfoStrings (bnum, &info, false);
|
D_ReadUserInfoStrings (bnum, &info, false);
|
||||||
|
|
||||||
if (!deathmatch && playerstarts[bnum].type == 0)
|
|
||||||
{
|
|
||||||
Printf ("%s tried to join, but there was no player %d start\n",
|
|
||||||
players[bnum].userinfo.GetName(), bnum+1);
|
|
||||||
ClearPlayer (bnum, false); // Make the bot inactive again
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
multiplayer = true; //Prevents cheating and so on; emulates real netgame (almost).
|
multiplayer = true; //Prevents cheating and so on; emulates real netgame (almost).
|
||||||
players[bnum].Bot = new DBot;
|
players[bnum].Bot = new DBot;
|
||||||
players[bnum].Bot->player = &players[bnum];
|
players[bnum].Bot->player = &players[bnum];
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
|
|
||||||
static FRandom pr_pickteam ("PickRandomTeam");
|
static FRandom pr_pickteam ("PickRandomTeam");
|
||||||
|
|
||||||
CVAR (Float, autoaim, 5000.f, CVAR_USERINFO | CVAR_ARCHIVE);
|
CVAR (Float, autoaim, 35.f, CVAR_USERINFO | CVAR_ARCHIVE);
|
||||||
CVAR (String, name, "Player", CVAR_USERINFO | CVAR_ARCHIVE);
|
CVAR (String, name, "Player", CVAR_USERINFO | CVAR_ARCHIVE);
|
||||||
CVAR (Color, color, 0x40cf00, CVAR_USERINFO | CVAR_ARCHIVE);
|
CVAR (Color, color, 0x40cf00, CVAR_USERINFO | CVAR_ARCHIVE);
|
||||||
CVAR (Int, colorset, 0, CVAR_USERINFO | CVAR_ARCHIVE);
|
CVAR (Int, colorset, 0, CVAR_USERINFO | CVAR_ARCHIVE);
|
||||||
|
@ -518,9 +518,9 @@ void D_UserInfoChanged (FBaseCVar *cvar)
|
||||||
autoaim = 0.0f;
|
autoaim = 0.0f;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (autoaim > 5000.0f)
|
else if (autoaim > 35.0f)
|
||||||
{
|
{
|
||||||
autoaim = 5000.f;
|
autoaim = 35.f;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -492,6 +492,7 @@ public:
|
||||||
crouchdir = 0;
|
crouchdir = 0;
|
||||||
crouching = 0;
|
crouching = 0;
|
||||||
crouchviewdelta = 0;
|
crouchviewdelta = 0;
|
||||||
|
viewheight = mo->ViewHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanCrouch() const
|
bool CanCrouch() const
|
||||||
|
|
|
@ -1422,6 +1422,8 @@ bool G_CheckSpot (int playernum, FPlayerStart *mthing)
|
||||||
fixed_t z, oldz;
|
fixed_t z, oldz;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (mthing->type == 0) return false;
|
||||||
|
|
||||||
x = mthing->x;
|
x = mthing->x;
|
||||||
y = mthing->y;
|
y = mthing->y;
|
||||||
z = mthing->z;
|
z = mthing->z;
|
||||||
|
@ -1573,6 +1575,11 @@ void G_DeathMatchSpawnPlayer (int playernum)
|
||||||
//
|
//
|
||||||
FPlayerStart *G_PickPlayerStart(int playernum, int flags)
|
FPlayerStart *G_PickPlayerStart(int playernum, int flags)
|
||||||
{
|
{
|
||||||
|
if (AllPlayerStarts.Size() == 0) // No starts to pick
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if ((level.flags2 & LEVEL2_RANDOMPLAYERSTARTS) || (flags & PPS_FORCERANDOM) ||
|
if ((level.flags2 & LEVEL2_RANDOMPLAYERSTARTS) || (flags & PPS_FORCERANDOM) ||
|
||||||
playerstarts[playernum].type == 0)
|
playerstarts[playernum].type == 0)
|
||||||
{
|
{
|
||||||
|
@ -1624,6 +1631,18 @@ static void G_QueueBody (AActor *body)
|
||||||
translationtables[TRANSLATION_PlayerCorpses][modslot]->UpdateNative();
|
translationtables[TRANSLATION_PlayerCorpses][modslot]->UpdateNative();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int skinidx = body->player->userinfo.GetSkin();
|
||||||
|
|
||||||
|
if (0 != skinidx && !(body->flags4 & MF4_NOSKIN))
|
||||||
|
{
|
||||||
|
// Apply skin's scale to actor's scale, it will be lost otherwise
|
||||||
|
const AActor *const defaultActor = body->GetDefault();
|
||||||
|
const FPlayerSkin &skin = skins[skinidx];
|
||||||
|
|
||||||
|
body->scaleX = Scale(body->scaleX, skin.ScaleX, defaultActor->scaleX);
|
||||||
|
body->scaleY = Scale(body->scaleY, skin.ScaleY, defaultActor->scaleY);
|
||||||
|
}
|
||||||
|
|
||||||
bodyqueslot++;
|
bodyqueslot++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2629,12 +2648,12 @@ bool G_ProcessIFFDemo (FString &mapname)
|
||||||
|
|
||||||
if (uncompSize > 0)
|
if (uncompSize > 0)
|
||||||
{
|
{
|
||||||
BYTE *uncompressed = new BYTE[uncompSize];
|
BYTE *uncompressed = (BYTE*)M_Malloc(uncompSize);
|
||||||
int r = uncompress (uncompressed, &uncompSize, demo_p, uLong(zdembodyend - demo_p));
|
int r = uncompress (uncompressed, &uncompSize, demo_p, uLong(zdembodyend - demo_p));
|
||||||
if (r != Z_OK)
|
if (r != Z_OK)
|
||||||
{
|
{
|
||||||
Printf ("Could not decompress demo! %s\n", M_ZLibError(r).GetChars());
|
Printf ("Could not decompress demo! %s\n", M_ZLibError(r).GetChars());
|
||||||
delete[] uncompressed;
|
M_Free(uncompressed);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
M_Free (demobuffer);
|
M_Free (demobuffer);
|
||||||
|
|
119
src/g_level.cpp
119
src/g_level.cpp
|
@ -1195,74 +1195,83 @@ void G_FinishTravel ()
|
||||||
TThinkerIterator<APlayerPawn> it (STAT_TRAVELLING);
|
TThinkerIterator<APlayerPawn> it (STAT_TRAVELLING);
|
||||||
APlayerPawn *pawn, *pawndup, *oldpawn, *next;
|
APlayerPawn *pawn, *pawndup, *oldpawn, *next;
|
||||||
AInventory *inv;
|
AInventory *inv;
|
||||||
|
FPlayerStart *start;
|
||||||
|
int pnum;
|
||||||
|
|
||||||
next = it.Next ();
|
next = it.Next ();
|
||||||
while ( (pawn = next) != NULL)
|
while ( (pawn = next) != NULL)
|
||||||
{
|
{
|
||||||
next = it.Next ();
|
next = it.Next ();
|
||||||
|
pnum = int(pawn->player - players);
|
||||||
pawn->ChangeStatNum (STAT_PLAYER);
|
pawn->ChangeStatNum (STAT_PLAYER);
|
||||||
pawndup = pawn->player->mo;
|
pawndup = pawn->player->mo;
|
||||||
|
start = NULL;
|
||||||
assert (pawn != pawndup);
|
assert (pawn != pawndup);
|
||||||
if (pawndup == NULL)
|
if (pawndup == NULL)
|
||||||
{ // Oh no! there was no start for this player!
|
{ // Oh no! there was no start for this player!
|
||||||
pawn->flags |= MF_NOSECTOR|MF_NOBLOCKMAP;
|
start = G_PickPlayerStart(pnum, PPS_FORCERANDOM);
|
||||||
pawn->Destroy ();
|
if (start != NULL) pawndup = P_SpawnPlayer(start, pnum, (level.flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0);
|
||||||
|
if (pawndup == NULL)
|
||||||
|
{
|
||||||
|
pawn->flags |= MF_NOSECTOR | MF_NOBLOCKMAP;
|
||||||
|
pawn->Destroy();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (start == NULL) start = G_PickPlayerStart(pnum, 0);
|
||||||
|
oldpawn = pawndup;
|
||||||
|
|
||||||
|
// The player being spawned here is a short lived dummy and
|
||||||
|
// must not start any ENTER script or big problems will happen.
|
||||||
|
pawndup = P_SpawnPlayer(start, pnum, SPF_TEMPPLAYER);
|
||||||
|
if (!(changeflags & CHANGELEVEL_KEEPFACING))
|
||||||
{
|
{
|
||||||
oldpawn = pawndup;
|
pawn->angle = pawndup->angle;
|
||||||
|
pawn->pitch = pawndup->pitch;
|
||||||
|
}
|
||||||
|
pawn->SetXYZ(pawndup->X(), pawndup->Y(), pawndup->Z());
|
||||||
|
pawn->velx = pawndup->velx;
|
||||||
|
pawn->vely = pawndup->vely;
|
||||||
|
pawn->velz = pawndup->velz;
|
||||||
|
pawn->Sector = pawndup->Sector;
|
||||||
|
pawn->floorz = pawndup->floorz;
|
||||||
|
pawn->ceilingz = pawndup->ceilingz;
|
||||||
|
pawn->dropoffz = pawndup->dropoffz;
|
||||||
|
pawn->floorsector = pawndup->floorsector;
|
||||||
|
pawn->floorpic = pawndup->floorpic;
|
||||||
|
pawn->floorterrain = pawndup->floorterrain;
|
||||||
|
pawn->ceilingsector = pawndup->ceilingsector;
|
||||||
|
pawn->ceilingpic = pawndup->ceilingpic;
|
||||||
|
pawn->floorclip = pawndup->floorclip;
|
||||||
|
pawn->waterlevel = pawndup->waterlevel;
|
||||||
|
pawn->target = NULL;
|
||||||
|
pawn->lastenemy = NULL;
|
||||||
|
pawn->player->mo = pawn;
|
||||||
|
pawn->player->camera = pawn;
|
||||||
|
pawn->player->viewheight = pawn->ViewHeight;
|
||||||
|
pawn->flags2 &= ~MF2_BLASTED;
|
||||||
|
DObject::StaticPointerSubstitution (oldpawn, pawn);
|
||||||
|
oldpawn->Destroy();
|
||||||
|
pawndup->Destroy ();
|
||||||
|
pawn->LinkToWorld ();
|
||||||
|
pawn->AddToHash ();
|
||||||
|
pawn->SetState(pawn->SpawnState);
|
||||||
|
pawn->player->SendPitchLimits();
|
||||||
|
|
||||||
// The player being spawned here is a short lived dummy and
|
for (inv = pawn->Inventory; inv != NULL; inv = inv->Inventory)
|
||||||
// must not start any ENTER script or big problems will happen.
|
{
|
||||||
pawndup = P_SpawnPlayer (&playerstarts[pawn->player - players], int(pawn->player - players), SPF_TEMPPLAYER);
|
inv->ChangeStatNum (STAT_INVENTORY);
|
||||||
if (!(changeflags & CHANGELEVEL_KEEPFACING))
|
inv->LinkToWorld ();
|
||||||
{
|
inv->Travelled ();
|
||||||
pawn->angle = pawndup->angle;
|
}
|
||||||
pawn->pitch = pawndup->pitch;
|
if (ib_compatflags & BCOMPATF_RESETPLAYERSPEED)
|
||||||
}
|
{
|
||||||
pawn->SetXYZ(pawndup->X(), pawndup->Y(), pawndup->Z());
|
pawn->Speed = pawn->GetDefault()->Speed;
|
||||||
pawn->velx = pawndup->velx;
|
}
|
||||||
pawn->vely = pawndup->vely;
|
if (level.FromSnapshot)
|
||||||
pawn->velz = pawndup->velz;
|
{
|
||||||
pawn->Sector = pawndup->Sector;
|
FBehavior::StaticStartTypedScripts (SCRIPT_Return, pawn, true);
|
||||||
pawn->floorz = pawndup->floorz;
|
|
||||||
pawn->ceilingz = pawndup->ceilingz;
|
|
||||||
pawn->dropoffz = pawndup->dropoffz;
|
|
||||||
pawn->floorsector = pawndup->floorsector;
|
|
||||||
pawn->floorpic = pawndup->floorpic;
|
|
||||||
pawn->floorterrain = pawndup->floorterrain;
|
|
||||||
pawn->ceilingsector = pawndup->ceilingsector;
|
|
||||||
pawn->ceilingpic = pawndup->ceilingpic;
|
|
||||||
pawn->floorclip = pawndup->floorclip;
|
|
||||||
pawn->waterlevel = pawndup->waterlevel;
|
|
||||||
pawn->target = NULL;
|
|
||||||
pawn->lastenemy = NULL;
|
|
||||||
pawn->player->mo = pawn;
|
|
||||||
pawn->player->camera = pawn;
|
|
||||||
pawn->player->viewheight = pawn->ViewHeight;
|
|
||||||
pawn->flags2 &= ~MF2_BLASTED;
|
|
||||||
DObject::StaticPointerSubstitution (oldpawn, pawn);
|
|
||||||
oldpawn->Destroy();
|
|
||||||
pawndup->Destroy ();
|
|
||||||
pawn->LinkToWorld ();
|
|
||||||
pawn->AddToHash ();
|
|
||||||
pawn->SetState(pawn->SpawnState);
|
|
||||||
pawn->player->SendPitchLimits();
|
|
||||||
|
|
||||||
for (inv = pawn->Inventory; inv != NULL; inv = inv->Inventory)
|
|
||||||
{
|
|
||||||
inv->ChangeStatNum (STAT_INVENTORY);
|
|
||||||
inv->LinkToWorld ();
|
|
||||||
inv->Travelled ();
|
|
||||||
}
|
|
||||||
if (ib_compatflags & BCOMPATF_RESETPLAYERSPEED)
|
|
||||||
{
|
|
||||||
pawn->Speed = pawn->GetDefault()->Speed;
|
|
||||||
}
|
|
||||||
if (level.FromSnapshot)
|
|
||||||
{
|
|
||||||
FBehavior::StaticStartTypedScripts (SCRIPT_Return, pawn, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1500,7 +1500,9 @@ void APowerTimeFreezer::InitEffect()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EffectTics++;
|
// Compensate for skipped tic, but beware of overflow.
|
||||||
|
if(EffectTics < INT_MAX)
|
||||||
|
EffectTics++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ void AFastProjectile::Tick ()
|
||||||
{
|
{
|
||||||
if (--ripcount <= 0)
|
if (--ripcount <= 0)
|
||||||
{
|
{
|
||||||
tm.LastRipped = NULL; // [RH] Do rip damage each step, like Hexen
|
tm.LastRipped.Clear(); // [RH] Do rip damage each step, like Hexen
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!P_TryMove (this, X() + xfrac,Y() + yfrac, true, NULL, tm))
|
if (!P_TryMove (this, X() + xfrac,Y() + yfrac, true, NULL, tm))
|
||||||
|
|
|
@ -591,6 +591,9 @@ void DIntermissionScreenCast::Drawer ()
|
||||||
// draw the current frame in the middle of the screen
|
// draw the current frame in the middle of the screen
|
||||||
if (caststate != NULL)
|
if (caststate != NULL)
|
||||||
{
|
{
|
||||||
|
double castscalex = FIXED2DBL(mDefaults->scaleX);
|
||||||
|
double castscaley = FIXED2DBL(mDefaults->scaleY);
|
||||||
|
|
||||||
int castsprite = caststate->sprite;
|
int castsprite = caststate->sprite;
|
||||||
|
|
||||||
if (!(mDefaults->flags4 & MF4_NOSKIN) &&
|
if (!(mDefaults->flags4 & MF4_NOSKIN) &&
|
||||||
|
@ -604,7 +607,15 @@ void DIntermissionScreenCast::Drawer ()
|
||||||
{
|
{
|
||||||
if (PlayerClasses[i].Type == mClass)
|
if (PlayerClasses[i].Type == mClass)
|
||||||
{
|
{
|
||||||
castsprite = skins[players[consoleplayer].userinfo.GetSkin()].sprite;
|
FPlayerSkin *skin = &skins[players[consoleplayer].userinfo.GetSkin()];
|
||||||
|
castsprite = skin->sprite;
|
||||||
|
|
||||||
|
if (!(mDefaults->flags4 & MF4_NOSKIN))
|
||||||
|
{
|
||||||
|
castscaley = FIXED2DBL(skin->ScaleY);
|
||||||
|
castscalex = FIXED2DBL(skin->ScaleX);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -615,6 +626,10 @@ void DIntermissionScreenCast::Drawer ()
|
||||||
screen->DrawTexture (pic, 160, 170,
|
screen->DrawTexture (pic, 160, 170,
|
||||||
DTA_320x200, true,
|
DTA_320x200, true,
|
||||||
DTA_FlipX, sprframe->Flip & 1,
|
DTA_FlipX, sprframe->Flip & 1,
|
||||||
|
DTA_DestHeightF, pic->GetScaledHeightDouble() * castscaley,
|
||||||
|
DTA_DestWidthF, pic->GetScaledWidthDouble() * castscalex,
|
||||||
|
DTA_RenderStyle, mDefaults->RenderStyle,
|
||||||
|
DTA_Alpha, mDefaults->alpha,
|
||||||
DTA_Translation, casttranslation,
|
DTA_Translation, casttranslation,
|
||||||
TAG_DONE);
|
TAG_DONE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -479,7 +479,8 @@ void FSliderItem::Drawer(bool selected)
|
||||||
screen->DrawText(mFont, selected? OptionSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true, TAG_DONE);
|
screen->DrawText(mFont, selected? OptionSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true, TAG_DONE);
|
||||||
|
|
||||||
int x = SmallFont->StringWidth ("Green") + 8 + mXpos;
|
int x = SmallFont->StringWidth ("Green") + 8 + mXpos;
|
||||||
DrawSlider (x, mYpos);
|
int x2 = SmallFont->StringWidth (mText) + 8 + mXpos;
|
||||||
|
DrawSlider (MAX(x2, x), mYpos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -630,14 +631,7 @@ void DPlayerMenu::Init(DMenu *parent, FListMenuDescriptor *desc)
|
||||||
li = GetItem(NAME_Autoaim);
|
li = GetItem(NAME_Autoaim);
|
||||||
if (li != NULL)
|
if (li != NULL)
|
||||||
{
|
{
|
||||||
int sel =
|
li->SetValue(0, (int)autoaim);
|
||||||
autoaim == 0 ? 0 :
|
|
||||||
autoaim <= 0.25 ? 1 :
|
|
||||||
autoaim <= 0.5 ? 2 :
|
|
||||||
autoaim <= 1 ? 3 :
|
|
||||||
autoaim <= 2 ? 4 :
|
|
||||||
autoaim <= 3 ? 5:6;
|
|
||||||
li->SetValue(0, sel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
li = GetItem(NAME_Switch);
|
li = GetItem(NAME_Switch);
|
||||||
|
@ -966,13 +960,11 @@ void DPlayerMenu::SkinChanged (FListMenuItem *li)
|
||||||
|
|
||||||
void DPlayerMenu::AutoaimChanged (FListMenuItem *li)
|
void DPlayerMenu::AutoaimChanged (FListMenuItem *li)
|
||||||
{
|
{
|
||||||
static const float ranges[] = { 0, 0.25, 0.5, 1, 2, 3, 5000 };
|
|
||||||
|
|
||||||
int sel;
|
int sel;
|
||||||
|
|
||||||
if (li->GetValue(0, &sel))
|
if (li->GetValue(0, &sel))
|
||||||
{
|
{
|
||||||
autoaim = ranges[sel];
|
autoaim = (float)sel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,9 @@ CUSTOM_CVAR( Int, r_maxparticles, 4000, CVAR_ARCHIVE )
|
||||||
{
|
{
|
||||||
if ( self == 0 )
|
if ( self == 0 )
|
||||||
self = 4000;
|
self = 4000;
|
||||||
else if ( self < 100 )
|
else if (self > 65535)
|
||||||
|
self = 65535;
|
||||||
|
else if (self < 100)
|
||||||
self = 100;
|
self = 100;
|
||||||
|
|
||||||
if ( gamestate != GS_STARTUP )
|
if ( gamestate != GS_STARTUP )
|
||||||
|
|
|
@ -445,13 +445,12 @@ struct FCheckPosition
|
||||||
// [RH] These are used by PIT_CheckThing and P_XYMovement to apply
|
// [RH] These are used by PIT_CheckThing and P_XYMovement to apply
|
||||||
// ripping damage once per tic instead of once per move.
|
// ripping damage once per tic instead of once per move.
|
||||||
bool DoRipping;
|
bool DoRipping;
|
||||||
AActor *LastRipped;
|
TMap<AActor*, bool> LastRipped;
|
||||||
int PushTime;
|
int PushTime;
|
||||||
|
|
||||||
FCheckPosition(bool rip=false)
|
FCheckPosition(bool rip=false)
|
||||||
{
|
{
|
||||||
DoRipping = rip;
|
DoRipping = rip;
|
||||||
LastRipped = NULL;
|
|
||||||
PushTime = 0;
|
PushTime = 0;
|
||||||
FromPMove = false;
|
FromPMove = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1286,9 +1286,10 @@ bool PIT_CheckThing(AActor *thing, FCheckPosition &tm)
|
||||||
{
|
{
|
||||||
if (!(tm.thing->flags6 & MF6_NOBOSSRIP) || !(thing->flags2 & MF2_BOSS))
|
if (!(tm.thing->flags6 & MF6_NOBOSSRIP) || !(thing->flags2 & MF2_BOSS))
|
||||||
{
|
{
|
||||||
if (tm.LastRipped != thing)
|
bool *check = tm.LastRipped.CheckKey(thing);
|
||||||
|
if (check == NULL || !*check)
|
||||||
{
|
{
|
||||||
tm.LastRipped = thing;
|
tm.LastRipped[thing] = true;
|
||||||
if (!(thing->flags & MF_NOBLOOD) &&
|
if (!(thing->flags & MF_NOBLOOD) &&
|
||||||
!(thing->flags2 & MF2_REFLECTIVE) &&
|
!(thing->flags2 & MF2_REFLECTIVE) &&
|
||||||
!(tm.thing->flags3 & MF3_BLOODLESSIMPACT) &&
|
!(tm.thing->flags3 & MF3_BLOODLESSIMPACT) &&
|
||||||
|
|
|
@ -4431,6 +4431,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
|
||||||
( gameaction != ga_worlddone ) &&
|
( gameaction != ga_worlddone ) &&
|
||||||
( p->mo != NULL ) &&
|
( p->mo != NULL ) &&
|
||||||
( !(p->mo->Sector->Flags & SECF_NORESPAWN) ) &&
|
( !(p->mo->Sector->Flags & SECF_NORESPAWN) ) &&
|
||||||
|
( NULL != p->attacker ) && // don't respawn on damaging floors
|
||||||
( p->mo->Sector->damageamount < TELEFRAG_DAMAGE )) // this really should be a bit smarter...
|
( p->mo->Sector->damageamount < TELEFRAG_DAMAGE )) // this really should be a bit smarter...
|
||||||
{
|
{
|
||||||
spawn_x = p->mo->X();
|
spawn_x = p->mo->X();
|
||||||
|
|
|
@ -283,6 +283,7 @@ void I_InitSound ()
|
||||||
if ((!GSnd || !GSnd->IsValid()) && IsOpenALPresent())
|
if ((!GSnd || !GSnd->IsValid()) && IsOpenALPresent())
|
||||||
{
|
{
|
||||||
Printf (TEXTCOLOR_RED"FMod Ex Sound init failed. Trying OpenAL.\n");
|
Printf (TEXTCOLOR_RED"FMod Ex Sound init failed. Trying OpenAL.\n");
|
||||||
|
I_CloseSound();
|
||||||
GSnd = new OpenALSoundRenderer;
|
GSnd = new OpenALSoundRenderer;
|
||||||
snd_backend = "openal";
|
snd_backend = "openal";
|
||||||
}
|
}
|
||||||
|
@ -300,6 +301,7 @@ void I_InitSound ()
|
||||||
if ((!GSnd || !GSnd->IsValid()) && IsFModExPresent())
|
if ((!GSnd || !GSnd->IsValid()) && IsFModExPresent())
|
||||||
{
|
{
|
||||||
Printf (TEXTCOLOR_RED"OpenAL Sound init failed. Trying FMod Ex.\n");
|
Printf (TEXTCOLOR_RED"OpenAL Sound init failed. Trying FMod Ex.\n");
|
||||||
|
I_CloseSound();
|
||||||
GSnd = new FMODSoundRenderer;
|
GSnd = new FMODSoundRenderer;
|
||||||
snd_backend = "fmod";
|
snd_backend = "fmod";
|
||||||
}
|
}
|
||||||
|
|
|
@ -4975,6 +4975,133 @@ enum RadiusGiveFlags
|
||||||
RGF_EITHER = 1 << 17,
|
RGF_EITHER = 1 << 17,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool DoRadiusGive(AActor *self, AActor *thing, const PClass *item, int amount, fixed_t distance, int flags, const PClass *filter, FName species, fixed_t mindist)
|
||||||
|
{
|
||||||
|
// [MC] We only want to make an exception for missiles here. Nothing else.
|
||||||
|
bool missilePass = !!((flags & RGF_MISSILES) && thing->isMissile());
|
||||||
|
if (thing == self)
|
||||||
|
{
|
||||||
|
if (!(flags & RGF_GIVESELF))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (thing->isMissile())
|
||||||
|
{
|
||||||
|
if (!missilePass)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//[MC] Check for a filter, species, and the related exfilter/expecies/either flag(s).
|
||||||
|
bool filterpass = DoCheckClass(thing, filter, !!(flags & RGF_EXFILTER)),
|
||||||
|
speciespass = DoCheckSpecies(thing, species, !!(flags & RGF_EXSPECIES));
|
||||||
|
|
||||||
|
if ((flags & RGF_EITHER) ? (!(filterpass || speciespass)) : (!(filterpass && speciespass)))
|
||||||
|
{
|
||||||
|
if (thing != self) //Don't let filter and species obstruct RGF_GIVESELF.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check for target, master, and tracer flagging.
|
||||||
|
bool targetPass = true;
|
||||||
|
bool masterPass = true;
|
||||||
|
bool tracerPass = true;
|
||||||
|
bool ptrPass = false;
|
||||||
|
if ((thing != self) && (flags & (RGF_NOTARGET | RGF_NOMASTER | RGF_NOTRACER)))
|
||||||
|
{
|
||||||
|
if ((thing == self->target) && (flags & RGF_NOTARGET))
|
||||||
|
targetPass = false;
|
||||||
|
if ((thing == self->master) && (flags & RGF_NOMASTER))
|
||||||
|
masterPass = false;
|
||||||
|
if ((thing == self->tracer) && (flags & RGF_NOTRACER))
|
||||||
|
tracerPass = false;
|
||||||
|
|
||||||
|
ptrPass = (flags & RGF_INCLUSIVE) ? (targetPass || masterPass || tracerPass) : (targetPass && masterPass && tracerPass);
|
||||||
|
|
||||||
|
//We should not care about what the actor is here. It's safe to abort this actor.
|
||||||
|
if (!ptrPass)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Next, actor flag checking.
|
||||||
|
bool selfPass = !!((flags & RGF_GIVESELF) && thing == self);
|
||||||
|
bool corpsePass = !!((flags & RGF_CORPSES) && thing->flags & MF_CORPSE);
|
||||||
|
bool killedPass = !!((flags & RGF_KILLED) && thing->flags6 & MF6_KILLED);
|
||||||
|
bool monsterPass = !!((flags & RGF_MONSTERS) && thing->flags3 & MF3_ISMONSTER);
|
||||||
|
bool objectPass = !!((flags & RGF_OBJECTS) && (thing->player == NULL) && (!(thing->flags3 & MF3_ISMONSTER))
|
||||||
|
&& ((thing->flags & MF_SHOOTABLE) || (thing->flags6 & MF6_VULNERABLE)));
|
||||||
|
bool playerPass = !!((flags & RGF_PLAYERS) && (thing->player != NULL) && (thing->player->mo == thing));
|
||||||
|
bool voodooPass = !!((flags & RGF_VOODOO) && (thing->player != NULL) && (thing->player->mo != thing));
|
||||||
|
//Self calls priority over the rest of this.
|
||||||
|
if (!selfPass)
|
||||||
|
{
|
||||||
|
//If it's specifically a monster/object/player/voodoo... Can be either or...
|
||||||
|
if (monsterPass || objectPass || playerPass || voodooPass)
|
||||||
|
{
|
||||||
|
//...and is dead, without desire to give to the dead...
|
||||||
|
if (((thing->health <= 0) && !(corpsePass || killedPass)))
|
||||||
|
{
|
||||||
|
//Skip!
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool itemPass = !!((flags & RGF_ITEMS) && thing->IsKindOf(RUNTIME_CLASS(AInventory)));
|
||||||
|
|
||||||
|
if (selfPass || monsterPass || corpsePass || killedPass || itemPass || objectPass || missilePass || playerPass || voodooPass)
|
||||||
|
{
|
||||||
|
|
||||||
|
fixedvec3 diff = self->Vec3To(thing);
|
||||||
|
diff.z += (thing->height - self->height) / 2;
|
||||||
|
if (flags & RGF_CUBE)
|
||||||
|
{ // check if inside a cube
|
||||||
|
double dx = fabs((double)(diff.x));
|
||||||
|
double dy = fabs((double)(diff.y));
|
||||||
|
double dz = fabs((double)(diff.z));
|
||||||
|
double dist = (double)distance;
|
||||||
|
double min = (double)mindist;
|
||||||
|
if ((dx > dist || dy > dist || dz > dist) || (min && (dx < min && dy < min && dz < min)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // check if inside a sphere
|
||||||
|
double distsquared = double(distance) * double(distance);
|
||||||
|
double minsquared = double(mindist) * double(mindist);
|
||||||
|
double lengthsquared = TVector3<double>(diff.x, diff.y, diff.z).LengthSquared();
|
||||||
|
if (lengthsquared > distsquared || (minsquared && (lengthsquared < minsquared)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & RGF_NOSIGHT) || P_CheckSight(thing, self, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))
|
||||||
|
{ // OK to give; target is in direct path, or the monster doesn't care about it being in line of sight.
|
||||||
|
AInventory *gift = static_cast<AInventory *>(Spawn(item, 0, 0, 0, NO_REPLACE));
|
||||||
|
if (gift->IsKindOf(RUNTIME_CLASS(AHealth)))
|
||||||
|
{
|
||||||
|
gift->Amount *= amount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gift->Amount = amount;
|
||||||
|
}
|
||||||
|
gift->flags |= MF_DROPPED;
|
||||||
|
gift->ClearCounters();
|
||||||
|
if (!gift->CallTryPickup(thing))
|
||||||
|
{
|
||||||
|
gift->Destroy();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
|
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
|
||||||
{
|
{
|
||||||
ACTION_PARAM_START(7);
|
ACTION_PARAM_START(7);
|
||||||
|
@ -4997,126 +5124,22 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
|
||||||
{
|
{
|
||||||
amount = 1;
|
amount = 1;
|
||||||
}
|
}
|
||||||
FBlockThingsIterator it(FBoundingBox(self->X(), self->Y(), distance));
|
|
||||||
|
|
||||||
AActor *thing;
|
AActor *thing;
|
||||||
bool given = false;
|
bool given = false;
|
||||||
while ((thing = it.Next()))
|
if (flags & RGF_MISSILES)
|
||||||
{
|
{
|
||||||
//[MC] Check for a filter, species, and the related exfilter/expecies/either flag(s).
|
TThinkerIterator<AActor> it;
|
||||||
bool filterpass = DoCheckClass(thing, filter, !!(flags & RGF_EXFILTER)),
|
while ((thing = it.Next()))
|
||||||
speciespass = DoCheckSpecies(thing, species, !!(flags & RGF_EXSPECIES));
|
|
||||||
|
|
||||||
if ((flags & RGF_EITHER) ? (!(filterpass || speciespass)) : (!(filterpass && speciespass)))
|
|
||||||
{
|
{
|
||||||
if (thing != self) //Don't let filter and species obstruct RGF_GIVESELF.
|
if (DoRadiusGive(self, thing, item, amount, distance, flags, filter, species, mindist)) given = true;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (thing == self)
|
else
|
||||||
|
{
|
||||||
|
FBlockThingsIterator it(FBoundingBox(self->X(), self->Y(), distance));
|
||||||
|
while ((thing = it.Next()))
|
||||||
{
|
{
|
||||||
if (!(flags & RGF_GIVESELF))
|
if (DoRadiusGive(self, thing, item, amount, distance, flags, filter, species, mindist)) given = true;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check for target, master, and tracer flagging.
|
|
||||||
bool targetPass = true;
|
|
||||||
bool masterPass = true;
|
|
||||||
bool tracerPass = true;
|
|
||||||
bool ptrPass = false;
|
|
||||||
if ((thing != self) && (flags & (RGF_NOTARGET | RGF_NOMASTER | RGF_NOTRACER)))
|
|
||||||
{
|
|
||||||
if ((thing == self->target) && (flags & RGF_NOTARGET))
|
|
||||||
targetPass = false;
|
|
||||||
if ((thing == self->master) && (flags & RGF_NOMASTER))
|
|
||||||
masterPass = false;
|
|
||||||
if ((thing == self->tracer) && (flags & RGF_NOTRACER))
|
|
||||||
tracerPass = false;
|
|
||||||
|
|
||||||
ptrPass = (flags & RGF_INCLUSIVE) ? (targetPass || masterPass || tracerPass) : (targetPass && masterPass && tracerPass);
|
|
||||||
|
|
||||||
//We should not care about what the actor is here. It's safe to abort this actor.
|
|
||||||
if (!ptrPass)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Next, actor flag checking.
|
|
||||||
bool selfPass = !!((flags & RGF_GIVESELF) && thing == self);
|
|
||||||
bool corpsePass = !!((flags & RGF_CORPSES) && thing->flags & MF_CORPSE);
|
|
||||||
bool killedPass = !!((flags & RGF_KILLED) && thing->flags6 & MF6_KILLED);
|
|
||||||
bool monsterPass = !!((flags & RGF_MONSTERS) && thing->flags3 & MF3_ISMONSTER);
|
|
||||||
bool objectPass = !!((flags & RGF_OBJECTS) && (thing->player == NULL) && (!(thing->flags3 & MF3_ISMONSTER))
|
|
||||||
&& ((thing->flags & MF_SHOOTABLE) || (thing->flags6 & MF6_VULNERABLE)));
|
|
||||||
bool playerPass = !!((flags & RGF_PLAYERS) && (thing->player != NULL) && (thing->player->mo == thing));
|
|
||||||
bool voodooPass = !!((flags & RGF_VOODOO) && (thing->player != NULL) && (thing->player->mo != thing));
|
|
||||||
//Self calls priority over the rest of this.
|
|
||||||
if (!selfPass)
|
|
||||||
{
|
|
||||||
//If it's specifically a monster/object/player/voodoo... Can be either or...
|
|
||||||
if (monsterPass || objectPass || playerPass || voodooPass)
|
|
||||||
{
|
|
||||||
//...and is dead, without desire to give to the dead...
|
|
||||||
if (((thing->health <= 0) && !(corpsePass || killedPass)))
|
|
||||||
{
|
|
||||||
//Skip!
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool itemPass = !!((flags & RGF_ITEMS) && thing->IsKindOf(RUNTIME_CLASS(AInventory)));
|
|
||||||
bool missilePass = !!((flags & RGF_MISSILES) && thing->flags & MF_MISSILE);
|
|
||||||
|
|
||||||
if (selfPass || monsterPass || corpsePass || killedPass || itemPass || objectPass || missilePass || playerPass || voodooPass)
|
|
||||||
{
|
|
||||||
|
|
||||||
fixedvec3 diff = self->Vec3To(thing);
|
|
||||||
diff.z += (thing->height - self->height) / 2;
|
|
||||||
if (flags & RGF_CUBE)
|
|
||||||
{ // check if inside a cube
|
|
||||||
double dx = fabs((double)(diff.x));
|
|
||||||
double dy = fabs((double)(diff.y));
|
|
||||||
double dz = fabs((double)(diff.z));
|
|
||||||
double dist = (double)distance;
|
|
||||||
double min = (double)mindist;
|
|
||||||
if ((dx > dist || dy > dist || dz > dist) || (min && (dx < min && dy < min && dz < min)))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // check if inside a sphere
|
|
||||||
double distsquared = double(distance) * double(distance);
|
|
||||||
double minsquared = double(mindist) * double(mindist);
|
|
||||||
double lengthsquared = TVector3<double>(diff.x, diff.y, diff.z).LengthSquared();
|
|
||||||
if (lengthsquared > distsquared || (minsquared && (lengthsquared < minsquared)))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & RGF_NOSIGHT) || P_CheckSight(thing, self, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))
|
|
||||||
{ // OK to give; target is in direct path, or the monster doesn't care about it being in line of sight.
|
|
||||||
AInventory *gift = static_cast<AInventory *>(Spawn(item, 0, 0, 0, NO_REPLACE));
|
|
||||||
if (gift->IsKindOf(RUNTIME_CLASS(AHealth)))
|
|
||||||
{
|
|
||||||
gift->Amount *= amount;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gift->Amount = amount;
|
|
||||||
}
|
|
||||||
gift->flags |= MF_DROPPED;
|
|
||||||
gift->ClearCounters();
|
|
||||||
if (!gift->CallTryPickup(thing))
|
|
||||||
{
|
|
||||||
gift->Destroy();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
given = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ACTION_SET_RESULT(given);
|
ACTION_SET_RESULT(given);
|
||||||
|
|
|
@ -1424,13 +1424,11 @@ void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int real
|
||||||
*cleany = cy2;
|
*cleany = cy2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*cleanx > 1 && *cleany > 1 && *cleanx != *cleany)
|
if (*cleanx < *cleany)
|
||||||
{
|
*cleany = *cleanx;
|
||||||
if (*cleanx < *cleany)
|
else
|
||||||
*cleany = *cleanx;
|
*cleanx = *cleany;
|
||||||
else
|
|
||||||
*cleanx = *cleany;
|
|
||||||
}
|
|
||||||
if (_cx1 != NULL) *_cx1 = cx1;
|
if (_cx1 != NULL) *_cx1 = cx1;
|
||||||
if (_cx2 != NULL) *_cx2 = cx2;
|
if (_cx2 != NULL) *_cx2 = cx2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -525,6 +525,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_DISPLAYCHANGE:
|
case WM_DISPLAYCHANGE:
|
||||||
|
case WM_STYLECHANGED:
|
||||||
if (SpawnEAXWindow)
|
if (SpawnEAXWindow)
|
||||||
{
|
{
|
||||||
SpawnEAXWindow = false;
|
SpawnEAXWindow = false;
|
||||||
|
|
|
@ -364,18 +364,6 @@ OptionValue "Gender"
|
||||||
2, "Other"
|
2, "Other"
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionValue "Autoaim"
|
|
||||||
{
|
|
||||||
0, "Never"
|
|
||||||
1, "Very low"
|
|
||||||
2, "Low"
|
|
||||||
3, "Medium"
|
|
||||||
4, "High"
|
|
||||||
5, "Very high"
|
|
||||||
6, "Always"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ListMenu "PlayerMenu"
|
ListMenu "PlayerMenu"
|
||||||
{
|
{
|
||||||
StaticTextCentered 160, 6, "$MNU_PLAYERSETUP"
|
StaticTextCentered 160, 6, "$MNU_PLAYERSETUP"
|
||||||
|
@ -414,7 +402,7 @@ ListMenu "PlayerMenu"
|
||||||
ValueText "Class", "Class"
|
ValueText "Class", "Class"
|
||||||
ValueText "Skin", "Skin"
|
ValueText "Skin", "Skin"
|
||||||
ValueText "Gender", "Gender", "Gender"
|
ValueText "Gender", "Gender", "Gender"
|
||||||
ValueText "Autoaim", "Autoaim", "Autoaim"
|
Slider "Autoaim", "Autoaim", 0, 35, 1
|
||||||
ValueText "Switch on pickup", "Switch", "OffOn"
|
ValueText "Switch on pickup", "Switch", "OffOn"
|
||||||
ValueText "Always Run", "AlwaysRun", "OnOff"
|
ValueText "Always Run", "AlwaysRun", "OnOff"
|
||||||
Class "PlayerMenu"
|
Class "PlayerMenu"
|
||||||
|
@ -710,6 +698,8 @@ OptionMenu "VideoOptions"
|
||||||
Option "Teleporter zoom", "telezoom", "OnOff"
|
Option "Teleporter zoom", "telezoom", "OnOff"
|
||||||
Slider "Earthquake shake intensity", "r_quakeintensity", 0.0, 1.0, 0.05, 2
|
Slider "Earthquake shake intensity", "r_quakeintensity", 0.0, 1.0, 0.05, 2
|
||||||
Option "Interpolate monster movement", "nomonsterinterpolation", "NoYes"
|
Option "Interpolate monster movement", "nomonsterinterpolation", "NoYes"
|
||||||
|
Slider "Menu dim", "dimamount", 0, 1.0, 0.05, 2
|
||||||
|
ColorPicker "Dim color", "dimcolor"
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in a new issue