mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-16 09:11:17 +00:00
Merge branch 'master' of https://github.com/rheit/zdoom into z_osx_pure
This commit is contained in:
commit
83c8f44cc4
20 changed files with 522 additions and 72 deletions
|
@ -3,6 +3,7 @@ cmake_minimum_required( VERSION 2.4 )
|
|||
make_release_only()
|
||||
|
||||
include( CheckFunctionExists )
|
||||
include( CheckCXXCompilerFlag )
|
||||
|
||||
# DUMB is much slower in a Debug build than a Release build, so we force a Release
|
||||
# build here, since we're not maintaining DUMB, only using it.
|
||||
|
@ -104,5 +105,9 @@ add_library( dumb
|
|||
target_link_libraries( dumb )
|
||||
|
||||
if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
|
||||
set_source_files_properties( src/it/filter.cpp PROPERTIES COMPILE_FLAGS -msse )
|
||||
CHECK_CXX_COMPILER_FLAG( -msse DUMB_CAN_USE_SSE )
|
||||
|
||||
if( DUMB_CAN_USE_SSE )
|
||||
set_source_files_properties( src/it/filter.cpp PROPERTIES COMPILE_FLAGS -msse )
|
||||
endif( DUMB_CAN_USE_SSE )
|
||||
endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
|
||||
|
|
|
@ -27,7 +27,9 @@ endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
|
|||
|
||||
option( DYN_FLUIDSYNTH "Dynamically load fluidsynth" ON )
|
||||
|
||||
option( OSX_COCOA_BACKEND "Use native Cocoa backend instead of SDL" ON )
|
||||
if( APPLE )
|
||||
option( OSX_COCOA_BACKEND "Use native Cocoa backend instead of SDL" ON )
|
||||
endif( APPLE )
|
||||
|
||||
if( CMAKE_SIZEOF_VOID_P MATCHES "8" )
|
||||
set( X64 64 )
|
||||
|
@ -548,6 +550,7 @@ set( PLAT_WIN32_SOURCES
|
|||
set( PLAT_POSIX_SOURCES
|
||||
posix/i_cd.cpp
|
||||
posix/i_movie.cpp
|
||||
posix/i_steam.cpp
|
||||
posix/i_system.cpp
|
||||
posix/st_start.cpp )
|
||||
set( PLAT_SDL_SOURCES
|
||||
|
|
10
src/actor.h
10
src/actor.h
|
@ -347,6 +347,14 @@ enum
|
|||
MF7_DONTTHRUST = 0x00000100, // Thrusting functions do not take, and do not give thrust (damage) to actors with this flag.
|
||||
MF7_ALLOWPAIN = 0x00000200, // Invulnerable or immune (via damagefactors) actors can still react to taking damage even if they don't.
|
||||
MF7_CAUSEPAIN = 0x00000400, // Damage sources with this flag can cause similar effects like ALLOWPAIN.
|
||||
MF7_THRUREFLECT = 0x00000800, // Actors who are reflective cause the missiles to not slow down or change angles.
|
||||
MF7_MIRRORREFLECT = 0x00001000, // Actor is turned directly 180 degrees around when reflected.
|
||||
MF7_AIMREFLECT = 0x00002000, // Actor is directly reflected straight back at the one who fired the projectile.
|
||||
MF7_HITTARGET = 0x00004000, // The actor the projectile dies on is set to target, provided it's targetable anyway.
|
||||
MF7_HITMASTER = 0x00008000, // Same as HITTARGET, except it's master instead of target.
|
||||
MF7_HITTRACER = 0x00010000, // Same as HITTARGET, but for tracer.
|
||||
|
||||
|
||||
|
||||
// --- mobj.renderflags ---
|
||||
|
||||
|
@ -859,7 +867,7 @@ public:
|
|||
DWORD flags4; // [RH] Even more flags!
|
||||
DWORD flags5; // OMG! We need another one.
|
||||
DWORD flags6; // Shit! Where did all the flags go?
|
||||
DWORD flags7; //
|
||||
DWORD flags7; // WHO WANTS TO BET ON 8!?
|
||||
|
||||
// [BB] If 0, everybody can see the actor, if > 0, only members of team (VisibleToTeam-1) can see it.
|
||||
DWORD VisibleToTeam;
|
||||
|
|
|
@ -430,27 +430,11 @@ int FIWadManager::IdentifyVersion (TArray<FString> &wadfiles, const char *iwad,
|
|||
}
|
||||
}
|
||||
}
|
||||
#ifdef _WIN32
|
||||
FString steam_path = I_GetSteamPath();
|
||||
if (steam_path.IsNotEmpty())
|
||||
TArray<FString> steam_path = I_GetSteamPath();
|
||||
for (i = 0; i < steam_path.Size(); ++i)
|
||||
{
|
||||
static const char *const steam_dirs[] =
|
||||
{
|
||||
"doom 2/base",
|
||||
"final doom/base",
|
||||
"heretic shadow of the serpent riders/base",
|
||||
"hexen/base",
|
||||
"hexen deathkings of the dark citadel/base",
|
||||
"ultimate doom/base",
|
||||
"DOOM 3 BFG Edition/base/wads"
|
||||
};
|
||||
steam_path += "/SteamApps/common/";
|
||||
for (i = 0; i < countof(steam_dirs); ++i)
|
||||
{
|
||||
CheckIWAD (steam_path + steam_dirs[i], &wads[0]);
|
||||
}
|
||||
CheckIWAD (steam_path[i], &wads[0]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (iwadparm != NULL && !wads[0].Path.IsEmpty())
|
||||
|
|
|
@ -116,6 +116,7 @@ CVAR (Bool, chasedemo, false, 0);
|
|||
CVAR (Bool, storesavepic, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, longsavemessages, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (String, save_dir, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
||||
CVAR (Bool, cl_waitforsave, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
||||
EXTERN_CVAR (Float, con_midtime);
|
||||
|
||||
//==========================================================================
|
||||
|
@ -2147,6 +2148,9 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
|
|||
filename = G_BuildSaveName ("demosave.zds", -1);
|
||||
}
|
||||
|
||||
if (cl_waitforsave)
|
||||
I_FreezeTime(true);
|
||||
|
||||
insave = true;
|
||||
G_SnapshotLevel ();
|
||||
|
||||
|
@ -2156,6 +2160,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
|
|||
{
|
||||
Printf ("Could not create savegame '%s'\n", filename.GetChars());
|
||||
insave = false;
|
||||
I_FreezeTime(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2232,6 +2237,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
|
|||
}
|
||||
|
||||
insave = false;
|
||||
I_FreezeTime(false);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -300,6 +300,7 @@ xx(CallACS)
|
|||
xx(Sqrt)
|
||||
xx(CheckClass)
|
||||
xx(IsPointerEqual)
|
||||
xx(Pick)
|
||||
|
||||
// Various actor names which are used internally
|
||||
xx(MapSpot)
|
||||
|
|
|
@ -1283,6 +1283,16 @@ bool PIT_CheckThing(AActor *thing, FCheckPosition &tm)
|
|||
{
|
||||
P_GiveBody(thing, -damage);
|
||||
}
|
||||
|
||||
if ((thing->flags7 & MF7_THRUREFLECT) && (thing->flags2 & MF2_REFLECTIVE) && (tm.thing->flags & MF_MISSILE))
|
||||
{
|
||||
if (tm.thing->flags2 & MF2_SEEKERMISSILE)
|
||||
{
|
||||
tm.thing->tracer = tm.thing->target;
|
||||
}
|
||||
tm.thing->target = thing;
|
||||
return true;
|
||||
}
|
||||
return false; // don't traverse any more
|
||||
}
|
||||
if (thing->flags2 & MF2_PUSHABLE && !(tm.thing->flags2 & MF2_CANNOTPUSH))
|
||||
|
@ -1643,7 +1653,7 @@ bool P_TestMobjZ(AActor *actor, bool quick, AActor **pOnmobj)
|
|||
{ // Don't clip against self
|
||||
continue;
|
||||
}
|
||||
if ((actor->flags & MF_MISSILE) && thing == actor->target)
|
||||
if ((actor->flags & MF_MISSILE) && (thing == actor->target))
|
||||
{ // Don't clip against whoever shot the missile.
|
||||
continue;
|
||||
}
|
||||
|
@ -2983,18 +2993,20 @@ bool P_BounceWall(AActor *mo)
|
|||
extern FRandom pr_bounce;
|
||||
bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop)
|
||||
{
|
||||
//Don't go through all of this if the actor is reflective and wants things to pass through them.
|
||||
if (BlockingMobj && ((BlockingMobj->flags2 & MF2_REFLECTIVE) && (BlockingMobj->flags7 & MF7_THRUREFLECT))) return true;
|
||||
if (mo && BlockingMobj && ((mo->BounceFlags & BOUNCE_AllActors)
|
||||
|| ((mo->flags & MF_MISSILE) && (!(mo->flags2 & MF2_RIP) || (BlockingMobj->flags5 & MF5_DONTRIP) || ((mo->flags6 & MF6_NOBOSSRIP) && (BlockingMobj->flags2 & MF2_BOSS))) && (BlockingMobj->flags2 & MF2_REFLECTIVE))
|
||||
|| ((BlockingMobj->player == NULL) && (!(BlockingMobj->flags3 & MF3_ISMONSTER)))
|
||||
))
|
||||
|| ((mo->flags & MF_MISSILE) && (!(mo->flags2 & MF2_RIP)
|
||||
|| (BlockingMobj->flags5 & MF5_DONTRIP)
|
||||
|| ((mo->flags6 & MF6_NOBOSSRIP) && (BlockingMobj->flags2 & MF2_BOSS))) && (BlockingMobj->flags2 & MF2_REFLECTIVE))
|
||||
|| ((BlockingMobj->player == NULL) && (!(BlockingMobj->flags3 & MF3_ISMONSTER)))))
|
||||
{
|
||||
if (mo->bouncecount > 0 && --mo->bouncecount == 0) return false;
|
||||
|
||||
if (!ontop)
|
||||
{
|
||||
fixed_t speed;
|
||||
angle_t angle = R_PointToAngle2(BlockingMobj->x,
|
||||
BlockingMobj->y, mo->x, mo->y) + ANGLE_1*((pr_bounce() % 16) - 8);
|
||||
angle_t angle = R_PointToAngle2(BlockingMobj->x,BlockingMobj->y, mo->x, mo->y) + ANGLE_1*((pr_bounce() % 16) - 8);
|
||||
speed = P_AproxDistance(mo->velx, mo->vely);
|
||||
speed = FixedMul(speed, mo->wallbouncefactor); // [GZ] was 0.75, using wallbouncefactor seems more consistent
|
||||
mo->angle = angle;
|
||||
|
@ -5090,6 +5102,8 @@ int P_PushUp(AActor *thing, FChangePosition *cpos)
|
|||
// is normally for projectiles which would have exploded by now anyway...
|
||||
if (thing->flags6 & MF6_THRUSPECIES && thing->GetSpecies() == intersect->GetSpecies())
|
||||
continue;
|
||||
if ((thing->flags & MF_MISSILE) && (intersect->flags2 & MF2_REFLECTIVE) && (intersect->flags7 & MF7_THRUREFLECT))
|
||||
continue;
|
||||
if (!(intersect->flags2 & MF2_PASSMOBJ) ||
|
||||
(!(intersect->flags3 & MF3_ISMONSTER) && intersect->Mass > mymass) ||
|
||||
(intersect->flags4 & MF4_ACTLIKEBRIDGE)
|
||||
|
@ -5098,7 +5112,8 @@ int P_PushUp(AActor *thing, FChangePosition *cpos)
|
|||
// Can't push bridges or things more massive than ourself
|
||||
return 2;
|
||||
}
|
||||
fixed_t oldz = intersect->z;
|
||||
fixed_t oldz;
|
||||
oldz = intersect->z;
|
||||
P_AdjustFloorCeil(intersect, cpos);
|
||||
intersect->z = thing->z + thing->height + 1;
|
||||
if (P_PushUp(intersect, cpos))
|
||||
|
|
|
@ -1202,6 +1202,9 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target)
|
|||
|
||||
if (target != NULL && ((target->flags & (MF_SHOOTABLE|MF_CORPSE)) || (target->flags6 & MF6_KILLED)) )
|
||||
{
|
||||
if (mo->flags7 & MF7_HITTARGET) mo->target = target;
|
||||
if (mo->flags7 & MF7_HITMASTER) mo->master = target;
|
||||
if (mo->flags7 & MF7_HITTRACER) mo->tracer = target;
|
||||
if (target->flags & MF_NOBLOOD) nextstate = mo->FindState(NAME_Crash);
|
||||
if (nextstate == NULL) nextstate = mo->FindState(NAME_Death, NAME_Extreme);
|
||||
}
|
||||
|
@ -1660,6 +1663,7 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
int steps, step, totalsteps;
|
||||
fixed_t startx, starty;
|
||||
fixed_t oldfloorz = mo->floorz;
|
||||
fixed_t oldz = mo->z;
|
||||
|
||||
fixed_t maxmove = (mo->waterlevel < 1) || (mo->flags & MF_MISSILE) ||
|
||||
(mo->player && mo->player->crouchoffset<-10*FRACUNIT) ? MAXMOVE : MAXMOVE/4;
|
||||
|
@ -1949,20 +1953,53 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
}
|
||||
if (BlockingMobj && (BlockingMobj->flags2 & MF2_REFLECTIVE))
|
||||
{
|
||||
angle = R_PointToAngle2(BlockingMobj->x, BlockingMobj->y, mo->x, mo->y);
|
||||
|
||||
// Change angle for deflection/reflection
|
||||
if (mo->AdjustReflectionAngle (BlockingMobj, angle))
|
||||
bool seeker = (mo->flags2 & MF2_SEEKERMISSILE) ? true : false;
|
||||
// Don't change the angle if there's THRUREFLECT on the monster.
|
||||
if (!(BlockingMobj->flags7 & MF7_THRUREFLECT))
|
||||
{
|
||||
goto explode;
|
||||
}
|
||||
int dir;
|
||||
angle_t delta;
|
||||
|
||||
if (BlockingMobj->flags7 & MF7_MIRRORREFLECT)
|
||||
angle = mo->angle + ANG180;
|
||||
else
|
||||
angle = R_PointToAngle2(BlockingMobj->x, BlockingMobj->y, mo->x, mo->y);
|
||||
|
||||
// Reflect the missile along angle
|
||||
mo->angle = angle;
|
||||
angle >>= ANGLETOFINESHIFT;
|
||||
mo->velx = FixedMul (mo->Speed>>1, finecosine[angle]);
|
||||
mo->vely = FixedMul (mo->Speed>>1, finesine[angle]);
|
||||
mo->velz = -mo->velz/2;
|
||||
// Change angle for deflection/reflection
|
||||
// AIMREFLECT calls precedence so make sure not to bother with adjusting here if declared.
|
||||
if (!(BlockingMobj->flags7 & MF7_AIMREFLECT) && (mo->AdjustReflectionAngle(BlockingMobj, angle)))
|
||||
{
|
||||
goto explode;
|
||||
}
|
||||
|
||||
// Reflect the missile along angle
|
||||
if (BlockingMobj->flags7 & MF7_AIMREFLECT)
|
||||
{
|
||||
dir = P_FaceMobj(mo, mo->target, &delta);
|
||||
if (dir)
|
||||
{ // Turn clockwise
|
||||
mo->angle += delta;
|
||||
}
|
||||
else
|
||||
{ // Turn counter clockwise
|
||||
mo->angle -= delta;
|
||||
}
|
||||
angle = mo->angle >> ANGLETOFINESHIFT;
|
||||
mo->velx = FixedMul(mo->Speed, finecosine[angle]);
|
||||
mo->vely = FixedMul(mo->Speed, finesine[angle]);
|
||||
mo->velz = -mo->velz;
|
||||
}
|
||||
else
|
||||
{
|
||||
mo->angle = angle;
|
||||
angle >>= ANGLETOFINESHIFT;
|
||||
mo->velx = FixedMul(mo->Speed >> 1, finecosine[angle]);
|
||||
mo->vely = FixedMul(mo->Speed >> 1, finesine[angle]);
|
||||
mo->velz = -mo->velz / 2;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
if (mo->flags2 & MF2_SEEKERMISSILE)
|
||||
{
|
||||
mo->tracer = mo->target;
|
||||
|
@ -2893,6 +2930,7 @@ int AActor::SpecialMissileHit (AActor *victim)
|
|||
bool AActor::AdjustReflectionAngle (AActor *thing, angle_t &angle)
|
||||
{
|
||||
if (flags2 & MF2_DONTREFLECT) return true;
|
||||
if (thing->flags7 & MF7_THRUREFLECT) return false;
|
||||
|
||||
// Change angle for reflection
|
||||
if (thing->flags4&MF4_SHIELDREFLECT)
|
||||
|
|
228
src/posix/i_steam.cpp
Normal file
228
src/posix/i_steam.cpp
Normal file
|
@ -0,0 +1,228 @@
|
|||
/*
|
||||
** i_steam.cpp
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2013 Braden Obrzut
|
||||
** 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 <sys/stat.h>
|
||||
|
||||
#include "doomerrors.h"
|
||||
#include "d_main.h"
|
||||
#include "zstring.h"
|
||||
#include "sc_man.h"
|
||||
|
||||
static void PSR_FindEndBlock(FScanner &sc)
|
||||
{
|
||||
int depth = 1;
|
||||
do
|
||||
{
|
||||
if(sc.CheckToken('}'))
|
||||
--depth;
|
||||
else if(sc.CheckToken('{'))
|
||||
++depth;
|
||||
else
|
||||
sc.MustGetAnyToken();
|
||||
}
|
||||
while(depth);
|
||||
}
|
||||
static void PSR_SkipBlock(FScanner &sc)
|
||||
{
|
||||
sc.MustGetToken('{');
|
||||
PSR_FindEndBlock(sc);
|
||||
}
|
||||
static bool PSR_FindAndEnterBlock(FScanner &sc, const char* keyword)
|
||||
{
|
||||
// Finds a block with a given keyword and then enter it (opening brace)
|
||||
// Should be closed with PSR_FindEndBlock
|
||||
while(sc.GetToken())
|
||||
{
|
||||
if(sc.TokenType == '}')
|
||||
{
|
||||
sc.UnGet();
|
||||
return false;
|
||||
}
|
||||
|
||||
sc.TokenMustBe(TK_StringConst);
|
||||
if(!sc.Compare(keyword))
|
||||
{
|
||||
if(!sc.CheckToken(TK_StringConst))
|
||||
PSR_SkipBlock(sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.MustGetToken('{');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static TArray<FString> PSR_ReadBaseInstalls(FScanner &sc)
|
||||
{
|
||||
TArray<FString> result;
|
||||
|
||||
// Get a list of possible install directories.
|
||||
while(sc.GetToken())
|
||||
{
|
||||
if(sc.TokenType == '}')
|
||||
break;
|
||||
|
||||
sc.TokenMustBe(TK_StringConst);
|
||||
FString key(sc.String);
|
||||
if(key.Left(18).CompareNoCase("BaseInstallFolder_") == 0)
|
||||
{
|
||||
sc.MustGetToken(TK_StringConst);
|
||||
result.Push(FString(sc.String) + "/steamapps/common");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(sc.CheckToken('{'))
|
||||
PSR_FindEndBlock(sc);
|
||||
else
|
||||
sc.MustGetToken(TK_StringConst);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
static TArray<FString> ParseSteamRegistry(const char* path)
|
||||
{
|
||||
TArray<FString> dirs;
|
||||
|
||||
// Read registry data
|
||||
FScanner sc;
|
||||
sc.OpenFile(path);
|
||||
sc.SetCMode(true);
|
||||
|
||||
// Find the SteamApps listing
|
||||
if(PSR_FindAndEnterBlock(sc, "InstallConfigStore"))
|
||||
{
|
||||
if(PSR_FindAndEnterBlock(sc, "Software"))
|
||||
{
|
||||
if(PSR_FindAndEnterBlock(sc, "Valve"))
|
||||
{
|
||||
if(PSR_FindAndEnterBlock(sc, "Steam"))
|
||||
{
|
||||
dirs = PSR_ReadBaseInstalls(sc);
|
||||
}
|
||||
PSR_FindEndBlock(sc);
|
||||
}
|
||||
PSR_FindEndBlock(sc);
|
||||
}
|
||||
PSR_FindEndBlock(sc);
|
||||
}
|
||||
|
||||
return dirs;
|
||||
}
|
||||
|
||||
static struct SteamAppInfo
|
||||
{
|
||||
const char* const BasePath;
|
||||
const int AppID;
|
||||
} AppInfo[] =
|
||||
{
|
||||
/*{"doom 2/base", 2300},
|
||||
{"final doom/base", 2290},
|
||||
{"heretic shadow of the serpent riders/base", 2390},
|
||||
{"hexen/base", 2360},
|
||||
{"hexen deathkings of the dark citadel/base", 2370},
|
||||
{"ultimate doom/base", 2280},
|
||||
{"DOOM 3 BFG Edition/base/wads", 208200},*/
|
||||
{"Strife", 317040}
|
||||
};
|
||||
|
||||
TArray<FString> I_GetSteamPath()
|
||||
{
|
||||
TArray<FString> result;
|
||||
TArray<FString> SteamInstallFolders;
|
||||
|
||||
// Linux and OS X actually allow the user to install to any location, so
|
||||
// we need to figure out on an app-by-app basis where the game is installed.
|
||||
// To do so, we read the virtual registry.
|
||||
#ifdef __APPLE__
|
||||
FString appSupportPath;
|
||||
|
||||
{
|
||||
char cpath[PATH_MAX];
|
||||
FSRef folder;
|
||||
|
||||
if (noErr == FSFindFolder(kUserDomain, kApplicationSupportFolderType, kCreateFolder, &folder) &&
|
||||
noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX))
|
||||
{
|
||||
appSupportPath = cpath;
|
||||
}
|
||||
}
|
||||
|
||||
FString regPath = appSupportPath + "/Steam/config/config.vdf";
|
||||
try
|
||||
{
|
||||
SteamInstallFolders = ParseSteamRegistry(regPath);
|
||||
}
|
||||
catch(class CDoomError &error)
|
||||
{
|
||||
// If we can't parse for some reason just pretend we can't find anything.
|
||||
return result;
|
||||
}
|
||||
|
||||
SteamInstallFolders.Push(appSupportPath + "/Steam/SteamApps/common");
|
||||
#else
|
||||
char* home = getenv("HOME");
|
||||
if(home != NULL && *home != '\0')
|
||||
{
|
||||
FString regPath;
|
||||
regPath.Format("%s/.local/share/Steam/config/config.vdf", home);
|
||||
try
|
||||
{
|
||||
SteamInstallFolders = ParseSteamRegistry(regPath);
|
||||
}
|
||||
catch(class CDoomError &error)
|
||||
{
|
||||
// If we can't parse for some reason just pretend we can't find anything.
|
||||
return result;
|
||||
}
|
||||
|
||||
regPath.Format("%s/.local/share/Steam/SteamApps/common", home);
|
||||
SteamInstallFolders.Push(regPath);
|
||||
}
|
||||
#endif
|
||||
|
||||
for(unsigned int i = 0;i < SteamInstallFolders.Size();++i)
|
||||
{
|
||||
for(unsigned int app = 0;app < countof(AppInfo);++app)
|
||||
{
|
||||
struct stat st;
|
||||
FString candidate(SteamInstallFolders[i] + "/" + AppInfo[app].BasePath);
|
||||
if(stat(candidate, &st) == 0 && S_ISDIR(st.st_mode))
|
||||
result.Push(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
|
@ -120,6 +120,10 @@ void I_SetIWADInfo ();
|
|||
// Pick from multiple IWADs to use
|
||||
int I_PickIWad (WadStuff *wads, int numwads, bool queryiwad, int defaultiwad);
|
||||
|
||||
// [RH] Checks the registry for Steam's install path, so we can scan its
|
||||
// directories for IWADs if the user purchased any through Steam.
|
||||
TArray<FString> I_GetSteamPath();
|
||||
|
||||
// The ini could not be saved at exit
|
||||
bool I_WriteIniFailed ();
|
||||
|
||||
|
|
|
@ -158,6 +158,7 @@ std2:
|
|||
'random' { RET(TK_Random); }
|
||||
'random2' { RET(TK_Random2); }
|
||||
'frandom' { RET(TK_FRandom); }
|
||||
'pick' { RET(TK_Pick); }
|
||||
|
||||
L (L|D)* { RET(TK_Identifier); }
|
||||
|
||||
|
|
|
@ -122,4 +122,5 @@ xx(TK_Array, "'array'")
|
|||
xx(TK_In, "'in'")
|
||||
xx(TK_SizeOf, "'sizeof'")
|
||||
xx(TK_AlignOf, "'alignof'")
|
||||
xx(TK_Pick, "'pick'")
|
||||
#undef xx
|
||||
|
|
|
@ -3071,37 +3071,41 @@ DEFINE_ACTION_FUNCTION(AActor, A_ClearTarget)
|
|||
|
||||
enum CLOF_flags
|
||||
{
|
||||
CLOFF_NOAIM_VERT = 0x1,
|
||||
CLOFF_NOAIM_HORZ = 0x2,
|
||||
CLOFF_NOAIM_VERT = 0x00000001,
|
||||
CLOFF_NOAIM_HORZ = 0x00000002,
|
||||
|
||||
CLOFF_JUMPENEMY = 0x4,
|
||||
CLOFF_JUMPFRIEND = 0x8,
|
||||
CLOFF_JUMPOBJECT = 0x10,
|
||||
CLOFF_JUMPNONHOSTILE = 0x20,
|
||||
CLOFF_JUMPENEMY = 0x00000004,
|
||||
CLOFF_JUMPFRIEND = 0x00000008,
|
||||
CLOFF_JUMPOBJECT = 0x00000010,
|
||||
CLOFF_JUMPNONHOSTILE = 0x00000020,
|
||||
|
||||
CLOFF_SKIPENEMY = 0x40,
|
||||
CLOFF_SKIPFRIEND = 0x80,
|
||||
CLOFF_SKIPOBJECT = 0x100,
|
||||
CLOFF_SKIPNONHOSTILE = 0x200,
|
||||
CLOFF_SKIPENEMY = 0x00000040,
|
||||
CLOFF_SKIPFRIEND = 0x00000080,
|
||||
CLOFF_SKIPOBJECT = 0x00000100,
|
||||
CLOFF_SKIPNONHOSTILE = 0x00000200,
|
||||
|
||||
CLOFF_MUSTBESHOOTABLE = 0x400,
|
||||
CLOFF_MUSTBESHOOTABLE = 0x00000400,
|
||||
|
||||
CLOFF_SKIPTARGET = 0x800,
|
||||
CLOFF_ALLOWNULL = 0x1000,
|
||||
CLOFF_CHECKPARTIAL = 0x2000,
|
||||
CLOFF_SKIPTARGET = 0x00000800,
|
||||
CLOFF_ALLOWNULL = 0x00001000,
|
||||
CLOFF_CHECKPARTIAL = 0x00002000,
|
||||
|
||||
CLOFF_MUSTBEGHOST = 0x4000,
|
||||
CLOFF_IGNOREGHOST = 0x8000,
|
||||
CLOFF_MUSTBEGHOST = 0x00004000,
|
||||
CLOFF_IGNOREGHOST = 0x00008000,
|
||||
|
||||
CLOFF_MUSTBESOLID = 0x10000,
|
||||
CLOFF_BEYONDTARGET = 0x20000,
|
||||
CLOFF_MUSTBESOLID = 0x00010000,
|
||||
CLOFF_BEYONDTARGET = 0x00020000,
|
||||
|
||||
CLOFF_FROMBASE = 0x40000,
|
||||
CLOFF_MUL_HEIGHT = 0x80000,
|
||||
CLOFF_MUL_WIDTH = 0x100000,
|
||||
CLOFF_FROMBASE = 0x00040000,
|
||||
CLOFF_MUL_HEIGHT = 0x00080000,
|
||||
CLOFF_MUL_WIDTH = 0x00100000,
|
||||
|
||||
CLOFF_JUMP_ON_MISS = 0x200000,
|
||||
CLOFF_AIM_VERT_NOOFFSET = 0x400000,
|
||||
CLOFF_JUMP_ON_MISS = 0x00200000,
|
||||
CLOFF_AIM_VERT_NOOFFSET = 0x00400000,
|
||||
|
||||
CLOFF_SETTARGET = 0x00800000,
|
||||
CLOFF_SETMASTER = 0x01000000,
|
||||
CLOFF_SETTRACER = 0x02000000,
|
||||
};
|
||||
|
||||
struct LOFData
|
||||
|
@ -3341,6 +3345,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
|
|||
{
|
||||
return;
|
||||
}
|
||||
if ((trace.HitType == TRACE_HitActor) && (trace.Actor != NULL) && !(lof_data.BadActor))
|
||||
{
|
||||
if (flags & (CLOFF_SETTARGET)) self->target = trace.Actor;
|
||||
if (flags & (CLOFF_SETMASTER)) self->master = trace.Actor;
|
||||
if (flags & (CLOFF_SETTRACER)) self->tracer = trace.Actor;
|
||||
}
|
||||
|
||||
ACTION_JUMP(jump);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -247,6 +247,12 @@ static FFlagDef ActorFlags[]=
|
|||
DEFINE_FLAG(MF7, DONTTHRUST, AActor, flags7),
|
||||
DEFINE_FLAG(MF7, ALLOWPAIN, AActor, flags7),
|
||||
DEFINE_FLAG(MF7, CAUSEPAIN, AActor, flags7),
|
||||
DEFINE_FLAG(MF7, THRUREFLECT, AActor, flags7),
|
||||
DEFINE_FLAG(MF7, MIRRORREFLECT, AActor, flags7),
|
||||
DEFINE_FLAG(MF7, AIMREFLECT, AActor, flags7),
|
||||
DEFINE_FLAG(MF7, HITTARGET, AActor, flags7),
|
||||
DEFINE_FLAG(MF7, HITMASTER, AActor, flags7),
|
||||
DEFINE_FLAG(MF7, HITTRACER, AActor, flags7),
|
||||
|
||||
// Effect flags
|
||||
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
|
||||
|
|
|
@ -371,6 +371,37 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls)
|
|||
|
||||
return new FxRandom(rng, min, max, sc);
|
||||
}
|
||||
else if (sc.CheckToken(TK_Pick))
|
||||
{
|
||||
FRandom *rng;
|
||||
TArray<FxExpression*> list;
|
||||
list.Clear();
|
||||
int index = 0;
|
||||
|
||||
if (sc.CheckToken('['))
|
||||
{
|
||||
sc.MustGetToken(TK_Identifier);
|
||||
rng = FRandom::StaticFindRNG(sc.String);
|
||||
sc.MustGetToken(']');
|
||||
}
|
||||
else
|
||||
{
|
||||
rng = &pr_exrandom;
|
||||
}
|
||||
sc.MustGetToken('(');
|
||||
|
||||
while (!(sc.CheckToken(')')))
|
||||
{
|
||||
FxExpression *min = ParseExpressionM(sc, cls);
|
||||
list.Push(min);
|
||||
if (sc.CheckToken(')'))
|
||||
break;
|
||||
else
|
||||
sc.MustGetToken(',');
|
||||
}
|
||||
|
||||
return new FxPick(rng, list, sc);
|
||||
}
|
||||
else if (sc.CheckToken(TK_FRandom))
|
||||
{
|
||||
FRandom *rng;
|
||||
|
|
|
@ -559,6 +559,27 @@ public:
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxPick : public FxExpression
|
||||
{
|
||||
protected:
|
||||
FRandom * rng;
|
||||
TDeletingArray<FxExpression*> min;
|
||||
|
||||
public:
|
||||
|
||||
FxPick(FRandom *, TArray<FxExpression*> mi, const FScriptPosition &pos);
|
||||
~FxPick();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
|
||||
ExpVal EvalExpression(AActor *self);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxFRandom : public FxRandom
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -1691,6 +1691,73 @@ ExpVal FxRandom::EvalExpression (AActor *self)
|
|||
return val;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
FxPick::FxPick(FRandom * r, TArray<FxExpression*> mi, const FScriptPosition &pos)
|
||||
: FxExpression(pos)
|
||||
{
|
||||
for (unsigned int index = 0; index < mi.Size(); index++)
|
||||
{
|
||||
min.Push(new FxIntCast(mi[index]));
|
||||
}
|
||||
rng = r;
|
||||
ValueType = VAL_Int;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxPick::~FxPick()
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxExpression *FxPick::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
for (unsigned int index = 0; index < min.Size(); index++)
|
||||
{
|
||||
RESOLVE(min[index], ctx);
|
||||
ABORT(min[index]);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpVal FxPick::EvalExpression(AActor *self)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Int;
|
||||
int max = min.Size();
|
||||
if (max > 0)
|
||||
{
|
||||
int select = (*rng)(max);
|
||||
val.Int = min[select]->EvalExpression(self).GetInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
val.Int = (*rng)();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
@ -1524,20 +1524,36 @@ static bool QueryPathKey(HKEY key, const char *keypath, const char *valname, FSt
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FString I_GetSteamPath()
|
||||
TArray<FString> I_GetSteamPath()
|
||||
{
|
||||
TArray<FString> result;
|
||||
static const char *const steam_dirs[] =
|
||||
{
|
||||
"doom 2/base",
|
||||
"final doom/base",
|
||||
"heretic shadow of the serpent riders/base",
|
||||
"hexen/base",
|
||||
"hexen deathkings of the dark citadel/base",
|
||||
"ultimate doom/base",
|
||||
"DOOM 3 BFG Edition/base/wads",
|
||||
"Strife"
|
||||
};
|
||||
|
||||
FString path;
|
||||
|
||||
if (QueryPathKey(HKEY_CURRENT_USER, "Software\\Valve\\Steam", "SteamPath", path))
|
||||
if (!QueryPathKey(HKEY_CURRENT_USER, "Software\\Valve\\Steam", "SteamPath", path))
|
||||
{
|
||||
return path;
|
||||
if (!QueryPathKey(HKEY_LOCAL_MACHINE, "Software\\Valve\\Steam", "InstallPath", path))
|
||||
return result;
|
||||
}
|
||||
if (QueryPathKey(HKEY_LOCAL_MACHINE, "Software\\Valve\\Steam", "InstallPath", path))
|
||||
path += "/SteamApps/common/";
|
||||
|
||||
for(unsigned int i = 0; i < countof(steam_dirs); ++i)
|
||||
{
|
||||
return path;
|
||||
result.Push(path + steam_dirs[i]);
|
||||
}
|
||||
path = "";
|
||||
return path;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -142,7 +142,7 @@ void I_SetWndProc();
|
|||
|
||||
// [RH] Checks the registry for Steam's install path, so we can scan its
|
||||
// directories for IWADs if the user purchased any through Steam.
|
||||
FString I_GetSteamPath();
|
||||
TArray<FString> I_GetSteamPath();
|
||||
|
||||
// Damn Microsoft for doing Get/SetWindowLongPtr half-assed. Instead of
|
||||
// giving them proper prototypes under Win32, they are just macros for
|
||||
|
|
|
@ -372,6 +372,10 @@ enum
|
|||
CLOFF_JUMP_ON_MISS = 0x200000,
|
||||
CLOFF_AIM_VERT_NOOFFSET = 0x400000,
|
||||
|
||||
CLOFF_SETTARGET = 0x800000,
|
||||
CLOFF_SETMASTER = 0x1000000,
|
||||
CLOFF_SETTRACER = 0x2000000,
|
||||
|
||||
CLOFF_SKIPOBSTACLES = CLOFF_SKIPENEMY|CLOFF_SKIPFRIEND|CLOFF_SKIPOBJECT|CLOFF_SKIPNONHOSTILE,
|
||||
CLOFF_NOAIM = CLOFF_NOAIM_VERT|CLOFF_NOAIM_HORZ
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue