From e5340ad6375a2311c11335d2be9df9367ffa0a34 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Tue, 9 Dec 2014 12:09:36 -0600 Subject: [PATCH 01/13] - Splitting the pull request in half. - Added THRUREFLECT, MIRRORREFLECT, and AIMREFLECT. All require REFLECTIVE to work. - THRUREFLECT prevents missiles from changing course if reflected, and takes precedence over all reflective flags. - MIRRORREFLECT causes missiles to perform a direct 180 turn-around. - AIMREFLECT turns the missile back to the original shooter, and does not slow the missile down. --- src/actor.h | 7 +++- src/p_map.cpp | 29 +++++++++++++---- src/p_mobj.cpp | 59 +++++++++++++++++++++++++++------- src/thingdef/thingdef_data.cpp | 3 ++ 4 files changed, 78 insertions(+), 20 deletions(-) diff --git a/src/actor.h b/src/actor.h index f46ee7148a..88cfa983e5 100644 --- a/src/actor.h +++ b/src/actor.h @@ -347,6 +347,11 @@ 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. + + // --- mobj.renderflags --- @@ -859,7 +864,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; diff --git a/src/p_map.cpp b/src/p_map.cpp index 3097ae8241..8575970891 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -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)) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index f1cfb6e284..2da365d600 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1660,6 +1660,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 +1950,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 +2927,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) diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index e8cb91239b..0bc7624a73 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -247,6 +247,9 @@ 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), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), From 533ae959336a4cd7a2e5c2580c70c3bf81294e70 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Tue, 9 Dec 2014 12:30:14 -0600 Subject: [PATCH 02/13] - Added three missile impact pointer changing flags. - HITTARGET, HITMASTER, and HITTRACER. - A missile that dies hitting an actor will set this impacted actor as the new target/master/tracer, depending on specifications. --- src/actor.h | 3 +++ src/p_mobj.cpp | 3 +++ src/thingdef/thingdef_data.cpp | 5 ++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/actor.h b/src/actor.h index f46ee7148a..ecf8ad6a10 100644 --- a/src/actor.h +++ b/src/actor.h @@ -347,6 +347,9 @@ 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_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 --- diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index f1cfb6e284..4d731f1fc6 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -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 (target->flags7 & MF7_HITTARGET) mo->target = target; + if (target->flags7 & MF7_HITMASTER) mo->master = target; + if (target->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); } diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index e8cb91239b..17c1868845 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -247,7 +247,10 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF7, DONTTHRUST, AActor, flags7), DEFINE_FLAG(MF7, ALLOWPAIN, AActor, flags7), DEFINE_FLAG(MF7, CAUSEPAIN, 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), DEFINE_FLAG2(FX_ROCKET, ROCKETTRAIL, AActor, effects), From c339bb33cf701a983784391ee6bd2a6051a4f68e Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Wed, 10 Dec 2014 20:55:00 +1300 Subject: [PATCH 03/13] Added cl_waitforsave - cl_waitforsave (default true) pauses the game timer when a save starts, preventing the network buffer from trying to compensate for slow saves. --- src/g_game.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/g_game.cpp b/src/g_game.cpp index beec9435ae..ba53254c2e 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -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); } From 372f7e7002410e33b477aa275b74a74c920f861b Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Wed, 10 Dec 2014 21:11:26 +0100 Subject: [PATCH 04/13] - Various CMake fixes for two problems. 1) Don't show OSX_COCOA_BACKEND option if the host is not OSX; 2) Don't use the '-msse' compiler flag in dumb/ if the architecture does not support it. --- dumb/CMakeLists.txt | 7 ++++++- src/CMakeLists.txt | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/dumb/CMakeLists.txt b/dumb/CMakeLists.txt index 2b70ee412d..9c1a69a79f 100644 --- a/dumb/CMakeLists.txt +++ b/dumb/CMakeLists.txt @@ -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 ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 07c13c20c2..2cc3bc63e7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 ) From 86372fce34d84e75ba424e20af677cfcfb5cd488 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Fri, 12 Dec 2014 16:19:37 -0500 Subject: [PATCH 05/13] - Added Steam detection for Stife: Veteran Edition. - Added Steam install scanning for Linux and OS X. (OS X and Win32 not yet tested.) --- src/CMakeLists.txt | 1 + src/cocoa/i_backend_cocoa.mm | 8 ++ src/d_iwad.cpp | 22 +--- src/sdl/i_steam.cpp | 217 +++++++++++++++++++++++++++++++++++ src/sdl/i_system.h | 4 + src/win32/i_system.cpp | 30 +++-- src/win32/i_system.h | 2 +- 7 files changed, 257 insertions(+), 27 deletions(-) create mode 100644 src/sdl/i_steam.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2cc3bc63e7..8b924bd508 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -569,6 +569,7 @@ set( PLAT_SDL_SYSTEM_SOURCES sdl/i_cd.cpp sdl/i_main.cpp sdl/i_movie.cpp + sdl/i_steam.cpp sdl/i_system.cpp sdl/sdlvideo.cpp sdl/st_start.cpp ) diff --git a/src/cocoa/i_backend_cocoa.mm b/src/cocoa/i_backend_cocoa.mm index bd3dc31156..9085d92db2 100644 --- a/src/cocoa/i_backend_cocoa.mm +++ b/src/cocoa/i_backend_cocoa.mm @@ -1619,6 +1619,14 @@ const char* I_GetBackEndName() } +FString OSX_FindApplicationSupport() +{ + NSURL *url = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil]; + if(url == nil) + return FString(); + return [[url path] UTF8String]; +} + // --------------------------------------------------------------------------- diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 6b430fa038..c03ed7a2f5 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -430,27 +430,11 @@ int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, } } } -#ifdef _WIN32 - FString steam_path = I_GetSteamPath(); - if (steam_path.IsNotEmpty()) + TArray 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()) diff --git a/src/sdl/i_steam.cpp b/src/sdl/i_steam.cpp new file mode 100644 index 0000000000..1da7fc5fab --- /dev/null +++ b/src/sdl/i_steam.cpp @@ -0,0 +1,217 @@ +/* +** 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 + +#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 PSR_ReadBaseInstalls(FScanner &sc) +{ + TArray 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(sc.String); + } + else + { + if(sc.CheckToken('{')) + PSR_FindEndBlock(sc); + else + sc.MustGetToken(TK_StringConst); + } + } + + return result; +} +static TArray ParseSteamRegistry(const char* path) +{ + TArray 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 I_GetSteamPath() +{ + TArray result; + TArray 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 OSX_FindApplicationSupport(); + + FString regPath = OSX_FindApplicationSupport() + "/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(OSX_FindApplicationSupport() + "/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; +} diff --git a/src/sdl/i_system.h b/src/sdl/i_system.h index a3341f4c56..fa03d3c377 100644 --- a/src/sdl/i_system.h +++ b/src/sdl/i_system.h @@ -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 I_GetSteamPath(); + // The ini could not be saved at exit bool I_WriteIniFailed (); diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index 4248df2740..71cc42af0b 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -1524,20 +1524,36 @@ static bool QueryPathKey(HKEY key, const char *keypath, const char *valname, FSt // //========================================================================== -FString I_GetSteamPath() +TArray I_GetSteamPath() { + TArray 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; } //========================================================================== diff --git a/src/win32/i_system.h b/src/win32/i_system.h index 9fbf2db5cb..647a08d134 100644 --- a/src/win32/i_system.h +++ b/src/win32/i_system.h @@ -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 I_GetSteamPath(); // Damn Microsoft for doing Get/SetWindowLongPtr half-assed. Instead of // giving them proper prototypes under Win32, they are just macros for From 8ee0554d567a693f7bff81e3fe8503b15ace716d Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Fri, 12 Dec 2014 16:33:49 -0500 Subject: [PATCH 06/13] - Fixed: Extra Steam paths still need steamapps/common appended to them. --- src/sdl/i_steam.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sdl/i_steam.cpp b/src/sdl/i_steam.cpp index 1da7fc5fab..f8b4c07d9c 100644 --- a/src/sdl/i_steam.cpp +++ b/src/sdl/i_steam.cpp @@ -99,7 +99,7 @@ static TArray PSR_ReadBaseInstalls(FScanner &sc) if(key.Left(18).CompareNoCase("BaseInstallFolder_") == 0) { sc.MustGetToken(TK_StringConst); - result.Push(sc.String); + result.Push(FString(sc.String) + "/steamapps/common"); } else { @@ -170,6 +170,7 @@ TArray I_GetSteamPath() FString OSX_FindApplicationSupport(); FString regPath = OSX_FindApplicationSupport() + "/Steam/config/config.vdf"; + Printf("Reading %s\n", regPath.GetChars()); try { SteamInstallFolders = ParseSteamRegistry(regPath); @@ -208,6 +209,7 @@ TArray I_GetSteamPath() { struct stat st; FString candidate(SteamInstallFolders[i] + "/" + AppInfo[app].BasePath); + Printf("Checking %s\n", candidate.GetChars()); if(stat(candidate, &st) == 0 && S_ISDIR(st.st_mode)) result.Push(candidate); } From b14eded8d8f6d4e756299f43768178dbe188b4ec Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Fri, 12 Dec 2014 17:06:01 -0500 Subject: [PATCH 07/13] - Accidentally committed debuging code. --- src/sdl/i_steam.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sdl/i_steam.cpp b/src/sdl/i_steam.cpp index f8b4c07d9c..23e74af5a5 100644 --- a/src/sdl/i_steam.cpp +++ b/src/sdl/i_steam.cpp @@ -170,7 +170,6 @@ TArray I_GetSteamPath() FString OSX_FindApplicationSupport(); FString regPath = OSX_FindApplicationSupport() + "/Steam/config/config.vdf"; - Printf("Reading %s\n", regPath.GetChars()); try { SteamInstallFolders = ParseSteamRegistry(regPath); @@ -209,7 +208,6 @@ TArray I_GetSteamPath() { struct stat st; FString candidate(SteamInstallFolders[i] + "/" + AppInfo[app].BasePath); - Printf("Checking %s\n", candidate.GetChars()); if(stat(candidate, &st) == 0 && S_ISDIR(st.st_mode)) result.Push(candidate); } From 8c5a8c54f01a00d9ef691f60574c15d45400c13a Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Sat, 13 Dec 2014 15:08:18 -0600 Subject: [PATCH 08/13] - Added rclamp(,). - Usable for DECORATE expressions. Chooses one of the two numbers placed in the field. --- src/namedef.h | 1 + src/sc_man_scanner.re | 1 + src/sc_man_tokens.h | 1 + src/thingdef/thingdef_exp.cpp | 23 ++++++++ src/thingdef/thingdef_exp.h | 21 +++++++ src/thingdef/thingdef_expression.cpp | 83 ++++++++++++++++++++++++++++ 6 files changed, 130 insertions(+) diff --git a/src/namedef.h b/src/namedef.h index 1469973091..7eef612c1d 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -300,6 +300,7 @@ xx(CallACS) xx(Sqrt) xx(CheckClass) xx(IsPointerEqual) +xx(RClamp) // Various actor names which are used internally xx(MapSpot) diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index dd90ce1d13..2e25fb2f71 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -158,6 +158,7 @@ std2: 'random' { RET(TK_Random); } 'random2' { RET(TK_Random2); } 'frandom' { RET(TK_FRandom); } + 'rclamp' { RET(TK_RClamp); } L (L|D)* { RET(TK_Identifier); } diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index 9dde749723..62622cf003 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -122,4 +122,5 @@ xx(TK_Array, "'array'") xx(TK_In, "'in'") xx(TK_SizeOf, "'sizeof'") xx(TK_AlignOf, "'alignof'") +xx(TK_RClamp, "'rclamp'") #undef xx diff --git a/src/thingdef/thingdef_exp.cpp b/src/thingdef/thingdef_exp.cpp index 773f7ffacb..4cef24187b 100644 --- a/src/thingdef/thingdef_exp.cpp +++ b/src/thingdef/thingdef_exp.cpp @@ -371,6 +371,29 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls) return new FxRandom(rng, min, max, sc); } + else if (sc.CheckToken(TK_RClamp)) + { + FRandom *rng; + + if (sc.CheckToken('[')) + { + sc.MustGetToken(TK_Identifier); + rng = FRandom::StaticFindRNG(sc.String); + sc.MustGetToken(']'); + } + else + { + rng = &pr_exrandom; + } + sc.MustGetToken('('); + + FxExpression *min = ParseExpressionM(sc, cls); + sc.MustGetToken(','); + FxExpression *max = ParseExpressionM(sc, cls); + sc.MustGetToken(')'); + + return new FxRClamp(rng, min, max, sc); + } else if (sc.CheckToken(TK_FRandom)) { FRandom *rng; diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index 77af37f539..42e35489dd 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -559,6 +559,27 @@ public: // //========================================================================== +class FxRClamp : public FxExpression +{ +protected: + FRandom * rng; + FxExpression *min, *max; + +public: + + FxRClamp(FRandom *, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos); + ~FxRClamp(); + FxExpression *Resolve(FCompileContext&); + + ExpVal EvalExpression(AActor *self); +}; + +//========================================================================== +// +// +// +//========================================================================== + class FxFRandom : public FxRandom { public: diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 7dbf5ec36d..5a5510a0b9 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -1691,6 +1691,89 @@ ExpVal FxRandom::EvalExpression (AActor *self) return val; } +//========================================================================== +// +// +// +//========================================================================== +FxRClamp::FxRClamp(FRandom * r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos) +: FxExpression(pos) +{ + if (mi != NULL && ma != NULL) + { + min = new FxIntCast(mi); + max = new FxIntCast(ma); + } + else min = max = NULL; + rng = r; + ValueType = VAL_Int; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxRClamp::~FxRClamp() +{ + SAFE_DELETE(min); + SAFE_DELETE(max); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxRClamp::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + if (min && max) + { + RESOLVE(min, ctx); + RESOLVE(max, ctx); + ABORT(min && max); + } + return this; +}; + + +//========================================================================== +// +// +// +//========================================================================== + +ExpVal FxRClamp::EvalExpression(AActor *self) +{ + ExpVal val; + val.Type = VAL_Int; + + if (min != NULL && max != NULL) + { + int minval = min->EvalExpression(self).GetInt(); + int maxval = max->EvalExpression(self).GetInt(); + + if (maxval < minval) + { + swapvalues(maxval, minval); + } + + val.Int = (*rng)(2); //rng->operator()(2); //(maxval - minval + 1) + minval; + if (val.Int > 0) + val.Int = maxval; + else + val.Int = minval; + } + else + { + val.Int = (*rng)(); + } + return val; +} + //========================================================================== // // From 785f72d6eb257dd3392a5962c3310503890b53ba Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Sat, 13 Dec 2014 15:59:27 -0600 Subject: [PATCH 09/13] - Renamed RClamp to Pick. --- src/namedef.h | 2 +- src/sc_man_scanner.re | 2 +- src/sc_man_tokens.h | 2 +- src/thingdef/thingdef_exp.cpp | 4 ++-- src/thingdef/thingdef_exp.h | 6 +++--- src/thingdef/thingdef_expression.cpp | 8 ++++---- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/namedef.h b/src/namedef.h index 7eef612c1d..e0b7e8ba62 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -300,7 +300,7 @@ xx(CallACS) xx(Sqrt) xx(CheckClass) xx(IsPointerEqual) -xx(RClamp) +xx(Pick) // Various actor names which are used internally xx(MapSpot) diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index 2e25fb2f71..3a7f717a81 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -158,7 +158,7 @@ std2: 'random' { RET(TK_Random); } 'random2' { RET(TK_Random2); } 'frandom' { RET(TK_FRandom); } - 'rclamp' { RET(TK_RClamp); } + 'pick' { RET(TK_Pick); } L (L|D)* { RET(TK_Identifier); } diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index 62622cf003..1c22046c96 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -122,5 +122,5 @@ xx(TK_Array, "'array'") xx(TK_In, "'in'") xx(TK_SizeOf, "'sizeof'") xx(TK_AlignOf, "'alignof'") -xx(TK_RClamp, "'rclamp'") +xx(TK_Pick, "'pick'") #undef xx diff --git a/src/thingdef/thingdef_exp.cpp b/src/thingdef/thingdef_exp.cpp index 4cef24187b..fd09364854 100644 --- a/src/thingdef/thingdef_exp.cpp +++ b/src/thingdef/thingdef_exp.cpp @@ -371,7 +371,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls) return new FxRandom(rng, min, max, sc); } - else if (sc.CheckToken(TK_RClamp)) + else if (sc.CheckToken(TK_Pick)) { FRandom *rng; @@ -392,7 +392,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls) FxExpression *max = ParseExpressionM(sc, cls); sc.MustGetToken(')'); - return new FxRClamp(rng, min, max, sc); + return new FxPick(rng, min, max, sc); } else if (sc.CheckToken(TK_FRandom)) { diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index 42e35489dd..03e465c3ab 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -559,7 +559,7 @@ public: // //========================================================================== -class FxRClamp : public FxExpression +class FxPick : public FxExpression { protected: FRandom * rng; @@ -567,8 +567,8 @@ protected: public: - FxRClamp(FRandom *, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos); - ~FxRClamp(); + FxPick(FRandom *, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos); + ~FxPick(); FxExpression *Resolve(FCompileContext&); ExpVal EvalExpression(AActor *self); diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 5a5510a0b9..dc2cb22091 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -1696,7 +1696,7 @@ ExpVal FxRandom::EvalExpression (AActor *self) // // //========================================================================== -FxRClamp::FxRClamp(FRandom * r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos) +FxPick::FxPick(FRandom * r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos) : FxExpression(pos) { if (mi != NULL && ma != NULL) @@ -1715,7 +1715,7 @@ FxRClamp::FxRClamp(FRandom * r, FxExpression *mi, FxExpression *ma, const FScrip // //========================================================================== -FxRClamp::~FxRClamp() +FxPick::~FxPick() { SAFE_DELETE(min); SAFE_DELETE(max); @@ -1727,7 +1727,7 @@ FxRClamp::~FxRClamp() // //========================================================================== -FxExpression *FxRClamp::Resolve(FCompileContext &ctx) +FxExpression *FxPick::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); if (min && max) @@ -1746,7 +1746,7 @@ FxExpression *FxRClamp::Resolve(FCompileContext &ctx) // //========================================================================== -ExpVal FxRClamp::EvalExpression(AActor *self) +ExpVal FxPick::EvalExpression(AActor *self) { ExpVal val; val.Type = VAL_Int; From 3f3aab42f1f1f20a522411c163800a78472b24b4 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Sun, 14 Dec 2014 04:45:39 -0600 Subject: [PATCH 10/13] - Pick can now hold unlimited numbers to choose from. - I.e. pick(1,4,12,16) --- src/thingdef/thingdef_exp.cpp | 18 ++++++++--- src/thingdef/thingdef_exp.h | 4 +-- src/thingdef/thingdef_expression.cpp | 47 +++++++++++++--------------- 3 files changed, 36 insertions(+), 33 deletions(-) diff --git a/src/thingdef/thingdef_exp.cpp b/src/thingdef/thingdef_exp.cpp index fd09364854..daa7f1a9cd 100644 --- a/src/thingdef/thingdef_exp.cpp +++ b/src/thingdef/thingdef_exp.cpp @@ -374,6 +374,9 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls) else if (sc.CheckToken(TK_Pick)) { FRandom *rng; + TArray list; + list.Clear(); + int index = 0; if (sc.CheckToken('[')) { @@ -387,12 +390,17 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls) } sc.MustGetToken('('); - FxExpression *min = ParseExpressionM(sc, cls); - sc.MustGetToken(','); - FxExpression *max = ParseExpressionM(sc, cls); - sc.MustGetToken(')'); + while (!(sc.CheckToken(')'))) + { + FxExpression *min = ParseExpressionM(sc, cls); + list.Push(min); + if (sc.CheckToken(')')) + break; + else + sc.MustGetToken(','); + } - return new FxPick(rng, min, max, sc); + return new FxPick(rng, list, sc); } else if (sc.CheckToken(TK_FRandom)) { diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index 03e465c3ab..b53b8796b4 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -563,11 +563,11 @@ class FxPick : public FxExpression { protected: FRandom * rng; - FxExpression *min, *max; + TArray min; public: - FxPick(FRandom *, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos); + FxPick(FRandom *, TArray mi, const FScriptPosition &pos); ~FxPick(); FxExpression *Resolve(FCompileContext&); diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index dc2cb22091..dd8e0e4c96 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -1696,15 +1696,17 @@ ExpVal FxRandom::EvalExpression (AActor *self) // // //========================================================================== -FxPick::FxPick(FRandom * r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos) +FxPick::FxPick(FRandom * r, TArray mi, const FScriptPosition &pos) : FxExpression(pos) { - if (mi != NULL && ma != NULL) + int index = 0; + int max = mi.Size(); + if (max > 0) { - min = new FxIntCast(mi); - max = new FxIntCast(ma); + for (index = 0; index < max; index++) + min.Push(new FxIntCast(mi[index])); } - else min = max = NULL; + else min.Clear(); rng = r; ValueType = VAL_Int; } @@ -1717,8 +1719,7 @@ FxPick::FxPick(FRandom * r, FxExpression *mi, FxExpression *ma, const FScriptPos FxPick::~FxPick() { - SAFE_DELETE(min); - SAFE_DELETE(max); + min.Clear(); } //========================================================================== @@ -1729,12 +1730,17 @@ FxPick::~FxPick() FxExpression *FxPick::Resolve(FCompileContext &ctx) { + int index = 0; CHECKRESOLVED(); - if (min && max) + int max = min.Size(); + if (max > 0) { - RESOLVE(min, ctx); - RESOLVE(max, ctx); - ABORT(min && max); + for (index = 0; index < max; index++) + { + RESOLVE(min[index], ctx); + ABORT(min[index]); + } + } return this; }; @@ -1750,22 +1756,11 @@ ExpVal FxPick::EvalExpression(AActor *self) { ExpVal val; val.Type = VAL_Int; - - if (min != NULL && max != NULL) + int max = min.Size(); + if (max > 0) { - int minval = min->EvalExpression(self).GetInt(); - int maxval = max->EvalExpression(self).GetInt(); - - if (maxval < minval) - { - swapvalues(maxval, minval); - } - - val.Int = (*rng)(2); //rng->operator()(2); //(maxval - minval + 1) + minval; - if (val.Int > 0) - val.Int = maxval; - else - val.Int = minval; + int select = (*rng)(max); + val.Int = min[select]->EvalExpression(self).GetInt(); } else { From 6410428715cdcffdc4727ef31ca3549d40105f00 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 14 Dec 2014 12:03:55 +0100 Subject: [PATCH 11/13] - fixed: FxPick leaked the array's content. Also did some cleanup on FxPick code. --- src/thingdef/thingdef_exp.h | 2 +- src/thingdef/thingdef_expression.cpp | 21 +++++---------------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index b53b8796b4..0e03c661f3 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -563,7 +563,7 @@ class FxPick : public FxExpression { protected: FRandom * rng; - TArray min; + TDeletingArray min; public: diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index dd8e0e4c96..913079bd20 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -1699,14 +1699,10 @@ ExpVal FxRandom::EvalExpression (AActor *self) FxPick::FxPick(FRandom * r, TArray mi, const FScriptPosition &pos) : FxExpression(pos) { - int index = 0; - int max = mi.Size(); - if (max > 0) + for (unsigned int index = 0; index < mi.Size(); index++) { - for (index = 0; index < max; index++) - min.Push(new FxIntCast(mi[index])); + min.Push(new FxIntCast(mi[index])); } - else min.Clear(); rng = r; ValueType = VAL_Int; } @@ -1719,7 +1715,6 @@ FxPick::FxPick(FRandom * r, TArray mi, const FScriptPosition &pos FxPick::~FxPick() { - min.Clear(); } //========================================================================== @@ -1730,17 +1725,11 @@ FxPick::~FxPick() FxExpression *FxPick::Resolve(FCompileContext &ctx) { - int index = 0; CHECKRESOLVED(); - int max = min.Size(); - if (max > 0) + for (unsigned int index = 0; index < min.Size(); index++) { - for (index = 0; index < max; index++) - { - RESOLVE(min[index], ctx); - ABORT(min[index]); - } - + RESOLVE(min[index], ctx); + ABORT(min[index]); } return this; }; From b6c5cfb9efc8f398d09cbbfde3da653bdb968eaf Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Mon, 15 Dec 2014 10:26:22 -0600 Subject: [PATCH 12/13] - Fixed: The new HIT* flags were checking the wrong actor. --- src/p_mobj.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 39d1ba12d8..49b4b983fd 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1202,9 +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 (target->flags7 & MF7_HITTARGET) mo->target = target; - if (target->flags7 & MF7_HITMASTER) mo->master = target; - if (target->flags7 & MF7_HITTRACER) mo->tracer = target; + 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); } From 465d9ab89a288e9194b5143eb6a54d92692ba5ea Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Mon, 15 Dec 2014 14:50:35 -0600 Subject: [PATCH 13/13] - Added flags for A_CheckLOF: - CLOFF_SETTARGET | CLOFF_SETMASTER | CLOFF_SETTRACER - An actor that causes A_CheckLOF (and only an actor) to succeed will set the intercepting actor as its target, master, and/or tracer, respectively. --- src/thingdef/thingdef_codeptr.cpp | 57 ++++++++++++++++++------------ wadsrc/static/actors/constants.txt | 4 +++ 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index a620f0080a..2a2da343e7 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -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); } } diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 22914fbfc0..8695c9c199 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -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 };