# Conflicts:
#	src/swrenderer/line/r_walldraw.cpp
#	src/version.h
This commit is contained in:
Rachael Alexanderson 2019-02-10 04:11:29 -05:00
commit 0f2fd5c4c9
305 changed files with 10892 additions and 10730 deletions

View file

@ -33,7 +33,7 @@ build_script:
- md build
- cd build
- cmake -G "%GENERATOR%" -T "%TOOLSET%" -DPK3_QUIET_ZIPDIR=YES ..
- cmake --build . --config "%CONFIGURATION%" -- /verbosity:minimal
- cmake --build . --config "%CONFIGURATION%" -- -maxcpucount -verbosity:minimal
after_build:
- set OUTPUT_DIR=%APPVEYOR_BUILD_FOLDER%\build\%CONFIGURATION%\

View file

@ -1,5 +1,5 @@
language: c++
dist: trusty
language: cpp
dist: xenial
branches:
except:
@ -27,8 +27,6 @@ matrix:
- CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS=-Wno-maybe-uninitialized"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.9
- libsdl2-dev
@ -41,8 +39,6 @@ matrix:
- CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS=-Wno-maybe-uninitialized"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
- libsdl2-dev
@ -99,7 +95,7 @@ matrix:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-7
- llvm-toolchain-xenial-7
packages:
- clang-7
- libsdl2-dev
@ -110,6 +106,14 @@ matrix:
- libfluidsynth-dev
- libgtk-3-dev
- os: windows
env:
- CMAKE_OPTIONS="-A Win32"
- os: windows
env:
- CMAKE_OPTIONS="-A x64"
before_install:
- if [ -n "$GCC_VERSION" ]; then export CC="gcc-${GCC_VERSION}" CXX="g++-${GCC_VERSION}"; fi
- if [ -n "$CLANG_VERSION" ]; then export CC="clang-${CLANG_VERSION}" CXX="clang++-${CLANG_VERSION}"; fi
@ -128,7 +132,8 @@ script:
-DFORCE_INTERNAL_GME=YES \
-DPK3_QUIET_ZIPDIR=YES \
..
- make -j2 -k
- if [[ $TRAVIS_OS_NAME == 'windows' ]]; then cmake --build . --config Release -- -maxcpucount -verbosity:minimal; fi
- if [[ $TRAVIS_OS_NAME != 'windows' ]]; then cmake --build . -- --jobs=2 --keep-going; fi
notifications:
email: false

View file

@ -163,14 +163,29 @@ option( NO_OPENAL "Disable OpenAL sound support" OFF )
find_package( BZip2 )
find_package( JPEG )
find_package( ZLIB )
find_package( asmjit )
include( TargetArch )
target_architecture(ZDOOM_TARGET_ARCH)
if( ${ZDOOM_TARGET_ARCH} MATCHES "x86_64" )
set( HAVE_VM_JIT ON )
endif()
# no, we're not using external asmjit for now, we made too many modifications to our's.
# if the asmjit author uses our changes then we'll update this.
#if( ${HAVE_VM_JIT} )
# find_package( asmjit )
#endif()
# GME
find_path( GME_INCLUDE_DIR gme/gme.h )
find_library( GME_LIBRARIES gme )
mark_as_advanced( GME_INCLUDE_DIR GME_LIBRARIES )
FIND_PACKAGE_HANDLE_STANDARD_ARGS( GME
REQUIRED_VARS GME_LIBRARIES GME_INCLUDE_DIR
)
#find_path( GME_INCLUDE_DIR gme/gme.h )
#find_library( GME_LIBRARIES gme )
#mark_as_advanced( GME_INCLUDE_DIR GME_LIBRARIES )
#FIND_PACKAGE_HANDLE_STANDARD_ARGS( GME
# REQUIRED_VARS GME_LIBRARIES GME_INCLUDE_DIR
#)
if( MSVC )
# Eliminate unreferenced functions and data
@ -222,6 +237,7 @@ if( MSVC )
string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE} )
string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_MINSIZEREL ${CMAKE_CXX_FLAGS_MINSIZEREL} )
string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} )
string(REPLACE "/Ob1 " "/Ob2 " CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} )
string(REPLACE "/MDd " " " CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG} )
string(REPLACE "/MD " " " CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} )
string(REPLACE "/MD " " " CMAKE_C_FLAGS_MINSIZEREL ${CMAKE_C_FLAGS_MINSIZEREL} )
@ -271,8 +287,10 @@ set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEB_C_FLAGS} -D_DEBUG" )
option(FORCE_INTERNAL_ZLIB "Use internal zlib")
option(FORCE_INTERNAL_JPEG "Use internal jpeg")
option(FORCE_INTERNAL_BZIP2 "Use internal bzip2")
option(FORCE_INTERNAL_GME "Use internal gme")
option(FORCE_INTERNAL_ASMJIT "Use internal asmjit")
option(FORCE_INTERNAL_GME "Use internal gme" ON)
mark_as_advanced( FORCE_INTERNAL_GME )
option(FORCE_INTERNAL_ASMJIT "Use internal asmjit" ON)
mark_as_advanced( FORCE_INTERNAL_ASMJIT )
# Fast math flags, required by some subprojects
set( ZD_FASTMATH_FLAG "" )
@ -293,15 +311,17 @@ else()
set( ZLIB_LIBRARY z )
endif()
if( ASMJIT_FOUND AND NOT FORCE_INTERNAL_ASMJIT )
message( STATUS "Using system asmjit, includes found at ${ASMJIT_INCLUDE_DIR}" )
else()
message( STATUS "Using internal asmjit" )
set( SKIP_INSTALL_ALL TRUE ) # Avoid installing asmjit alongside zdoom
add_subdirectory( asmjit )
set( ASMJIT_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/asmjit )
set( ASMJIT_LIBRARIES asmjit )
set( ASMJIT_LIBRARY asmjit )
if( ${HAVE_VM_JIT} )
if( ASMJIT_FOUND AND NOT FORCE_INTERNAL_ASMJIT )
message( STATUS "Using system asmjit, includes found at ${ASMJIT_INCLUDE_DIR}" )
else()
message( STATUS "Using internal asmjit" )
set( SKIP_INSTALL_ALL TRUE ) # Avoid installing asmjit alongside zdoom
add_subdirectory( asmjit )
set( ASMJIT_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/asmjit )
set( ASMJIT_LIBRARIES asmjit )
set( ASMJIT_LIBRARY asmjit )
endif()
endif()
if( JPEG_FOUND AND NOT FORCE_INTERNAL_JPEG )

View file

@ -1,4 +1,4 @@
// Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
/*
Last validated with zexall 2006.11.14 2:19 PM
@ -162,6 +162,11 @@ static byte const ed_dd_timing [0x100] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
};
// even on x86, using short and unsigned char was slower
typedef int fint16;
typedef unsigned fuint16;
typedef unsigned fuint8;
bool Kss_Cpu::run( cpu_time_t end_time )
{
set_end_time( end_time );
@ -178,10 +183,10 @@ bool Kss_Cpu::run( cpu_time_t end_time )
rg = this->r.b;
cpu_time_t s_time = s.time;
uint16_t pc = r.pc;
uint16_t sp = r.sp;
uint16_t ix = r.ix; // TODO: keep in memory for direct access?
uint16_t iy = r.iy;
fuint16 pc = r.pc;
fuint16 sp = r.sp;
fuint16 ix = r.ix; // TODO: keep in memory for direct access?
fuint16 iy = r.iy;
int flags = r.b.flags;
goto loop;
@ -203,7 +208,7 @@ loop:
uint8_t const* instr = s.read [pc >> page_shift];
#define GET_ADDR() GET_LE16( instr )
uint8_t opcode;
fuint8 opcode;
// TODO: eliminate this special case
#if BLARGG_NONPORTABLE
@ -236,7 +241,7 @@ loop:
11,10,10, 4,17,11, 7,11,11, 6,10, 4,17, 8, 7,11, // F
};
uint16_t data;
fuint16 data;
data = base_timing [opcode];
if ( (s_time += data) >= 0 )
goto possibly_out_of_time;
@ -292,7 +297,7 @@ possibly_out_of_time:
goto loop;
case 0x3A:{// LD A,(addr)
uint16_t addr = GET_ADDR();
fuint16 addr = GET_ADDR();
pc += 2;
rg.a = READ( addr );
goto loop;
@ -380,7 +385,7 @@ possibly_out_of_time:
case 0xCD:{// CALL addr
call_taken:
uint16_t addr = pc + 2;
fuint16 addr = pc + 2;
pc = GET_ADDR();
sp = uint16_t (sp - 2);
WRITE_WORD( sp, addr );
@ -388,7 +393,7 @@ possibly_out_of_time:
}
case 0xFF: // RST
if ( pc >= idle_addr )
if ( pc > idle_addr )
goto hit_idle_addr;
CASE7( C7, CF, D7, DF, E7, EF, F7 ):
data = pc;
@ -496,7 +501,7 @@ possibly_out_of_time:
add_hl_data: {
blargg_ulong sum = rp.hl + data;
data ^= rp.hl;
rp.hl = sum;
rp.hl = (uint16_t)sum;
flags = (flags & (S80 | Z40 | V04)) |
(sum >> 16) |
(sum >> 8 & (F20 | F08)) |
@ -686,21 +691,21 @@ possibly_out_of_time:
goto loop;
case 0x2A:{// LD HL,(addr)
uint16_t addr = GET_ADDR();
fuint16 addr = GET_ADDR();
pc += 2;
rp.hl = READ_WORD( addr );
goto loop;
}
case 0x32:{// LD (addr),A
uint16_t addr = GET_ADDR();
fuint16 addr = GET_ADDR();
pc += 2;
WRITE( addr, rg.a );
goto loop;
}
case 0x22:{// LD (addr),HL
uint16_t addr = GET_ADDR();
fuint16 addr = GET_ADDR();
pc += 2;
WRITE_WORD( addr, rp.hl );
goto loop;
@ -723,7 +728,7 @@ possibly_out_of_time:
// Rotate
case 0x07:{// RLCA
uint16_t temp = rg.a;
fuint16 temp = rg.a;
temp = (temp << 1) | (temp >> 7);
flags = (flags & (S80 | Z40 | P04)) |
(temp & (F20 | F08 | C01));
@ -732,7 +737,7 @@ possibly_out_of_time:
}
case 0x0F:{// RRCA
uint16_t temp = rg.a;
fuint16 temp = rg.a;
flags = (flags & (S80 | Z40 | P04)) |
(temp & C01);
temp = (temp << 7) | (temp >> 1);
@ -746,12 +751,12 @@ possibly_out_of_time:
flags = (flags & (S80 | Z40 | P04)) |
(temp & (F20 | F08)) |
(temp >> 8);
rg.a = temp;
rg.a = (uint8_t)temp;
goto loop;
}
case 0x1F:{// RRA
uint16_t temp = (flags << 7) | (rg.a >> 1);
fuint16 temp = (flags << 7) | (rg.a >> 1);
flags = (flags & (S80 | Z40 | P04)) |
(temp & (F20 | F08)) |
(rg.a & C01);
@ -761,7 +766,7 @@ possibly_out_of_time:
// Misc
case 0x2F:{// CPL
uint16_t temp = ~rg.a;
fuint16 temp = ~rg.a;
flags = (flags & (S80 | Z40 | P04 | C01)) |
(temp & (F20 | F08)) |
(H10 | N02);
@ -787,21 +792,21 @@ possibly_out_of_time:
goto loop;
case 0xE3:{// EX (SP),HL
uint16_t temp = READ_WORD( sp );
fuint16 temp = READ_WORD( sp );
WRITE_WORD( sp, rp.hl );
rp.hl = temp;
goto loop;
}
case 0xEB:{// EX DE,HL
uint16_t temp = rp.hl;
fuint16 temp = rp.hl;
rp.hl = rp.de;
rp.de = temp;
goto loop;
}
case 0xD9:{// EXX DE,HL
uint16_t temp = r.alt.w.bc;
fuint16 temp = r.alt.w.bc;
r.alt.w.bc = rp.bc;
rp.bc = temp;
@ -842,7 +847,7 @@ possibly_out_of_time:
// Rotate left
#define RLC( read, write ) {\
uint8_t result = read;\
fuint8 result = read;\
result = uint8_t (result << 1) | (result >> 7);\
flags = SZ28P( result ) | (result & C01);\
write;\
@ -861,7 +866,7 @@ possibly_out_of_time:
}
#define RL( read, write ) {\
uint16_t result = (read << 1) | (flags & C01);\
fuint16 result = (read << 1) | (flags & C01);\
flags = SZ28PC( result );\
write;\
goto loop;\
@ -879,7 +884,7 @@ possibly_out_of_time:
}
#define SLA( read, add, write ) {\
uint16_t result = (read << 1) | add;\
fuint16 result = (read << 1) | add;\
flags = SZ28PC( result );\
write;\
goto loop;\
@ -910,7 +915,7 @@ possibly_out_of_time:
// Rotate right
#define RRC( read, write ) {\
uint8_t result = read;\
fuint8 result = read;\
flags = result & C01;\
result = uint8_t (result << 7) | (result >> 1);\
flags |= SZ28P( result );\
@ -930,8 +935,8 @@ possibly_out_of_time:
}
#define RR( read, write ) {\
uint8_t result = read;\
uint8_t temp = result & C01;\
fuint8 result = read;\
fuint8 temp = result & C01;\
result = uint8_t (flags << 7) | (result >> 1);\
flags = SZ28P( result ) | temp;\
write;\
@ -950,7 +955,7 @@ possibly_out_of_time:
}
#define SRA( read, write ) {\
uint8_t result = read;\
fuint8 result = read;\
flags = result & C01;\
result = (result & 0x80) | (result >> 1);\
flags |= SZ28P( result );\
@ -970,7 +975,7 @@ possibly_out_of_time:
}
#define SRL( read, write ) {\
uint8_t result = read;\
fuint8 result = read;\
flags = result & C01;\
result >>= 1;\
flags |= SZ28P( result );\
@ -1078,7 +1083,7 @@ possibly_out_of_time:
blargg_ulong sum = temp + (flags & C01);
flags = ~data >> 2 & N02;
if ( flags )
sum = -sum;
sum = (blargg_ulong)-(blargg_long)sum;
sum += rp.hl;
temp ^= rp.hl;
temp ^= sum;
@ -1086,7 +1091,7 @@ possibly_out_of_time:
(temp >> 8 & H10) |
(sum >> 8 & (S80 | F20 | F08)) |
((temp - -0x8000) >> 14 & V04);
rp.hl = sum;
rp.hl = (uint16_t)sum;
if ( (uint16_t) sum )
goto loop;
flags |= Z40;
@ -1114,7 +1119,7 @@ possibly_out_of_time:
case 0x43: // LD (ADDR),BC
case 0x53: // LD (ADDR),DE
temp = R16( data, 4, 0x43 );
uint16_t addr = GET_ADDR();
fuint16 addr = GET_ADDR();
pc += 2;
WRITE_WORD( addr, temp );
goto loop;
@ -1122,21 +1127,21 @@ possibly_out_of_time:
case 0x4B: // LD BC,(ADDR)
case 0x5B:{// LD DE,(ADDR)
uint16_t addr = GET_ADDR();
fuint16 addr = GET_ADDR();
pc += 2;
R16( data, 4, 0x4B ) = READ_WORD( addr );
goto loop;
}
case 0x7B:{// LD SP,(ADDR)
uint16_t addr = GET_ADDR();
fuint16 addr = GET_ADDR();
pc += 2;
sp = READ_WORD( addr );
goto loop;
}
case 0x67:{// RRD
uint8_t temp = READ( rp.hl );
fuint8 temp = READ( rp.hl );
WRITE( rp.hl, (rg.a << 4) | (temp >> 4) );
temp = (rg.a & 0xF0) | (temp & 0x0F);
flags = (flags & C01) | SZ28P( temp );
@ -1145,7 +1150,7 @@ possibly_out_of_time:
}
case 0x6F:{// RLD
uint8_t temp = READ( rp.hl );
fuint8 temp = READ( rp.hl );
WRITE( rp.hl, (temp << 4) | (rg.a & 0x0F) );
temp = (rg.a & 0xF0) | (temp >> 4);
flags = (flags & C01) | SZ28P( temp );
@ -1169,7 +1174,7 @@ possibly_out_of_time:
case 0xA1: // CPI
case 0xB1: // CPIR
inc = +1;
uint16_t addr = rp.hl;
fuint16 addr = rp.hl;
rp.hl = addr + inc;
int temp = READ( addr );
@ -1202,7 +1207,7 @@ possibly_out_of_time:
case 0xA0: // LDI
case 0xB0: // LDIR
inc = +1;
uint16_t addr = rp.hl;
fuint16 addr = rp.hl;
rp.hl = addr + inc;
int temp = READ( addr );
@ -1234,7 +1239,7 @@ possibly_out_of_time:
case 0xA3: // OUTI
case 0xB3: // OTIR
inc = +1;
uint16_t addr = rp.hl;
fuint16 addr = rp.hl;
rp.hl = addr + inc;
int temp = READ( addr );
@ -1260,7 +1265,7 @@ possibly_out_of_time:
case 0xB2: // INIR
inc = +1;
uint16_t addr = rp.hl;
fuint16 addr = rp.hl;
rp.hl = addr + inc;
int temp = IN( rp.bc );
@ -1325,7 +1330,7 @@ possibly_out_of_time:
//////////////////////////////////////// DD/FD prefix
{
uint16_t ixy;
fuint16 ixy;
case 0xDD:
ixy = ix;
goto ix_prefix;
@ -1521,7 +1526,7 @@ possibly_out_of_time:
goto loop;
case 0x22:{// LD (ADDR),IXY
uint16_t addr = GET_ADDR();
fuint16 addr = GET_ADDR();
pc += 2;
WRITE_WORD( addr, ixy );
goto loop;
@ -1533,7 +1538,7 @@ possibly_out_of_time:
goto set_ixy;
case 0x2A:{// LD IXY,(addr)
uint16_t addr = GET_ADDR();
fuint16 addr = GET_ADDR();
ixy = READ_WORD( addr );
pc += 2;
goto set_ixy;
@ -1557,7 +1562,7 @@ possibly_out_of_time:
case 0x3E: goto srl_data_addr; // SRL (IXY)
CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ):{// BIT b,(IXY+disp)
uint8_t temp = READ( data );
fuint8 temp = READ( data );
int masked = temp & 1 << (data2 >> 3 & 7);
flags = (flags & C01) | H10 |
(masked & S80) |
@ -1659,7 +1664,7 @@ possibly_out_of_time:
goto loop;
case 0xE3:{// EX (SP),IXY
uint16_t temp = READ_WORD( sp );
fuint16 temp = READ_WORD( sp );
WRITE_WORD( sp, ixy );
ixy = temp;
goto set_ixy;

View file

@ -299,11 +299,6 @@ blargg_err_t Spc_Emu::start_track_( int track )
RETURN_ERR( apu.load_spc( file_data, file_size ) );
filter.set_gain( (int) (gain() * SPC_Filter::gain_unit) );
apu.clear_echo();
track_info_t spc_info;
RETURN_ERR( track_info_( &spc_info, track ) );
// Set a default track length, need a non-zero fadeout
if ( spc_info.length > 0 )
set_fade ( spc_info.length, 50 );
return 0;
}

View file

@ -1,5 +1,5 @@
/* 7zArcIn.c -- 7z Input functions
2017-04-03 : Igor Pavlov : Public domain */
2018-07-04 : Igor Pavlov : Public domain */
#include "Precomp.h"
@ -1744,7 +1744,7 @@ size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex)
UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
{
Bool needSlash;
BoolInt needSlash;
if (!p->FileNameOffsets)
{
*(--dest) = 0;

View file

@ -1,5 +1,5 @@
/* 7zDec.c -- Decoding from 7z folder
2017-04-03 : Igor Pavlov : Public domain */
2018-07-04 : Igor Pavlov : Public domain */
#include "Precomp.h"
@ -44,7 +44,7 @@ typedef struct
const Byte *end;
const Byte *begin;
UInt64 processed;
Bool extra;
BoolInt extra;
SRes res;
const ILookInStream *inStream;
} CByteInToLook;
@ -269,7 +269,7 @@ static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer
return SZ_OK;
}
static Bool IS_MAIN_METHOD(UInt32 m)
static BoolInt IS_MAIN_METHOD(UInt32 m)
{
switch (m)
{
@ -286,7 +286,7 @@ static Bool IS_MAIN_METHOD(UInt32 m)
return False;
}
static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
static BoolInt IS_SUPPORTED_CODER(const CSzCoderInfo *c)
{
return
c->NumStreams == 1

View file

@ -1,5 +1,5 @@
/* 7zTypes.h -- Basic types
2017-07-17 : Igor Pavlov : Public domain */
2018-08-04 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H
#define __7Z_TYPES_H
@ -103,7 +103,8 @@ typedef UInt32 SizeT;
typedef size_t SizeT;
#endif
typedef int Bool;
typedef int BoolInt;
/* typedef BoolInt Bool; */
#define True 1
#define False 0

View file

@ -1,7 +1,7 @@
#define MY_VER_MAJOR 18
#define MY_VER_MINOR 05
#define MY_VER_MINOR 06
#define MY_VER_BUILD 0
#define MY_VERSION_NUMBERS "18.05"
#define MY_VERSION_NUMBERS "18.06"
#define MY_VERSION MY_VERSION_NUMBERS
#ifdef MY_CPU_NAME
@ -10,7 +10,7 @@
#define MY_VERSION_CPU MY_VERSION
#endif
#define MY_DATE "2018-04-30"
#define MY_DATE "2018-12-30"
#undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov"

View file

@ -1,5 +1,5 @@
/* CpuArch.c -- CPU specific code
2016-02-25: Igor Pavlov : Public domain */
2018-07-04: Igor Pavlov : Public domain */
#include "Precomp.h"
@ -115,7 +115,7 @@ void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
#endif
}
Bool x86cpuid_CheckAndRead(Cx86cpuid *p)
BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p)
{
CHECK_CPUID_IS_SUPPORTED
MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
@ -144,7 +144,7 @@ int x86cpuid_GetFirm(const Cx86cpuid *p)
return -1;
}
Bool CPU_Is_InOrder()
BoolInt CPU_Is_InOrder()
{
Cx86cpuid p;
int firm;
@ -175,7 +175,7 @@ Bool CPU_Is_InOrder()
#if !defined(MY_CPU_AMD64) && defined(_WIN32)
#include <windows.h>
static Bool CPU_Sys_Is_SSE_Supported()
static BoolInt CPU_Sys_Is_SSE_Supported()
{
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi);
@ -188,7 +188,7 @@ static Bool CPU_Sys_Is_SSE_Supported()
#define CHECK_SYS_SSE_SUPPORT
#endif
Bool CPU_Is_Aes_Supported()
BoolInt CPU_Is_Aes_Supported()
{
Cx86cpuid p;
CHECK_SYS_SSE_SUPPORT

View file

@ -1,5 +1,5 @@
/* CpuArch.h -- CPU specific code
2017-09-04 : Igor Pavlov : Public domain */
2018-07-04 : Igor Pavlov : Public domain */
#ifndef __CPU_ARCH_H
#define __CPU_ARCH_H
@ -318,15 +318,15 @@ enum
void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d);
Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p);
int x86cpuid_GetFirm(const Cx86cpuid *p);
#define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF))
#define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF))
#define x86cpuid_GetStepping(ver) (ver & 0xF)
Bool CPU_Is_InOrder();
Bool CPU_Is_Aes_Supported();
BoolInt CPU_Is_InOrder();
BoolInt CPU_Is_Aes_Supported();
#endif

View file

@ -1,5 +1,5 @@
/* LzFind.c -- Match finder for LZ algorithms
2017-06-10 : Igor Pavlov : Public domain */
2018-07-08 : Igor Pavlov : Public domain */
#include "Precomp.h"
@ -138,7 +138,7 @@ static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
void MatchFinder_Construct(CMatchFinder *p)
{
UInt32 i;
unsigned i;
p->bufferBase = NULL;
p->directInput = 0;
p->hash = NULL;
@ -147,7 +147,7 @@ void MatchFinder_Construct(CMatchFinder *p)
for (i = 0; i < 256; i++)
{
UInt32 r = i;
UInt32 r = (UInt32)i;
unsigned j;
for (j = 0; j < 8; j++)
r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
@ -368,6 +368,8 @@ static void MatchFinder_Normalize(CMatchFinder *p)
MatchFinder_ReduceOffsets(p, subValue);
}
MY_NO_INLINE
static void MatchFinder_CheckLimits(CMatchFinder *p)
{
if (p->pos == kMaxValForNormalize)
@ -379,10 +381,16 @@ static void MatchFinder_CheckLimits(CMatchFinder *p)
MatchFinder_SetLimits(p);
}
static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
/*
(lenLimit > maxLen)
*/
MY_FORCE_INLINE
static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
UInt32 *distances, UInt32 maxLen)
UInt32 *distances, unsigned maxLen)
{
/*
son[_cyclicBufferPos] = curMatch;
for (;;)
{
@ -400,7 +408,8 @@ static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos,
break;
if (maxLen < len)
{
*distances++ = maxLen = len;
maxLen = len;
*distances++ = len;
*distances++ = delta - 1;
if (len == lenLimit)
return distances;
@ -408,15 +417,58 @@ static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos,
}
}
}
*/
const Byte *lim = cur + lenLimit;
son[_cyclicBufferPos] = curMatch;
do
{
UInt32 delta = pos - curMatch;
if (delta >= _cyclicBufferSize)
break;
{
ptrdiff_t diff;
curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
diff = (ptrdiff_t)0 - delta;
if (cur[maxLen] == cur[maxLen + diff])
{
const Byte *c = cur;
while (*c == c[diff])
{
if (++c == lim)
{
distances[0] = (UInt32)(lim - cur);
distances[1] = delta - 1;
return distances + 2;
}
}
{
unsigned len = (unsigned)(c - cur);
if (maxLen < len)
{
maxLen = len;
distances[0] = (UInt32)len;
distances[1] = delta - 1;
distances += 2;
}
}
}
}
}
while (--cutValue);
return distances;
}
MY_FORCE_INLINE
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
UInt32 *distances, UInt32 maxLen)
{
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
UInt32 len0 = 0, len1 = 0;
CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
unsigned len0 = 0, len1 = 0;
for (;;)
{
UInt32 delta = pos - curMatch;
@ -426,9 +478,10 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt
return distances;
}
{
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
const Byte *pb = cur - delta;
UInt32 len = (len0 < len1 ? len0 : len1);
unsigned len = (len0 < len1 ? len0 : len1);
UInt32 pair0 = pair[0];
if (pb[len] == cur[len])
{
if (++len != lenLimit && pb[len] == cur[len])
@ -437,11 +490,12 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt
break;
if (maxLen < len)
{
*distances++ = maxLen = len;
maxLen = (UInt32)len;
*distances++ = (UInt32)len;
*distances++ = delta - 1;
if (len == lenLimit)
{
*ptr1 = pair[0];
*ptr1 = pair0;
*ptr0 = pair[1];
return distances;
}
@ -468,9 +522,9 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt
static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
{
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
UInt32 len0 = 0, len1 = 0;
CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
unsigned len0 = 0, len1 = 0;
for (;;)
{
UInt32 delta = pos - curMatch;
@ -480,9 +534,9 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const
return;
}
{
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
const Byte *pb = cur - delta;
UInt32 len = (len0 < len1 ? len0 : len1);
unsigned len = (len0 < len1 ? len0 : len1);
if (pb[len] == cur[len])
{
while (++len != lenLimit)
@ -520,13 +574,13 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const
p->buffer++; \
if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
#define MOVE_POS_RET MOVE_POS return offset;
#define MOVE_POS_RET MOVE_POS return (UInt32)offset;
static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
#define GET_MATCHES_HEADER2(minLen, ret_op) \
UInt32 lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
unsigned lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
cur = p->buffer;
#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
@ -535,22 +589,22 @@ static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
#define GET_MATCHES_FOOTER(offset, maxLen) \
offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
distances + offset, maxLen) - distances); MOVE_POS_RET;
offset = (unsigned)(GetMatchesSpec1((UInt32)lenLimit, curMatch, MF_PARAMS(p), \
distances + offset, (UInt32)maxLen) - distances); MOVE_POS_RET;
#define SKIP_FOOTER \
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
#define UPDATE_maxLen { \
ptrdiff_t diff = (ptrdiff_t)0 - d2; \
const Byte *c = cur + maxLen; \
const Byte *lim = cur + lenLimit; \
for (; c != lim; c++) if (*(c + diff) != *c) break; \
maxLen = (UInt32)(c - cur); }
maxLen = (unsigned)(c - cur); }
static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 offset;
unsigned offset;
GET_MATCHES_HEADER(2)
HASH2_CALC;
curMatch = p->hash[hv];
@ -561,7 +615,7 @@ static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 offset;
unsigned offset;
GET_MATCHES_HEADER(3)
HASH_ZIP_CALC;
curMatch = p->hash[hv];
@ -572,7 +626,8 @@ UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 h2, d2, maxLen, offset, pos;
UInt32 h2, d2, pos;
unsigned maxLen, offset;
UInt32 *hash;
GET_MATCHES_HEADER(3)
@ -594,12 +649,12 @@ static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{
UPDATE_maxLen
distances[0] = maxLen;
distances[0] = (UInt32)maxLen;
distances[1] = d2 - 1;
offset = 2;
if (maxLen == lenLimit)
{
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p));
MOVE_POS_RET;
}
}
@ -609,7 +664,8 @@ static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 h2, h3, d2, d3, maxLen, offset, pos;
UInt32 h2, h3, d2, d3, pos;
unsigned maxLen, offset;
UInt32 *hash;
GET_MATCHES_HEADER(4)
@ -618,12 +674,12 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
hash = p->hash;
pos = p->pos;
d2 = pos - hash[ h2];
d2 = pos - hash [h2];
d3 = pos - (hash + kFix3HashSize)[h3];
curMatch = (hash + kFix4HashSize)[hv];
hash[ h2] = pos;
hash [h2] = pos;
(hash + kFix3HashSize)[h3] = pos;
(hash + kFix4HashSize)[hv] = pos;
@ -632,7 +688,8 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{
distances[0] = maxLen = 2;
maxLen = 2;
distances[0] = 2;
distances[1] = d2 - 1;
offset = 2;
}
@ -648,10 +705,10 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (offset != 0)
{
UPDATE_maxLen
distances[(size_t)offset - 2] = maxLen;
distances[(size_t)offset - 2] = (UInt32)maxLen;
if (maxLen == lenLimit)
{
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p));
MOVE_POS_RET;
}
}
@ -674,13 +731,13 @@ static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
hash = p->hash;
pos = p->pos;
d2 = pos - hash[ h2];
d2 = pos - hash [h2];
d3 = pos - (hash + kFix3HashSize)[h3];
d4 = pos - (hash + kFix4HashSize)[h4];
curMatch = (hash + kFix5HashSize)[hv];
hash[ h2] = pos;
hash [h2] = pos;
(hash + kFix3HashSize)[h3] = pos;
(hash + kFix4HashSize)[h4] = pos;
(hash + kFix5HashSize)[hv] = pos;
@ -741,7 +798,8 @@ static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 h2, h3, d2, d3, maxLen, offset, pos;
UInt32 h2, h3, d2, d3, pos;
unsigned maxLen, offset;
UInt32 *hash;
GET_MATCHES_HEADER(4)
@ -750,12 +808,11 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
hash = p->hash;
pos = p->pos;
d2 = pos - hash[ h2];
d2 = pos - hash [h2];
d3 = pos - (hash + kFix3HashSize)[h3];
curMatch = (hash + kFix4HashSize)[hv];
hash[ h2] = pos;
hash [h2] = pos;
(hash + kFix3HashSize)[h3] = pos;
(hash + kFix4HashSize)[hv] = pos;
@ -764,7 +821,8 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{
distances[0] = maxLen = 2;
maxLen = 2;
distances[0] = 2;
distances[1] = d2 - 1;
offset = 2;
}
@ -780,7 +838,7 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (offset != 0)
{
UPDATE_maxLen
distances[(size_t)offset - 2] = maxLen;
distances[(size_t)offset - 2] = (UInt32)maxLen;
if (maxLen == lenLimit)
{
p->son[p->cyclicBufferPos] = curMatch;
@ -791,7 +849,7 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (maxLen < 3)
maxLen = 3;
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
offset = (unsigned)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
distances + offset, maxLen) - (distances));
MOVE_POS_RET
}
@ -808,13 +866,13 @@ static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
hash = p->hash;
pos = p->pos;
d2 = pos - hash[ h2];
d2 = pos - hash [h2];
d3 = pos - (hash + kFix3HashSize)[h3];
d4 = pos - (hash + kFix4HashSize)[h4];
curMatch = (hash + kFix5HashSize)[hv];
hash[ h2] = pos;
hash [h2] = pos;
(hash + kFix3HashSize)[h3] = pos;
(hash + kFix4HashSize)[h4] = pos;
(hash + kFix5HashSize)[hv] = pos;
@ -877,12 +935,12 @@ static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 offset;
unsigned offset;
GET_MATCHES_HEADER(3)
HASH_ZIP_CALC;
curMatch = p->hash[hv];
p->hash[hv] = p->pos;
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
offset = (unsigned)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
distances, 2) - (distances));
MOVE_POS_RET
}
@ -940,7 +998,7 @@ static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
HASH4_CALC;
hash = p->hash;
curMatch = (hash + kFix4HashSize)[hv];
hash[ h2] =
hash [h2] =
(hash + kFix3HashSize)[h3] =
(hash + kFix4HashSize)[hv] = p->pos;
SKIP_FOOTER
@ -959,7 +1017,7 @@ static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
HASH5_CALC;
hash = p->hash;
curMatch = (hash + kFix5HashSize)[hv];
hash[ h2] =
hash [h2] =
(hash + kFix3HashSize)[h3] =
(hash + kFix4HashSize)[h4] =
(hash + kFix5HashSize)[hv] = p->pos;
@ -979,7 +1037,7 @@ static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
HASH4_CALC;
hash = p->hash;
curMatch = (hash + kFix4HashSize)[hv];
hash[ h2] =
hash [h2] =
(hash + kFix3HashSize)[h3] =
(hash + kFix4HashSize)[hv] = p->pos;
p->son[p->cyclicBufferPos] = curMatch;
@ -999,7 +1057,7 @@ static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
HASH5_CALC;
hash = p->hash;
curMatch = hash + kFix5HashSize)[hv];
hash[ h2] =
hash [h2] =
(hash + kFix3HashSize)[h3] =
(hash + kFix4HashSize)[h4] =
(hash + kFix5HashSize)[hv] = p->pos;

View file

@ -1,5 +1,5 @@
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms
2017-06-10 : Igor Pavlov : Public domain */
2018-12-29 : Igor Pavlov : Public domain */
#include "Precomp.h"
@ -232,38 +232,57 @@ static void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
#define kEmptyHashValue 0
/* #define MFMT_GM_INLINE */
#define MFMT_GM_INLINE
#ifdef MFMT_GM_INLINE
#define NO_INLINE MY_FAST_CALL
/*
we use size_t for _cyclicBufferPos instead of UInt32
to eliminate "movsx" BUG in old MSVC x64 compiler.
*/
static Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
MY_NO_INLINE
static UInt32 *GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
UInt32 *distances, UInt32 _maxLen, const UInt32 *hash, const UInt32 *limit, UInt32 size, UInt32 *posRes)
{
do
{
UInt32 *distances = _distances + 1;
UInt32 curMatch = pos - *hash++;
UInt32 *_distances = ++distances;
UInt32 delta = *hash++;
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
UInt32 len0 = 0, len1 = 0;
CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
unsigned len0 = 0, len1 = 0;
UInt32 cutValue = _cutValue;
UInt32 maxLen = _maxLen;
for (;;)
unsigned maxLen = (unsigned)_maxLen;
/*
if (size > 1)
{
UInt32 delta = pos - curMatch;
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
UInt32 delta = *hash;
if (delta < _cyclicBufferSize)
{
*ptr0 = *ptr1 = kEmptyHashValue;
break;
UInt32 cyc1 = _cyclicBufferPos + 1;
CLzRef *pair = son + ((size_t)(cyc1 - delta + ((delta > cyc1) ? _cyclicBufferSize : 0)) << 1);
Byte b = *(cur + 1 - delta);
_distances[0] = pair[0];
_distances[1] = b;
}
}
*/
if (cutValue == 0 || delta >= _cyclicBufferSize)
{
*ptr0 = *ptr1 = kEmptyHashValue;
}
else
for(;;)
{
{
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((_cyclicBufferPos < delta) ? _cyclicBufferSize : 0)) << 1);
const Byte *pb = cur - delta;
UInt32 len = (len0 < len1 ? len0 : len1);
unsigned len = (len0 < len1 ? len0 : len1);
UInt32 pair0 = *pair;
if (pb[len] == cur[len])
{
if (++len != lenLimit && pb[len] == cur[len])
@ -272,54 +291,66 @@ static Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *
break;
if (maxLen < len)
{
*distances++ = maxLen = len;
maxLen = len;
*distances++ = (UInt32)len;
*distances++ = delta - 1;
if (len == lenLimit)
{
*ptr1 = pair[0];
*ptr0 = pair[1];
UInt32 pair1 = pair[1];
*ptr1 = pair0;
*ptr0 = pair1;
break;
}
}
}
if (pb[len] < cur[len])
{
*ptr1 = curMatch;
ptr1 = pair + 1;
curMatch = *ptr1;
len1 = len;
}
else
{
*ptr0 = curMatch;
ptr0 = pair;
curMatch = *ptr0;
len0 = len;
UInt32 curMatch = pos - delta;
// delta = pos - *pair;
// delta = pos - pair[((UInt32)pb[len] - (UInt32)cur[len]) >> 31];
if (pb[len] < cur[len])
{
delta = pos - pair[1];
*ptr1 = curMatch;
ptr1 = pair + 1;
len1 = len;
}
else
{
delta = pos - *pair;
*ptr0 = curMatch;
ptr0 = pair;
len0 = len;
}
}
}
if (--cutValue == 0 || delta >= _cyclicBufferSize)
{
*ptr0 = *ptr1 = kEmptyHashValue;
break;
}
}
pos++;
_cyclicBufferPos++;
cur++;
{
UInt32 num = (UInt32)(distances - _distances);
*_distances = num - 1;
_distances += num;
limit -= num;
_distances[-1] = num;
}
}
while (limit > 0 && --size != 0);
while (distances < limit && --size != 0);
*posRes = pos;
return limit;
return distances;
}
#endif
static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
{
UInt32 numProcessed = 0;
UInt32 curPos = 2;
UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);
UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); // * 2
distances[1] = p->hashNumAvail;
@ -369,8 +400,10 @@ static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
#else
{
UInt32 posRes;
curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos), size, &posRes);
curPos = (UInt32)(GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos,
distances + limit,
size, &posRes) - distances);
p->hashBufPos += posRes - pos;
cyclicBufferPos += posRes - pos;
p->buffer += posRes - pos;

View file

@ -1,5 +1,5 @@
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms
2017-04-03 : Igor Pavlov : Public domain */
2018-07-04 : Igor Pavlov : Public domain */
#ifndef __LZ_FIND_MT_H
#define __LZ_FIND_MT_H
@ -19,10 +19,10 @@ EXTERN_C_BEGIN
typedef struct _CMtSync
{
Bool wasCreated;
Bool needStart;
Bool exit;
Bool stopWriting;
BoolInt wasCreated;
BoolInt needStart;
BoolInt exit;
BoolInt stopWriting;
CThread thread;
CAutoResetEvent canStart;
@ -30,8 +30,8 @@ typedef struct _CMtSync
CAutoResetEvent wasStopped;
CSemaphore freeSemaphore;
CSemaphore filledSemaphore;
Bool csWasInitialized;
Bool csWasEntered;
BoolInt csWasInitialized;
BoolInt csWasEntered;
CCriticalSection cs;
UInt32 numProcessedBlocks;
} CMtSync;

View file

@ -1,5 +1,5 @@
/* Lzma2Dec.c -- LZMA2 Decoder
2018-02-19 : Igor Pavlov : Public domain */
2018-07-04 : Igor Pavlov : Public domain */
/* #define SHOW_DEBUG_INFO */
@ -169,7 +169,7 @@ static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT s
p->processedPos += (UInt32)size;
}
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);
void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
@ -232,7 +232,7 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
if (p->state == LZMA2_STATE_DATA)
{
Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
}
@ -254,8 +254,8 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
if (p->state == LZMA2_STATE_DATA)
{
Bool initDic = (p->control >= 0xE0);
Bool initState = (p->control >= 0xA0);
BoolInt initDic = (p->control >= 0xE0);
BoolInt initState = (p->control >= 0xA0);
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
p->state = LZMA2_STATE_DATA_CONT;
}

View file

@ -1,13 +1,13 @@
/* LzmaDec.c -- LZMA Decoder
2018-02-28 : Igor Pavlov : Public domain */
2018-07-04 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include <string.h>
/* #include "CpuArch.h" */
#include "LzmaDec.h"
#include <string.h>
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
@ -19,7 +19,7 @@
#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)
#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
@ -66,7 +66,7 @@
#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)
#define UPDATE_0_CHECK range = bound;
#define UPDATE_1_CHECK range -= bound; code -= bound;
#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
@ -539,7 +539,7 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit
curLen = ((rem < len) ? (unsigned)rem : len);
pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);
processedPos += curLen;
processedPos += (UInt32)curLen;
len -= curLen;
if (curLen <= dicBufSize - pos)
@ -547,7 +547,7 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit
Byte *dest = dic + dicPos;
ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
const Byte *lim = dest + curLen;
dicPos += curLen;
dicPos += (SizeT)curLen;
do
*(dest) = (Byte)*(dest + src);
while (++dest != lim);
@ -572,14 +572,14 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit
p->buf = buf;
p->range = range;
p->code = code;
p->remainLen = len;
p->remainLen = (UInt32)len;
p->dicPos = dicPos;
p->processedPos = processedPos;
p->reps[0] = rep0;
p->reps[1] = rep1;
p->reps[2] = rep2;
p->reps[3] = rep3;
p->state = state;
p->state = (UInt32)state;
return SZ_OK;
}
@ -601,8 +601,8 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
p->checkDicSize = p->prop.dicSize;
p->processedPos += len;
p->remainLen -= len;
p->processedPos += (UInt32)len;
p->remainLen -= (UInt32)len;
while (len != 0)
{
len--;
@ -850,7 +850,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
}
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState)
{
p->remainLen = kMatchSpecLenStart + 1;
p->tempBufSize = 0;
@ -979,10 +979,10 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
p->tempBufSize = rem;
if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
{
int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, (SizeT)rem);
if (dummyRes == DUMMY_ERROR)
{
(*srcLen) += lookAhead;
(*srcLen) += (SizeT)lookAhead;
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
}
@ -1005,9 +1005,9 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
return SZ_ERROR_FAIL; /* some internal error */
lookAhead -= rem;
}
(*srcLen) += lookAhead;
(*srcLen) += (SizeT)lookAhead;
src += lookAhead;
inSize -= lookAhead;
inSize -= (SizeT)lookAhead;
p->tempBufSize = 0;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/* Ppmd7.c -- PPMdH codec
2017-04-03 : Igor Pavlov : Public domain
2018-07-04 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "Precomp.h"
@ -95,7 +95,7 @@ void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc)
p->Base = 0;
}
Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc)
BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc)
{
if (!p->Base || p->Size != size)
{
@ -342,7 +342,7 @@ void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)
p->DummySee.Count = 64; /* unused */
}
static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)
static CTX_PTR CreateSuccessors(CPpmd7 *p, BoolInt skip)
{
CPpmd_State upState;
CTX_PTR c = p->MinContext;

View file

@ -1,5 +1,5 @@
/* Ppmd7.h -- PPMdH compression codec
2017-04-03 : Igor Pavlov : Public domain
2018-07-04 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
/* This code supports virtual RangeDecoder and includes the implementation
@ -60,7 +60,7 @@ typedef struct
} CPpmd7;
void Ppmd7_Construct(CPpmd7 *p);
Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc);
BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc);
void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc);
void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder);
#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
@ -115,7 +115,7 @@ typedef struct
} CPpmd7z_RangeDec;
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p);
Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p);
BoolInt Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p);
#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
int Ppmd7_DecodeSymbol(CPpmd7 *p, const IPpmd7_RangeDec *rc);

View file

@ -1,5 +1,5 @@
/* Ppmd7Dec.c -- PPMdH Decoder
2017-04-03 : Igor Pavlov : Public domain
2018-07-04 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "Precomp.h"
@ -8,7 +8,7 @@ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#define kTopValue (1 << 24)
Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
BoolInt Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
{
unsigned i;
p->Code = 0;

View file

@ -1,6 +1,109 @@
HISTORY of the LZMA SDK
-----------------------
18.06 2018-12-30
-------------------------
- The speed for LZMA/LZMA2 compressing was increased by 3-10%,
and there are minor changes in compression ratio.
- Some bugs were fixed.
- The bug in 7-Zip 18.02-18.05 was fixed:
There was memory leak in multithreading xz decoder - XzDecMt_Decode(),
if xz stream contains only one block.
- The changes for MSVS compiler makefiles:
- the makefiles now use "PLATFORM" macroname with values (x64, x86, arm64)
instead of "CPU" macroname with values (AMD64, ARM64).
- the makefiles by default now use static version of the run-time library.
18.05 2018-04-30
-------------------------
- The speed for LZMA/LZMA2 compressing was increased
by 8% for fastest/fast compression levels and
by 3% for normal/maximum compression levels.
- Previous versions of 7-Zip could work incorrectly in "Large memory pages" mode in
Windows 10 because of some BUG with "Large Pages" in Windows 10.
Now 7-Zip doesn't use "Large Pages" on Windows 10 up to revision 1709 (16299).
- The BUG was fixed in Lzma2Enc.c
Lzma2Enc_Encode2() function worked incorretly,
if (inStream == NULL) and the number of block threads is more than 1.
18.03 beta 2018-03-04
-------------------------
- Asm\x86\LzmaDecOpt.asm: new optimized LZMA decoder written in asm
for x64 with about 30% higher speed than main version of LZMA decoder written in C.
- The speed for single-thread LZMA/LZMA2 decoder written in C was increased by 3%.
- 7-Zip now can use multi-threading for 7z/LZMA2 decoding,
if there are multiple independent data chunks in LZMA2 stream.
- 7-Zip now can use multi-threading for xz decoding,
if there are multiple blocks in xz stream.
18.01 2019-01-28
-------------------------
- The BUG in 17.01 - 18.00 beta was fixed:
XzDec.c : random block unpacking and XzUnpacker_IsBlockFinished()
didn't work correctly for xz archives without checksum (CRC).
18.00 beta 2019-01-10
-------------------------
- The BUG in xz encoder was fixed:
There was memory leak of 16 KB for each file compressed with
xz compression method, if additional filter was used.
17.01 beta 2017-08-28
-------------------------
- Minor speed optimization for LZMA2 (xz and 7z) multi-threading compression.
7-Zip now uses additional memory buffers for multi-block LZMA2 compression.
CPU utilization was slightly improved.
- 7-zip now creates multi-block xz archives by default. Block size can be
specified with -ms[Size]{m|g} switch.
- xz decoder now can unpack random block from multi-block xz archives.
- 7-Zip command line: @listfile now doesn't work after -- switch.
Use -i@listfile before -- switch instead.
- The BUGs were fixed:
7-Zip 17.00 beta crashed for commands that write anti-item to 7z archive.
17.00 beta 2017-04-29
-------------------------
- NewHandler.h / NewHandler.cpp:
now it redefines operator new() only for old MSVC compilers (_MSC_VER < 1900).
- C/7zTypes.h : the names of variables in interface structures were changed (vt).
- Some bugs were fixed. 7-Zip could crash in some cases.
- Some internal changes in code.
16.04 2016-10-04
-------------------------
- The bug was fixed in DllSecur.c.
16.03 2016-09-28
-------------------------
- SFX modules now use some protection against DLL preloading attack.
- Some bugs in 7z code were fixed.
16.02 2016-05-21
-------------------------
- The BUG in 16.00 - 16.01 was fixed:
Split Handler (SplitHandler.cpp) returned incorrect
total size value (kpidSize) for split archives.
16.01 2016-05-19
-------------------------
- Some internal changes to reduce the number of compiler warnings.
16.00 2016-05-10
-------------------------
- Some bugs were fixed.
15.12 2015-11-19
-------------------------
- The BUG in C version of 7z decoder was fixed:

View file

@ -1,4 +1,4 @@
LZMA SDK 15.13
LZMA SDK 18.06
--------------
LZMA SDK provides the documentation, samples, header files,

View file

@ -13,7 +13,6 @@ include( CheckIncludeFile )
include( CheckIncludeFiles )
include( CheckLibraryExists )
include( FindPkgConfig )
include( TargetArch )
if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
option( NO_STRIP "Do not strip Release or MinSizeRel builds" )
@ -33,12 +32,13 @@ if( APPLE )
option( OSX_COCOA_BACKEND "Use native Cocoa backend instead of SDL" ON )
endif()
target_architecture(ZDOOM_TARGET_ARCH)
if( ${ZDOOM_TARGET_ARCH} MATCHES "x86_64" )
set( X64 64 )
endif()
if( X64 OR ${ZDOOM_TARGET_ARCH} MATCHES "i386" )
add_definitions( -DARCH_IA32 )
endif()
if( NOT ZDOOM_LIBS )
set( ZDOOM_LIBS "" )
@ -460,8 +460,14 @@ add_custom_target( revision_check ALL
# Libraries ZDoom needs
message( STATUS "Fluid synth libs: ${FLUIDSYNTH_LIBRARIES}" )
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${GME_LIBRARIES}" "${ASMJIT_LIBRARIES}" "${CMAKE_DL_LIBS}" )
include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GME_INCLUDE_DIR}" "${ASMJIT_INCLUDE_DIR}" )
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${GME_LIBRARIES}" "${CMAKE_DL_LIBS}" )
include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GME_INCLUDE_DIR}" )
if( ${HAVE_VM_JIT} )
add_definitions( -DHAVE_VM_JIT )
include_directories( "${ASMJIT_INCLUDE_DIR}" )
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ASMJIT_LIBRARIES}")
endif()
if( SNDFILE_FOUND )
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${SNDFILE_LIBRARIES}" )
@ -649,6 +655,7 @@ file( GLOB HEADER_FILES
g_statusbar/*.h
g_inventory/*.h
intermission/*.h
maploader/*.h
menu/*.h
sound/adlmidi/*.h*
sound/opnmidi/*.h*
@ -799,6 +806,17 @@ set( NOT_COMPILED_SOURCE_FILES
zcc-parse.h
)
set( VM_JIT_SOURCES
scripting/vm/jit.cpp
scripting/vm/jit_runtime.cpp
scripting/vm/jit_call.cpp
scripting/vm/jit_flow.cpp
scripting/vm/jit_load.cpp
scripting/vm/jit_math.cpp
scripting/vm/jit_move.cpp
scripting/vm/jit_store.cpp
)
# This is disabled for now because I cannot find a way to give the .pch file a different name.
# Visual C++ 2015 seems hell-bent on only allowing one .pch file with the same name as the executable.
#enable_precompiled_headers( g_pch2.h FASTMATH_PCH_SOURCES )
@ -890,7 +908,6 @@ set (PCH_SOURCES
c_functions.cpp
cmdlib.cpp
colormatcher.cpp
compatibility.cpp
configfile.cpp
ct_chat.cpp
cycler.cpp
@ -908,7 +925,6 @@ set (PCH_SOURCES
doomstat.cpp
dsectoreffect.cpp
dthinker.cpp
edata.cpp
f_wipe.cpp
files.cpp
files_decompress.cpp
@ -955,7 +971,6 @@ set (PCH_SOURCES
p_effect.cpp
p_enemy.cpp
p_floor.cpp
p_glnodes.cpp
p_interaction.cpp
p_lights.cpp
p_linkedsectors.cpp
@ -974,7 +989,6 @@ set (PCH_SOURCES
p_sectors.cpp
p_setup.cpp
p_sight.cpp
p_slopes.cpp
p_spec.cpp
p_states.cpp
p_switch.cpp
@ -984,7 +998,6 @@ set (PCH_SOURCES
p_things.cpp
p_tick.cpp
p_trace.cpp
p_udmf.cpp
p_usdf.cpp
p_user.cpp
p_xlat.cpp
@ -1077,7 +1090,14 @@ set (PCH_SOURCES
hwrenderer/utility/hw_lighting.cpp
hwrenderer/utility/hw_shaderpatcher.cpp
hwrenderer/utility/hw_vrmodes.cpp
maploader/edata.cpp
maploader/maploader.cpp
maploader/slopes.cpp
maploader/glnodes.cpp
maploader/udmf.cpp
maploader/polyobjects.cpp
maploader/renderinfo.cpp
maploader/compatibility.cpp
menu/joystickmenu.cpp
menu/loadsavemenu.cpp
menu/menu.cpp
@ -1144,7 +1164,6 @@ set (PCH_SOURCES
r_data/sprites.cpp
r_data/portalgroups.cpp
r_data/voxels.cpp
r_data/renderinfo.cpp
r_data/renderstyle.cpp
r_data/r_canvastexture.cpp
r_data/r_interpolate.cpp
@ -1174,14 +1193,6 @@ set (PCH_SOURCES
scripting/decorate/thingdef_states.cpp
scripting/vm/vmexec.cpp
scripting/vm/vmframe.cpp
scripting/vm/jit.cpp
scripting/vm/jit_runtime.cpp
scripting/vm/jit_call.cpp
scripting/vm/jit_flow.cpp
scripting/vm/jit_load.cpp
scripting/vm/jit_math.cpp
scripting/vm/jit_move.cpp
scripting/vm/jit_store.cpp
scripting/zscript/ast.cpp
scripting/zscript/zcc_compile.cpp
scripting/zscript/zcc_parser.cpp
@ -1256,6 +1267,12 @@ set (PCH_SOURCES
events.cpp
)
if( ${HAVE_VM_JIT} )
set( PCH_SOURCES ${PCH_SOURCES} ${VM_JIT_SOURCES} )
else()
set( NOT_COMPILED_SOURCE_FILES ${NOT_COMPILED_SOURCE_FILES} ${VM_JIT_SOURCES} )
endif()
enable_precompiled_headers( g_pch.h PCH_SOURCES )
add_executable( zdoom WIN32 MACOSX_BUNDLE
@ -1263,7 +1280,6 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
${NOT_COMPILED_SOURCE_FILES}
__autostart.cpp
${SYSTEM_SOURCES}
${X86_SOURCES}
${FASTMATH_SOURCES}
${PCH_SOURCES}
x86.cpp
@ -1301,6 +1317,13 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS")
set( ZDOOM_LIBS ${ZDOOM_LIBS} nsl socket)
endif()
if( UNIX )
find_package( Backtrace )
if(Backtrace_FOUND)
set( ZDOOM_LIBS ${ZDOOM_LIBS} ${Backtrace_LIBRARIES} )
endif()
endif()
target_link_libraries( zdoom ${ZDOOM_LIBS} gdtoa dumb lzma )
include_directories( .
@ -1422,7 +1445,7 @@ source_group("External\\RapidJSON" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_D
source_group("External\\SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+")
source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+")
source_group("Intermission" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/intermission/.+")
source_group("Inventory" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_inventory/.+")
source_group("Map Loader" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/maploader/.+")
source_group("Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/menu/.+")
source_group("Hardware Renderer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/.+")
source_group("Hardware Renderer\\Data" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/hwrenderer/data/.+")

View file

@ -742,11 +742,6 @@ public:
bool CallOkayToSwitchTarget(AActor *other);
bool OkayToSwitchTarget (AActor *other);
// Note: Although some of the inventory functions are virtual, this
// is not exposed to scripts, as the only class overriding them is
// APlayerPawn for some specific handling for players. None of this
// should ever be overridden by custom classes.
// Uses an item and removes it from the inventory.
bool UseInventory (AActor *item);
@ -821,7 +816,9 @@ public:
void Crash();
// Return starting health adjusted by skill level
double AttackOffset(double offset = 0);
int SpawnHealth() const;
virtual int GetMaxHealth(bool withupgrades = false) const;
int GetGibHealth() const;
double GetCameraHeight() const;
@ -1106,7 +1103,7 @@ public:
int32_t threshold; // if > 0, the target will be chased
int32_t DefThreshold; // [MC] Default threshold which the actor will reset its threshold to after switching targets
// no matter what (even if shot)
player_t *player; // only valid if type of APlayerPawn
player_t *player; // only valid if type of PlayerPawn
TObjPtr<AActor*> LastLookActor; // Actor last looked for (if TIDtoHate != 0)
DVector3 SpawnPoint; // For nightmare respawn
uint16_t SpawnAngle;
@ -1235,7 +1232,7 @@ public:
DVector3 Prev;
DRotator PrevAngles;
int PrevPortalGroup;
TArray<TObjPtr<AActor*> > AttachedLights;
TArray<FDynamicLight *> AttachedLights;
// When was this actor spawned?
int SpawnTime;
@ -1489,13 +1486,11 @@ public:
int ApplyDamageFactor(FName damagetype, int damage) const;
int GetModifiedDamage(FName damagetype, int damage, bool passive);
void DeleteAttachedLights();
static void DeleteAllAttachedLights();
static void RecreateAllAttachedLights();
bool hasmodel;
size_t PropagateMark();
};
class FActorIterator

View file

@ -3,6 +3,7 @@
#include "actor.h"
#include "r_defs.h"
#include "g_levellocals.h"
#include "d_player.h"
// These depend on both actor.h and r_defs.h so they cannot be in either file without creating a circular dependency.
inline DVector3 AActor::PosRelative(int portalgroup) const
@ -79,3 +80,16 @@ inline double AActor::GetGravity() const
if (flags & MF_NOGRAVITY) return 0;
return level.gravity * Sector->gravity * Gravity * 0.00125;
}
inline double AActor::AttackOffset(double offset)
{
if (player != NULL)
{
return (FloatVar(NAME_AttackZOffset) + offset) * player->crouchfactor;
}
else
{
return 8 + offset;
}
}

View file

@ -150,7 +150,7 @@ void VerifyTargetChain(AActor *self, bool preciseMissileCheck)
{
// if any of the actors from self to (inclusive) origin match the next actor,
// self has reached/created a loop
self->target = NULL;
self->target = nullptr;
return;
}
if (compare == origin) break; // when "compare" = origin, we know that the next actor is, and should be "next"
@ -176,7 +176,7 @@ void VerifyMasterChain(AActor *self)
{
if (compare == next)
{
self->master = NULL;
self->master = nullptr;
return;
}
if (compare == origin) break;
@ -215,4 +215,4 @@ void ASSIGN_AAPTR(AActor *toActor, int toSlot, AActor *ptr, int flags)
toActor->tracer = ptr;
break;
}
}
}

View file

@ -83,6 +83,7 @@ CVAR (Bool, am_customcolors, true, CVAR_ARCHIVE);
CVAR (Int, am_map_secrets, 1, CVAR_ARCHIVE);
CVAR (Int, am_drawmapback, 1, CVAR_ARCHIVE);
CVAR (Bool, am_showkeys, true, CVAR_ARCHIVE);
CVAR (Bool, am_showkeys_always, false, CVAR_ARCHIVE);
CVAR (Int, am_showtriggerlines, 0, CVAR_ARCHIVE);
CVAR (Int, am_showthingsprites, 0, CVAR_ARCHIVE);
@ -2333,10 +2334,9 @@ void AM_showSS()
AM_drawSeg(sub->firstline + i, yellow);
}
for (int i = 0; i <po_NumPolyobjs; i++)
for (auto &poly : level.Polyobjects)
{
FPolyObj *po = &polyobjs[i];
FPolyNode *pnode = po->subsectorlinks;
FPolyNode *pnode = poly.subsectorlinks;
while (pnode != NULL)
{
@ -3057,7 +3057,7 @@ void AM_drawThings ()
// That is the case for all default keys, however.
if (t->IsKindOf(NAME_Key))
{
if (G_SkillProperty(SKILLP_EasyKey))
if (G_SkillProperty(SKILLP_EasyKey) || am_showkeys_always)
{
// Already drawn by AM_drawKeys(), so don't draw again
color.Index = -1;
@ -3284,7 +3284,7 @@ void AM_Drawer (int bottom)
AM_drawWalls(allmap);
AM_drawPlayers();
if (G_SkillProperty(SKILLP_EasyKey))
if (G_SkillProperty(SKILLP_EasyKey) || am_showkeys_always)
AM_drawKeys();
if ((am_cheat >= 2 && am_cheat != 4) || allthings)
AM_drawThings();

View file

@ -71,14 +71,14 @@ DBot::DBot ()
void DBot::Clear ()
{
player = NULL;
player = nullptr;
Angle = 0.;
dest = NULL;
prev = NULL;
enemy = NULL;
missile = NULL;
mate = NULL;
last_mate = NULL;
dest = nullptr;
prev = nullptr;
enemy = nullptr;
missile = nullptr;
mate = nullptr;
last_mate = nullptr;
memset(&skill, 0, sizeof(skill));
t_active = 0;
t_respawn = 0;
@ -138,7 +138,7 @@ void DBot::Tick ()
{
Super::Tick ();
if (player->mo == NULL || bglobal.freeze)
if (player->mo == nullptr || bglobal.freeze)
{
return;
}
@ -176,7 +176,7 @@ CCMD (addbot)
if (argv.argc() > 1)
bglobal.SpawnBot (argv[1]);
else
bglobal.SpawnBot (NULL);
bglobal.SpawnBot (nullptr);
}
void FCajunMaster::ClearPlayer (int i, bool keepTeam)
@ -184,7 +184,7 @@ void FCajunMaster::ClearPlayer (int i, bool keepTeam)
if (players[i].mo)
{
players[i].mo->Destroy ();
players[i].mo = NULL;
players[i].mo = nullptr;
}
botinfo_t *bot = botinfo;
while (bot && stricmp (players[i].userinfo.GetName(), bot->name))
@ -194,10 +194,10 @@ void FCajunMaster::ClearPlayer (int i, bool keepTeam)
bot->inuse = BOTINUSE_No;
bot->lastteam = keepTeam ? players[i].userinfo.GetTeam() : TEAM_NONE;
}
if (players[i].Bot != NULL)
if (players[i].Bot != nullptr)
{
players[i].Bot->Destroy ();
players[i].Bot = NULL;
players[i].Bot = nullptr;
}
players[i].~player_t();
::new(&players[i]) player_t;
@ -261,7 +261,7 @@ void InitBotStuff()
while (sc.GetString())
{
PClassActor *wcls = PClass::FindActor(sc.String);
if (wcls != NULL && wcls->IsDescendantOf(NAME_Weapon))
if (wcls != nullptr && wcls->IsDescendantOf(NAME_Weapon))
{
BotInfoData bi = {};
sc.MustGetStringName(",");
@ -306,7 +306,7 @@ void InitBotStuff()
for(unsigned i=0;i<countof(warnbotmissiles);i++)
{
AActor *a = GetDefaultByName (warnbotmissiles[i]);
if (a != NULL)
if (a != nullptr)
{
a->flags3|=MF3_WARNBOT;
}

View file

@ -351,7 +351,7 @@ AActor *DBot::Choose_Mate ()
if (mate)
{
if (mate->health <= 0)
mate = NULL;
mate = nullptr;
else
last_mate = mate;
}
@ -361,7 +361,7 @@ AActor *DBot::Choose_Mate ()
//Check old_mates status.
if (last_mate)
if (last_mate->health <= 0)
last_mate = NULL;
last_mate = nullptr;
target = NULL;
closest_dist = FLT_MAX;

View file

@ -92,6 +92,7 @@ Everything that is changed is marked (maybe commented) with "Added by MC"
#include "d_player.h"
#include "events.h"
#include "vm.h"
#include "g_levellocals.h"
static FRandom pr_botspawn ("BotSpawn");
@ -173,12 +174,12 @@ void FCajunMaster::Main ()
void FCajunMaster::Init ()
{
botnum = 0;
firstthing = NULL;
firstthing = nullptr;
spawn_tries = 0;
freeze = false;
observer = false;
body1 = NULL;
body2 = NULL;
body1 = nullptr;
body2 = nullptr;
if (ctf && teamplay == false)
teamplay = true; //Need teamplay for ctf. (which is not done yet)
@ -447,7 +448,7 @@ void FCajunMaster::RemoveAllBots (bool fromlist)
// [ZZ] run event hook
E_PlayerDisconnected(i);
//
FBehavior::StaticStartTypedScripts (SCRIPT_Disconnect, players[i].mo, true, i, true);
level.Behaviors.StartTypedScripts (SCRIPT_Disconnect, players[i].mo, true, i, true);
ClearPlayer (i, !fromlist);
}
}

View file

@ -63,7 +63,7 @@ void DBot::Think ()
memset (cmd, 0, sizeof(*cmd));
if (enemy && enemy->health <= 0)
enemy = NULL;
enemy = nullptr;
if (player->mo->health > 0) //Still alive
{
@ -121,7 +121,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
(!missile->Vel.X || !missile->Vel.Y || !Check_LOS(missile, SHOOTFOV*3/2)))
{
sleft = !sleft;
missile = NULL; //Probably ended its travel.
missile = nullptr; //Probably ended its travel.
}
#if 0 // this has always been broken and without any reference it cannot be fixed.
@ -183,7 +183,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
}
}
dest = NULL; //To let bot turn right
dest = nullptr; //To let bot turn right
if (GetBotInfo(player->ReadyWeapon).MoveCombatDist == 0)
player->mo->flags &= ~MF_DROPOFF; //Don't jump off any ledges when fighting.
@ -237,7 +237,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
{
if (mate == dest && pr_botmove.Random() < 32)
{ // [RH] If the mate is the dest, pick a new dest sometimes
dest = NULL;
dest = nullptr;
}
goto roam;
}
@ -264,7 +264,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
if (dest && !(dest->flags&MF_SPECIAL) && dest->health < 0)
{ //Roaming after something dead.
dest = NULL;
dest = nullptr;
}
if (dest == NULL)
@ -333,7 +333,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
if (!t_roam && dest)
{
prev = dest;
dest = NULL;
dest = nullptr;
}
if (t_fight<(AFTERTICS/2))
@ -342,7 +342,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
old = player->mo->Pos();
}
int P_GetRealMaxHealth(APlayerPawn *actor, int max);
int P_GetRealMaxHealth(AActor *actor, int max);
//BOT_WhatToGet
//
@ -438,5 +438,5 @@ void DBot::Set_enemy ()
}
//Verify that that enemy is really something alive that bot can kill.
if (enemy && ((enemy->health < 0 || !(enemy->flags&MF_SHOOTABLE)) || player->mo->IsFriend(enemy)))
enemy = NULL;
enemy = nullptr;
}

View file

@ -55,100 +55,100 @@ const char *KeyNames[NUM_KEYS] =
// DirectInput codes and assume a qwerty keyboard layout.
// See <dinput.h> for the DIK_* codes
NULL, "escape", "1", "2", "3", "4", "5", "6", //00
"7", "8", "9", "0", "-", "=", "backspace","tab", //08
"q", "w", "e", "r", "t", "y", "u", "i", //10
"o", "p", "[", "]", "enter", "ctrl", "a", "s", //18
"d", "f", "g", "h", "j", "k", "l", ";", //20
"'", "`", "shift", "\\", "z", "x", "c", "v", //28
"b", "n", "m", ",", ".", "/", "rshift", "kp*", //30
"alt", "space", "capslock", "f1", "f2", "f3", "f4", "f5", //38
"f6", "f7", "f8", "f9", "f10", "numlock", "scroll", "kp7", //40
"kp8", "kp9", "kp-", "kp4", "kp5", "kp6", "kp+", "kp1", //48
"kp2", "kp3", "kp0", "kp.", NULL, NULL, "oem102", "f11", //50
"f12", NULL, NULL, NULL, NULL, NULL, NULL, NULL, //58
NULL, NULL, NULL, NULL, "f13", "f14", "f15", "f16", //60
NULL, "Escape", "1", "2", "3", "4", "5", "6", //00
"7", "8", "9", "0", "-", "=", "Backspace","Tab", //08
"Q", "W", "E", "R", "T", "Y", "U", "I", //10
"O", "P", "[", "]", "Enter", "Ctrl", "A", "S", //18
"D", "F", "G", "H", "J", "K", "L", ";", //20
"'", "`", "Shift", "\\", "Z", "X", "C", "V", //28
"B", "N", "M", ",", ".", "/", "RShift", "KP*", //30
"Alt", "Space", "CapsLock", "F1", "F2", "F3", "F4", "F5", //38
"F6", "F7", "F8", "F9", "F10", "NumLock", "Scroll", "KP7", //40
"KP8", "KP9", "KP-", "KP4", "KP5", "KP6", "KP+", "KP1", //48
"KP2", "KP3", "KP0", "KP.", NULL, NULL, "OEM102", "F11", //50
"F12", NULL, NULL, NULL, NULL, NULL, NULL, NULL, //58
NULL, NULL, NULL, NULL, "F13", "F14", "F15", "F16", //60
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //68
"kana", NULL, NULL, "abnt_c1", NULL, NULL, NULL, NULL, //70
NULL, "convert", NULL, "noconvert",NULL, "yen", "abnt_c2", NULL, //78
"Kana", NULL, NULL, "Abnt_C1", NULL, NULL, NULL, NULL, //70
NULL, "Convert", NULL, "NoConvert",NULL, "Yen", "Abnt_C2", NULL, //78
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //80
NULL, NULL, NULL, NULL, NULL, "kp=", NULL, NULL, //88
"circumflex","@", ":", "_", "kanji", "stop", "ax", "unlabeled",//90
NULL, "prevtrack",NULL, NULL, "kp-enter", "rctrl", NULL, NULL, //98
"mute", "calculator","play", NULL, "stop", NULL, NULL, NULL, //A0
NULL, NULL, NULL, NULL, NULL, NULL, "voldown", NULL, //A8
"volup", NULL, "webhome", "kp,", NULL, "kp/", NULL, "sysrq", //B0
"ralt", NULL, NULL, NULL, NULL, NULL, NULL, NULL, //B8
NULL, NULL, NULL, NULL, NULL, "pause", NULL, "home", //C0
"uparrow", "pgup", NULL, "leftarrow",NULL, "rightarrow",NULL, "end", //C8
"downarrow","pgdn", "ins", "del", NULL, NULL, NULL, NULL, //D0
NULL, NULL, NULL, NULL, NULL, "KP=", NULL, NULL, //88
"Circumflex","@", ":", "_", "Kanji", "Stop", "Ax", "Unlabeled",//90
NULL, "PrevTrack",NULL, NULL, "KP-Enter", "RCtrl", NULL, NULL, //98
"Mute", "Calculator","Play", NULL, "Stop", NULL, NULL, NULL, //A0
NULL, NULL, NULL, NULL, NULL, NULL, "VolDown", NULL, //A8
"VolUp", NULL, "WebHome", "KP,", NULL, "KP/", NULL, "SysRq", //B0
"RAlt", NULL, NULL, NULL, NULL, NULL, NULL, NULL, //B8
NULL, NULL, NULL, NULL, NULL, "Pause", NULL, "Home", //C0
"UpArrow", "PgUp", NULL, "LeftArrow",NULL, "RightArrow",NULL, "End", //C8
"DownArrow","PgDn", "Ins", "Del", NULL, NULL, NULL, NULL, //D0
#ifdef __APPLE__
NULL, NULL, NULL, "command", NULL, "apps", "power", "sleep", //D8
NULL, NULL, NULL, "Command", NULL, "Apps", "Power", "Sleep", //D8
#else // !__APPLE__
NULL, NULL, NULL, "lwin", "rwin", "apps", "power", "sleep", //D8
NULL, NULL, NULL, "LWin", "RWin", "Apps", "Power", "Sleep", //D8
#endif // __APPLE__
NULL, NULL, NULL, "wake", NULL, "search", "favorites","refresh", //E0
"webstop", "webforward","webback", "mycomputer","mail", "mediaselect",NULL, NULL, //E8
NULL, NULL, NULL, "Wake", NULL, "Search", "Favorites","Refresh", //E0
"WebStop", "WebForward","WebBack", "MyComputer","Mail", "MediaSelect",NULL, NULL, //E8
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //F0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //F8
// non-keyboard buttons that can be bound
"mouse1", "mouse2", "mouse3", "mouse4", // 8 mouse buttons
"mouse5", "mouse6", "mouse7", "mouse8",
"Mouse1", "Mouse2", "Mouse3", "Mouse4", // 8 mouse buttons
"Mouse5", "Mouse6", "Mouse7", "Mouse8",
"joy1", "joy2", "joy3", "joy4", // 128 joystick buttons!
"joy5", "joy6", "joy7", "joy8",
"joy9", "joy10", "joy11", "joy12",
"joy13", "joy14", "joy15", "joy16",
"joy17", "joy18", "joy19", "joy20",
"joy21", "joy22", "joy23", "joy24",
"joy25", "joy26", "joy27", "joy28",
"joy29", "joy30", "joy31", "joy32",
"joy33", "joy34", "joy35", "joy36",
"joy37", "joy38", "joy39", "joy40",
"joy41", "joy42", "joy43", "joy44",
"joy45", "joy46", "joy47", "joy48",
"joy49", "joy50", "joy51", "joy52",
"joy53", "joy54", "joy55", "joy56",
"joy57", "joy58", "joy59", "joy60",
"joy61", "joy62", "joy63", "joy64",
"joy65", "joy66", "joy67", "joy68",
"joy69", "joy70", "joy71", "joy72",
"joy73", "joy74", "joy75", "joy76",
"joy77", "joy78", "joy79", "joy80",
"joy81", "joy82", "joy83", "joy84",
"joy85", "joy86", "joy87", "joy88",
"joy89", "joy90", "joy91", "joy92",
"joy93", "joy94", "joy95", "joy96",
"joy97", "joy98", "joy99", "joy100",
"joy101", "joy102", "joy103", "joy104",
"joy105", "joy106", "joy107", "joy108",
"joy109", "joy110", "joy111", "joy112",
"joy113", "joy114", "joy115", "joy116",
"joy117", "joy118", "joy119", "joy120",
"joy121", "joy122", "joy123", "joy124",
"joy125", "joy126", "joy127", "joy128",
"Joy1", "Joy2", "Joy3", "Joy4", // 128 joystick buttons!
"Joy5", "Joy6", "Joy7", "Joy8",
"Joy9", "Joy10", "Joy11", "Joy12",
"Joy13", "Joy14", "Joy15", "Joy16",
"Joy17", "Joy18", "Joy19", "Joy20",
"Joy21", "Joy22", "Joy23", "Joy24",
"Joy25", "Joy26", "Joy27", "Joy28",
"Joy29", "Joy30", "Joy31", "Joy32",
"Joy33", "Joy34", "Joy35", "Joy36",
"Joy37", "Joy38", "Joy39", "Joy40",
"Joy41", "Joy42", "Joy43", "Joy44",
"Joy45", "Joy46", "Joy47", "Joy48",
"Joy49", "Joy50", "Joy51", "Joy52",
"Joy53", "Joy54", "Joy55", "Joy56",
"Joy57", "Joy58", "Joy59", "Joy60",
"Joy61", "Joy62", "Joy63", "Joy64",
"Joy65", "Joy66", "Joy67", "Joy68",
"Joy69", "Joy70", "Joy71", "Joy72",
"Joy73", "Joy74", "Joy75", "Joy76",
"Joy77", "Joy78", "Joy79", "Joy80",
"Joy81", "Joy82", "Joy83", "Joy84",
"Joy85", "Joy86", "Joy87", "Joy88",
"Joy89", "Joy90", "Joy91", "Joy92",
"Joy93", "Joy94", "Joy95", "Joy96",
"Joy97", "Joy98", "Joy99", "Joy100",
"Joy101", "Joy102", "Joy103", "Joy104",
"Joy105", "Joy106", "Joy107", "Joy108",
"Joy109", "Joy110", "Joy111", "Joy112",
"Joy113", "Joy114", "Joy115", "Joy116",
"Joy117", "Joy118", "Joy119", "Joy120",
"Joy121", "Joy122", "Joy123", "Joy124",
"Joy125", "Joy126", "Joy127", "Joy128",
"pov1up", "pov1right","pov1down", "pov1left", // First POV hat
"pov2up", "pov2right","pov2down", "pov2left", // Second POV hat
"pov3up", "pov3right","pov3down", "pov3left", // Third POV hat
"pov4up", "pov4right","pov4down", "pov4left", // Fourth POV hat
"POV1Up", "POV1Right","POV1Down", "POV1Left", // First POV hat
"POV2Up", "POV2Right","POV2Down", "POV2Left", // Second POV hat
"POV3Up", "POV3Right","POV3Down", "POV3Left", // Third POV hat
"POV4Up", "POV4Right","POV4Down", "POV4Left", // Fourth POV hat
"mwheelup", "mwheeldown", // the mouse wheel
"mwheelright", "mwheelleft",
"MWheelUp", "MWheelDown", // the mouse wheel
"MWheelRight", "MWheelLeft",
"axis1plus","axis1minus","axis2plus","axis2minus", // joystick axes as buttons
"axis3plus","axis3minus","axis4plus","axis4minus",
"axis5plus","axis5minus","axis6plus","axis6minus",
"axis7plus","axis7minus","axis8plus","axis8minus",
"Axis1Plus","Axis1Minus","Axis2Plus","Axis2Minus", // joystick axes as buttons
"Axis3Plus","Axis3Minus","Axis4Plus","Axis4Minus",
"Axis5Plus","Axis5Minus","Axis6Plus","Axis6Minus",
"Axis7Plus","Axis7Minus","Axis8Plus","Axis8Minus",
"lstickright","lstickleft","lstickdown","lstickup", // Gamepad axis-based buttons
"rstickright","rstickleft","rstickdown","rstickup",
"LStickRight","LStickLeft","LStickDown","LStickUp", // Gamepad axis-based buttons
"RStickRight","RStickLeft","RStickDown","RStickUp",
"dpadup","dpaddown","dpadleft","dpadright", // Gamepad buttons
"pad_start","pad_back","lthumb","rthumb",
"lshoulder","rshoulder","ltrigger","rtrigger",
"pad_a", "pad_b", "pad_x", "pad_y"
"DPadUp","DPadDown","DPadLeft","DPadRight", // Gamepad buttons
"Pad_Start","Pad_Back","LThumb","RThumb",
"LShoulder","RShoulder","LTrigger","RTrigger",
"Pad_A", "Pad_B", "Pad_X", "Pad_Y"
};
FKeyBindings Bindings;

View file

@ -74,6 +74,7 @@ extern bool insave;
CVAR (Bool, sv_cheats, false, CVAR_SERVERINFO | CVAR_LATCH)
CVAR (Bool, sv_unlimited_pickup, false, CVAR_SERVERINFO)
CVAR (Bool, cl_blockcheats, false, 0)
CCMD (toggleconsole)
{
@ -87,6 +88,11 @@ bool CheckCheatmode (bool printmsg)
if (printmsg) Printf ("sv_cheats must be true to enable this command.\n");
return true;
}
else if (cl_blockcheats)
{
if (printmsg) Printf ("cl_blockcheats is turned on and disabled this command.\n");
return true;
}
else
{
return false;

View file

@ -629,7 +629,7 @@ void C_DeinitConsole ()
while (cmd != NULL)
{
GameAtExit *next = cmd->Next;
AddCommandString (cmd->Command.LockBuffer());
AddCommandString (cmd->Command);
delete cmd;
cmd = next;
}
@ -1559,17 +1559,9 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer)
{
// Work with a copy of command to avoid side effects caused by
// exception raised during execution, like with 'error' CCMD.
// It's problematic to maintain FString's lock symmetry.
static TArray<char> command;
const size_t length = buffer.Text.Len();
command.Resize(unsigned(length + 1));
memcpy(&command[0], buffer.Text.GetChars(), length);
command[length] = '\0';
FString copy = buffer.Text;
buffer.SetString("");
AddCommandString(&command[0]);
AddCommandString(copy);
}
TabbedLast = false;
TabbedList = false;

View file

@ -59,38 +59,122 @@
// TYPES -------------------------------------------------------------------
class DWaitingCommand : public DThinker
class UnsafeExecutionScope
{
DECLARE_CLASS (DWaitingCommand, DThinker)
const bool wasEnabled;
public:
DWaitingCommand (const char *cmd, int tics, bool unsafe);
~DWaitingCommand ();
void Serialize(FSerializer &arc);
void Tick ();
explicit UnsafeExecutionScope(const bool enable = true)
: wasEnabled(UnsafeExecutionContext)
{
UnsafeExecutionContext = enable;
}
private:
DWaitingCommand ();
~UnsafeExecutionScope()
{
UnsafeExecutionContext = wasEnabled;
}
};
char *Command;
class FDelayedCommand
{
public:
virtual ~FDelayedCommand() {}
protected:
virtual bool Tick() = 0;
friend class FDelayedCommandQueue;
};
class FWaitingCommand : public FDelayedCommand
{
public:
FWaitingCommand(const char *cmd, int tics, bool unsafe)
: Command(cmd), TicsLeft(tics+1), IsUnsafe(unsafe)
{}
bool Tick() override
{
if (--TicsLeft == 0)
{
UnsafeExecutionScope scope(IsUnsafe);
AddCommandString(Command);
return true;
}
return false;
}
FString Command;
int TicsLeft;
bool IsUnsafe;
};
class DStoredCommand : public DThinker
class FStoredCommand : public FDelayedCommand
{
DECLARE_CLASS (DStoredCommand, DThinker)
public:
DStoredCommand (FConsoleCommand *com, const char *cmd);
~DStoredCommand ();
void Tick ();
FStoredCommand(FConsoleCommand *com, const char *cmd)
: Command(com), Text(cmd)
{}
bool Tick() override
{
if (Text.IsNotEmpty() && Command != nullptr)
{
FCommandLine args(Text);
Command->Run(args, players[consoleplayer].mo, 0);
}
return true;
}
private:
DStoredCommand ();
FConsoleCommand *Command;
char *Text;
FString Text;
};
class FDelayedCommandQueue
{
TDeletingArray<FDelayedCommand *> delayedCommands;
public:
void Run()
{
for (unsigned i = 0; i < delayedCommands.Size(); i++)
{
if (delayedCommands[i]->Tick())
{
delete delayedCommands[i];
delayedCommands.Delete(i);
i--;
}
}
}
void Clear()
{
delayedCommands.DeleteAndClear();
}
void AddCommand(FDelayedCommand * cmd)
{
delayedCommands.Push(cmd);
}
};
static FDelayedCommandQueue delayedCommandQueue;
void C_RunDelayedCommands()
{
delayedCommandQueue.Run();
}
void C_ClearDelayedCommands()
{
delayedCommandQueue.Clear();
}
struct FActionMap
{
FButtonStatus *Button;
@ -127,22 +211,6 @@ FButtonStatus Button_Mlook, Button_Klook, Button_Use, Button_AltAttack,
bool ParsingKeyConf, UnsafeExecutionContext;
class UnsafeExecutionScope
{
const bool wasEnabled;
public:
explicit UnsafeExecutionScope(const bool enable = true)
: wasEnabled(UnsafeExecutionContext)
{
UnsafeExecutionContext = enable;
}
~UnsafeExecutionScope()
{
UnsafeExecutionContext = wasEnabled;
}
};
// To add new actions, go to the console and type "key <action name>".
// This will give you the key value to use in the first column. Then
@ -205,79 +273,6 @@ static const char *KeyConfCommands[] =
// CODE --------------------------------------------------------------------
IMPLEMENT_CLASS(DWaitingCommand, false, false)
void DWaitingCommand::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc("command", Command)
("ticsleft", TicsLeft)
("unsafe", IsUnsafe);
}
DWaitingCommand::DWaitingCommand ()
{
Command = NULL;
TicsLeft = 1;
IsUnsafe = false;
}
DWaitingCommand::DWaitingCommand (const char *cmd, int tics, bool unsafe)
{
Command = copystring (cmd);
TicsLeft = tics+1;
IsUnsafe = unsafe;
}
DWaitingCommand::~DWaitingCommand ()
{
if (Command != NULL)
{
delete[] Command;
}
}
void DWaitingCommand::Tick ()
{
if (--TicsLeft == 0)
{
UnsafeExecutionScope scope(IsUnsafe);
AddCommandString (Command);
Destroy ();
}
}
IMPLEMENT_CLASS(DStoredCommand, false, false)
DStoredCommand::DStoredCommand ()
{
Text = NULL;
Destroy ();
}
DStoredCommand::DStoredCommand (FConsoleCommand *command, const char *args)
{
Command = command;
Text = copystring (args);
}
DStoredCommand::~DStoredCommand ()
{
if (Text != NULL)
{
delete[] Text;
}
}
void DStoredCommand::Tick ()
{
if (Text != NULL && Command != NULL)
{
FCommandLine args (Text);
Command->Run (args, players[consoleplayer].mo, 0);
}
Destroy ();
}
static int ListActionCommands (const char *pattern)
{
@ -656,7 +651,8 @@ void C_DoCommand (const char *cmd, int keynum)
}
else
{
Create<DStoredCommand> (com, beg);
auto cmd = new FStoredCommand(com, beg);
delayedCommandQueue.AddCommand(cmd);
}
}
}
@ -696,8 +692,12 @@ DEFINE_ACTION_FUNCTION(DOptionMenuItemCommand, DoCommand)
return 0;
}
void AddCommandString (char *cmd, int keynum)
void AddCommandString (const char *text, int keynum)
{
// Operate on a local copy instead of messing around with the data that's being passed in here.
TArray<char> buffer(strlen(text) + 1, true);
memcpy(buffer.Data(), text, buffer.Size());
char *cmd = buffer.Data();
char *brkpt;
int more;
@ -752,7 +752,8 @@ void AddCommandString (char *cmd, int keynum)
// Note that deferred commands lose track of which key
// (if any) they were pressed from.
*brkpt = ';';
Create<DWaitingCommand> (brkpt, tics, UnsafeExecutionContext);
auto cmd = new FWaitingCommand(brkpt, tics, UnsafeExecutionContext);
delayedCommandQueue.AddCommand(cmd);
}
return;
}
@ -1039,12 +1040,12 @@ FConsoleCommand::~FConsoleCommand ()
delete[] m_Name;
}
void FConsoleCommand::Run (FCommandLine &argv, APlayerPawn *who, int key)
void FConsoleCommand::Run (FCommandLine &argv, AActor *who, int key)
{
m_RunFunc (argv, who, key);
}
void FUnsafeConsoleCommand::Run (FCommandLine &args, APlayerPawn *instigator, int key)
void FUnsafeConsoleCommand::Run (FCommandLine &args, AActor *instigator, int key)
{
if (UnsafeExecutionContext)
{
@ -1455,7 +1456,7 @@ bool FConsoleAlias::IsAlias ()
return true;
}
void FConsoleAlias::Run (FCommandLine &args, APlayerPawn *who, int key)
void FConsoleAlias::Run (FCommandLine &args, AActor *who, int key)
{
if (bRunning)
{
@ -1477,8 +1478,7 @@ void FConsoleAlias::Run (FCommandLine &args, APlayerPawn *who, int key)
}
bRunning = true;
AddCommandString (mycommand.LockBuffer(), key);
mycommand.UnlockBuffer();
AddCommandString (mycommand, key);
bRunning = false;
if (m_Command[index].IsEmpty())
{ // The alias is unchanged, so put the command back so it can be used again.
@ -1519,7 +1519,7 @@ void FConsoleAlias::SafeDelete ()
}
}
void FUnsafeConsoleAlias::Run (FCommandLine &args, APlayerPawn *instigator, int key)
void FUnsafeConsoleAlias::Run (FCommandLine &args, AActor *instigator, int key)
{
UnsafeExecutionScope scope;
FConsoleAlias::Run(args, instigator, key);
@ -1554,8 +1554,7 @@ void FExecList::ExecCommands() const
{
for (unsigned i = 0; i < Commands.Size(); ++i)
{
AddCommandString(Commands[i].LockBuffer());
Commands[i].UnlockBuffer();
AddCommandString(Commands[i]);
}
}

View file

@ -37,7 +37,6 @@
#include "doomtype.h"
class FConfigFile;
class APlayerPawn;
// Class that can parse command lines
class FCommandLine
@ -78,7 +77,10 @@ FExecList *C_ParseCmdLineParams(FExecList *exec);
// and semicolon-separated commands. This function may modify the source
// string, but the string will be restored to its original state before
// returning. Therefore, commands passed must not be in read-only memory.
void AddCommandString (char *text, int keynum=0);
void AddCommandString (const char *text, int keynum=0);
void C_RunDelayedCommands();
void C_ClearDelayedCommands();
// Process a single console command. Does not handle wait.
void C_DoCommand (const char *cmd, int keynum=0);
@ -96,7 +98,8 @@ void C_ClearAliases ();
// build a single string out of multiple strings
FString BuildString (int argc, FString *argv);
typedef void (*CCmdRun) (FCommandLine &argv, APlayerPawn *instigator, int key);
class AActor;
typedef void (*CCmdRun) (FCommandLine &argv, AActor *instigator, int key);
class FConsoleCommand
{
@ -106,7 +109,7 @@ public:
virtual bool IsAlias ();
void PrintCommand () { Printf ("%s\n", m_Name); }
virtual void Run (FCommandLine &args, APlayerPawn *instigator, int key);
virtual void Run (FCommandLine &args, AActor *instigator, int key);
static FConsoleCommand* FindByName (const char* name);
FConsoleCommand *m_Next, **m_Prev;
@ -123,9 +126,9 @@ protected:
};
#define CCMD(n) \
void Cmd_##n (FCommandLine &, APlayerPawn *, int key); \
void Cmd_##n (FCommandLine &, AActor *, int key); \
FConsoleCommand Cmd_##n##_Ref (#n, Cmd_##n); \
void Cmd_##n (FCommandLine &argv, APlayerPawn *who, int key)
void Cmd_##n (FCommandLine &argv, AActor *who, int key)
class FUnsafeConsoleCommand : public FConsoleCommand
{
@ -135,13 +138,13 @@ public:
{
}
virtual void Run (FCommandLine &args, APlayerPawn *instigator, int key) override;
virtual void Run (FCommandLine &args, AActor *instigator, int key) override;
};
#define UNSAFE_CCMD(n) \
static void Cmd_##n (FCommandLine &, APlayerPawn *, int key); \
static void Cmd_##n (FCommandLine &, AActor *, int key); \
static FUnsafeConsoleCommand Cmd_##n##_Ref (#n, Cmd_##n); \
void Cmd_##n (FCommandLine &argv, APlayerPawn *who, int key)
void Cmd_##n (FCommandLine &argv, AActor *who, int key)
const int KEY_DBLCLICKED = 0x8000;
@ -150,7 +153,7 @@ class FConsoleAlias : public FConsoleCommand
public:
FConsoleAlias (const char *name, const char *command, bool noSave);
~FConsoleAlias ();
void Run (FCommandLine &args, APlayerPawn *Instigator, int key);
void Run (FCommandLine &args, AActor *instigator, int key);
bool IsAlias ();
void PrintAlias ();
void Archive (FConfigFile *f);
@ -171,7 +174,7 @@ public:
{
}
virtual void Run (FCommandLine &args, APlayerPawn *instigator, int key) override;
virtual void Run (FCommandLine &args, AActor *instigator, int key) override;
};
// Actions

View file

@ -1,42 +0,0 @@
#ifndef COMPATIBILITY_H
#define COMPATIBILITY_H
#include "doomtype.h"
#include "tarray.h"
#include "p_setup.h"
union FMD5Holder
{
uint8_t Bytes[16];
uint32_t DWords[4];
hash_t Hash;
};
struct FCompatValues
{
int CompatFlags[3];
unsigned int ExtCommandIndex;
};
struct FMD5HashTraits
{
hash_t Hash(const FMD5Holder key)
{
return key.Hash;
}
int Compare(const FMD5Holder left, const FMD5Holder right)
{
return left.DWords[0] != right.DWords[0] ||
left.DWords[1] != right.DWords[1] ||
left.DWords[2] != right.DWords[2] ||
left.DWords[3] != right.DWords[3];
}
};
extern TMap<FMD5Holder, FCompatValues, FMD5HashTraits> BCompatMap;
void ParseCompatibility();
FName CheckCompatibility(MapData *map);
void SetCompatibilityParams(FName);
#endif

View file

@ -213,6 +213,7 @@ DEFINE_FIELD_X(DehInfo, DehInfo, ExplosionAlpha)
DEFINE_FIELD_X(DehInfo, DehInfo, NoAutofreeze)
DEFINE_FIELD_X(DehInfo, DehInfo, BFGCells)
DEFINE_FIELD_X(DehInfo, DehInfo, BlueAC)
DEFINE_FIELD_X(DehInfo, DehInfo, MaxHealth)
// Doom identified pickup items by their sprites. ZDoom prefers to use their
// class type to identify them instead. To support the traditional Doom
@ -807,6 +808,7 @@ void SetDehParams(FState *state, int codepointer)
}
fclose(dump);
}
#ifdef HAVE_VM_JIT
if (Args->CheckParm("-dumpjit"))
{
FILE *dump = fopen("dumpjit.txt", "a");
@ -816,6 +818,7 @@ void SetDehParams(FState *state, int codepointer)
}
fclose(dump);
}
#endif // HAVE_VM_JIT
}
}
@ -1988,7 +1991,7 @@ static int PatchMisc (int dummy)
health->IntVar(NAME_Amount) = health->IntVar(NAME_MaxAmount) = deh.MegasphereHealth;
}
APlayerPawn *player = static_cast<APlayerPawn *> (GetDefaultByName ("DoomPlayer"));
AActor *player = GetDefaultByName ("DoomPlayer");
if (player != NULL)
{
player->health = deh.StartHealth;

View file

@ -89,7 +89,6 @@
#include "d_event.h"
#include "d_netinf.h"
#include "m_cheat.h"
#include "compatibility.h"
#include "m_joy.h"
#include "po_man.h"
#include "r_renderer.h"
@ -750,8 +749,7 @@ void D_Display ()
// Check for the presence of dynamic lights at the start of the frame once.
if ((gl_lights && vid_rendermode == 4) || (r_dynlights && vid_rendermode != 4))
{
TThinkerIterator<ADynamicLight> it(STAT_DLIGHT);
level.HasDynamicLights = !!it.Next();
level.HasDynamicLights = !!level.lights;
}
else level.HasDynamicLights = false; // lights are off so effectively we have none.
@ -762,15 +760,15 @@ void D_Display ()
{
AM_Drawer (hud_althud? viewheight : StatusBar->GetTopOfStatusbar());
}
if (!automapactive || viewactive)
{
screen->RefreshViewBorder ();
}
// for timing the statusbar code.
//cycle_t stb;
//stb.Reset();
//stb.Clock();
if (!automapactive || viewactive)
{
StatusBar->RefreshViewBorder ();
}
if (hud_althud && viewheight == SCREENHEIGHT && screenblocks > 10)
{
StatusBar->DrawBottomStuff (HUD_AltHud);
@ -2432,8 +2430,6 @@ void D_DoomMain (void)
StartScreen = new FStartupScreen(0);
}
ParseCompatibility();
CheckCmdLine();
// [RH] Load sound environments
@ -2583,7 +2579,7 @@ void D_DoomMain (void)
// [RH] Run any saved commands from the command line or autoexec.cfg now.
gamestate = GS_FULLCONSOLE;
Net_NewMakeTic ();
DThinker::RunThinkers ();
C_RunDelayedCommands();
gamestate = GS_STARTUP;
if (!restart)
@ -2650,7 +2646,7 @@ void D_DoomMain (void)
G_InitNew(startmap, false);
if (StoredWarp.IsNotEmpty())
{
AddCommandString(StoredWarp.LockBuffer());
AddCommandString(StoredWarp);
StoredWarp = NULL;
}
}
@ -2702,7 +2698,6 @@ void D_DoomMain (void)
DThinker::DestroyThinkersInList(STAT_STATIC);
E_Shutdown(false);
P_FreeLevelData();
P_FreeExtraLevelData();
M_SaveDefaults(NULL); // save config before the restart
@ -2717,7 +2712,6 @@ void D_DoomMain (void)
S_Shutdown(); // free all channels and delete playlist
C_ClearAliases(); // CCMDs won't be reinitialized so these need to be deleted here
DestroyCVarsFlagged(CVAR_MOD); // Delete any cvar left by mods
FS_Close(); // destroy the global FraggleScript.
DeinitMenus();
LightDefaults.DeleteAndClear(); // this can leak heap memory if it isn't cleared.

View file

@ -127,7 +127,7 @@ void G_BuildTiccmd (ticcmd_t *cmd);
void D_DoAdvanceDemo (void);
static void SendSetup (uint32_t playersdetected[MAXNETNODES], uint8_t gotsetup[MAXNETNODES], int len);
static void RunScript(uint8_t **stream, APlayerPawn *pawn, int snum, int argn, int always);
static void RunScript(uint8_t **stream, AActor *pawn, int snum, int argn, int always);
int reboundpacket;
uint8_t reboundstore[MAX_MSGLEN];
@ -2487,10 +2487,10 @@ void Net_DoCommand (int type, uint8_t **stream, int player)
case DEM_RUNNAMEDSCRIPT:
{
char *sname = ReadString(stream);
s = ReadString(stream);
int argn = ReadByte(stream);
RunScript(stream, players[player].mo, -FName(sname), argn & 127, (argn & 128) ? ACS_ALWAYS : 0);
RunScript(stream, players[player].mo, -FName(s), argn & 127, (argn & 128) ? ACS_ALWAYS : 0);
}
break;
@ -2557,9 +2557,9 @@ void Net_DoCommand (int type, uint8_t **stream, int player)
case DEM_KILLCLASSCHEAT:
{
char *classname = ReadString (stream);
s = ReadString (stream);
int killcount = 0;
PClassActor *cls = PClass::FindActor(classname);
PClassActor *cls = PClass::FindActor(s);
if (cls != NULL)
{
@ -2569,20 +2569,20 @@ void Net_DoCommand (int type, uint8_t **stream, int player)
{
killcount += KillAll(cls_rep);
}
Printf ("Killed %d monsters of type %s.\n",killcount, classname);
Printf ("Killed %d monsters of type %s.\n",killcount, s);
}
else
{
Printf ("%s is not an actor class.\n", classname);
Printf ("%s is not an actor class.\n", s);
}
}
break;
case DEM_REMOVE:
{
char *classname = ReadString(stream);
s = ReadString(stream);
int removecount = 0;
PClassActor *cls = PClass::FindActor(classname);
PClassActor *cls = PClass::FindActor(s);
if (cls != NULL && cls->IsDescendantOf(RUNTIME_CLASS(AActor)))
{
removecount = RemoveClass(cls);
@ -2591,11 +2591,11 @@ void Net_DoCommand (int type, uint8_t **stream, int player)
{
removecount += RemoveClass(cls_rep);
}
Printf("Removed %d actors of type %s.\n", removecount, classname);
Printf("Removed %d actors of type %s.\n", removecount, s);
}
else
{
Printf("%s is not an actor class.\n", classname);
Printf("%s is not an actor class.\n", s);
}
}
break;
@ -2688,7 +2688,7 @@ void Net_DoCommand (int type, uint8_t **stream, int player)
}
// Used by DEM_RUNSCRIPT, DEM_RUNSCRIPT2, and DEM_RUNNAMEDSCRIPT
static void RunScript(uint8_t **stream, APlayerPawn *pawn, int snum, int argn, int always)
static void RunScript(uint8_t **stream, AActor *pawn, int snum, int argn, int always)
{
int arg[4] = { 0, 0, 0, 0 };
int i;

View file

@ -138,12 +138,12 @@ int D_GenderToInt (const char *gender)
{
if (gender[0] == 'f')
return GENDER_FEMALE;
else if (gender[0] == 'm')
return GENDER_MALE;
else if (gender[0] == 'n')
return GENDER_NEUTER;
else
else if (gender[0] == 'o')
return GENDER_OBJECT;
else
return GENDER_MALE;
}
int D_PlayerClassToInt (const char *classname)
@ -728,8 +728,8 @@ void D_WriteUserInfoStrings (int pnum, uint8_t **stream, bool compact)
case NAME_Gender:
*stream += sprintf(*((char **)stream), "\\%s",
*static_cast<FIntCVar *>(pair->Value) == GENDER_FEMALE ? "female" :
*static_cast<FIntCVar *>(pair->Value) == GENDER_MALE ? "male" :
*static_cast<FIntCVar *>(pair->Value) == GENDER_NEUTER ? "neutral" : "other");
*static_cast<FIntCVar *>(pair->Value) == GENDER_NEUTER ? "neutral" :
*static_cast<FIntCVar *>(pair->Value) == GENDER_OBJECT ? "other" : "male");
break;
case NAME_PlayerClass:

View file

@ -79,84 +79,8 @@ extern ColorSetList ColorSets;
FString GetPrintableDisplayName(PClassActor *cls);
class APlayerPawn : public AActor
{
DECLARE_CLASS(APlayerPawn, AActor)
HAS_OBJECT_POINTERS
public:
virtual void Serialize(FSerializer &arc);
void PlayIdle(AActor *player);
virtual void PostBeginPlay() override;
virtual void Tick() override;
virtual void BeginPlay () override;
virtual bool UpdateWaterLevel (bool splash) override;
bool ResetAirSupply (bool playgasp = true);
int GetMaxHealth(bool withupgrades = false) const;
void GiveDeathmatchInventory ();
void GiveDefaultInventory ();
// These are virtual on the script side only.
void PlayIdle();
const char *GetSoundClass () const;
int hasBuddha(); // returns 0 for no buddha, 1 for regular buddha and 2 for strong buddha
enum EInvulState
{
INVUL_Start,
INVUL_Active,
INVUL_Stop,
INVUL_GetAlpha
};
int crouchsprite;
int MaxHealth;
int BonusHealth;
int MugShotMaxHealth;
int RunHealth;
int PlayerFlags;
double FullHeight;
TObjPtr<AActor*> InvFirst; // first inventory item displayed on inventory bar
TObjPtr<AActor*> InvSel; // selected inventory item
// [GRB] Player class properties
double JumpZ;
double GruntSpeed;
double FallingScreamMinSpeed, FallingScreamMaxSpeed;
double ViewHeight;
double ForwardMove1, ForwardMove2;
double SideMove1, SideMove2;
FTextureID ScoreIcon;
int SpawnMask;
FName MorphWeapon;
double AttackZOffset; // attack height, relative to player center
double UseRange; // [NS] Distance at which player can +use
double AirCapacity; // Multiplier for air supply underwater.
PClassActor *FlechetteType;
// [CW] Fades for when you are being damaged.
PalEntry DamageFade;
// [SP] ViewBob Multiplier
double ViewBob;
double curBob;
// Former class properties that were moved into the object to get rid of the meta class.
FName SoundClass; // Sound class
FName Face; // Doom status bar face (when used)
FName Portrait;
FName Slot[10];
double HexenArmor[5];
uint8_t ColorRangeStart; // Skin color range
uint8_t ColorRangeEnd;
};
//
// PlayerPawn flags
@ -164,8 +88,6 @@ public:
enum
{
PPF_NOTHRUSTWHENINVUL = 1, // Attacks do not thrust the player if they are invulnerable.
PPF_CANSUPERMORPH = 2, // Being remorphed into this class can give you a Tome of Power
PPF_CROUCHABLEMORPH = 4, // This morphed player can crouch
};
//
@ -369,7 +291,7 @@ public:
void SetLogText (const char *text);
void SendPitchLimits() const;
APlayerPawn *mo = nullptr;
AActor *mo = nullptr;
uint8_t playerstate = 0;
ticcmd_t cmd = {};
usercmd_t original_cmd;
@ -483,9 +405,15 @@ public:
double GetDeltaViewHeight() const
{
return (mo->ViewHeight + crouchviewdelta - viewheight) / 8;
return (mo->FloatVar(NAME_ViewHeight) + crouchviewdelta - viewheight) / 8;
}
double DefaultViewHeight() const
{
return mo->FloatVar(NAME_ViewHeight);
}
void Uncrouch()
{
if (crouchfactor != 1)
@ -495,15 +423,10 @@ public:
crouchdir = 0;
crouching = 0;
crouchviewdelta = 0;
viewheight = mo ? mo->ViewHeight : 0;
viewheight = mo ? mo->FloatVar(NAME_ViewHeight) : 0;
}
}
bool CanCrouch() const
{
return morphTics == 0 || mo->PlayerFlags & PPF_CROUCHABLEMORPH;
}
int GetSpawnClass();
// PSprite layers
@ -515,8 +438,6 @@ public:
// you are 100% sure the context already implies the layer exists.
DPSprite *GetPSprite(PSPLayers layer);
bool GetPainFlash(FName type, PalEntry *color) const;
// [Nash] set player FOV
void SetFOV(float fov);
bool HasWeaponsInSlot(int slot) const;

View file

@ -503,7 +503,7 @@ void DObject::StaticPointerSubstitution (AActor *old, AActor *notOld)
{
if (playeringame[i])
{
APlayerPawn *replacement = static_cast<APlayerPawn *>(notOld);
AActor *replacement = notOld;
auto &p = players[i];
if (p.mo == old) p.mo = replacement, changed++;

View file

@ -38,6 +38,7 @@
#include <type_traits>
#include "doomtype.h"
#include "i_system.h"
#include "vectors.h"
class PClass;
class PType;
@ -238,6 +239,7 @@ public:
inline PalEntry &ColorVar(FName field);
inline FName &NameVar(FName field);
inline double &FloatVar(FName field);
inline DAngle &AngleVar(FName field);
inline FString &StringVar(FName field);
template<class T> T*& PointerVar(FName field);
@ -456,6 +458,11 @@ inline double &DObject::FloatVar(FName field)
return *(double*)ScriptVar(field, nullptr);
}
inline DAngle &DObject::AngleVar(FName field)
{
return *(DAngle*)ScriptVar(field, nullptr);
}
template<class T>
inline T *&DObject::PointerVar(FName field)
{

View file

@ -190,24 +190,6 @@ size_t PropagateMark()
obj->GetClass()->Size;
}
//==========================================================================
//
// PropagateAll
//
// Empties the gray list by propagating every single object in it.
//
//==========================================================================
static size_t PropagateAll()
{
size_t m = 0;
while (Gray != NULL)
{
m += PropagateMark();
}
return m;
}
//==========================================================================
//
// SweepList
@ -273,7 +255,7 @@ void Mark(DObject **obj)
{
DObject *lobj = *obj;
assert(lobj == nullptr || !(lobj->ObjectFlags & OF_Released));
//assert(lobj == nullptr || !(lobj->ObjectFlags & OF_Released));
if (lobj != nullptr && !(lobj->ObjectFlags & OF_Released))
{
if (lobj->ObjectFlags & OF_EuthanizeMe)
@ -668,14 +650,14 @@ size_t DSectorMarker::PropagateMark()
moretodo = true;
}
if (!moretodo && polyobjs != NULL)
if (!moretodo && level.Polyobjects.Size() > 0)
{
for (i = 0; i < POLYSTEPSIZE && PolyNum + i < po_NumPolyobjs; ++i)
for (i = 0; i < POLYSTEPSIZE && PolyNum + i < (int)level.Polyobjects.Size(); ++i)
{
GC::Mark(polyobjs[PolyNum + i].interpolation);
GC::Mark(level.Polyobjects[PolyNum + i].interpolation);
}
marked += i * sizeof(FPolyObj);
if (PolyNum + i < po_NumPolyobjs)
if (PolyNum + i < (int)level.Polyobjects.Size())
{
PolyNum += i;
moretodo = true;
@ -686,7 +668,7 @@ size_t DSectorMarker::PropagateMark()
for (i = 0; i < SIDEDEFSTEPSIZE && SideNum + i < (int)level.sides.Size(); ++i)
{
side_t *side = &level.sides[SideNum + i];
for(int j=0;j<3;j++) GC::Mark(side->textures[j].interpolation);
for (int j = 0; j < 3; j++) GC::Mark(side->textures[j].interpolation);
}
marked += i * sizeof(side_t);
if (SideNum + i < (int)level.sides.Size())

View file

@ -180,6 +180,28 @@ public:
return *this;
}
T operator=(std::nullptr_t nul)
{
o = nullptr;
return *this;
}
// To allow NULL, too.
T operator=(const int val)
{
assert(val == 0);
o = nullptr;
return *this;
}
// To allow NULL, too. In Clang NULL is a long.
T operator=(const long val)
{
assert(val == 0);
o = nullptr;
return *this;
}
operator T() throw()
{
return GC::ReadBarrier(pp);
@ -190,13 +212,6 @@ public:
assert(q != NULL);
return *q;
}
T *operator&() throw()
{
// Does not perform a read barrier. The only real use for this is with
// the DECLARE_POINTER macro, where a read barrier would be a very bad
// thing.
return &pp;
}
T operator->() throw()
{
return GC::ReadBarrier(pp);

View file

@ -267,7 +267,17 @@ inline VersionInfo MakeVersion(unsigned int ma, unsigned int mi, unsigned int re
return{ (uint16_t)ma, (uint16_t)mi, (uint32_t)re };
}
enum class ELightMode : int8_t
{
NotSet = -1,
LinearStandard = 0,
DoomBright = 1,
Doom = 2,
DoomDark = 3,
DoomLegacy = 4,
ZDoomSoftware = 8,
DoomSoftware = 16
};
// Screenshot buffer image data types
enum ESSType

View file

@ -39,7 +39,7 @@ IMPLEMENT_CLASS(DSectorEffect, false, false)
DSectorEffect::DSectorEffect ()
: DThinker(STAT_SECTOREFFECT)
{
m_Sector = NULL;
m_Sector = nullptr;
}
void DSectorEffect::OnDestroy()
@ -48,15 +48,15 @@ void DSectorEffect::OnDestroy()
{
if (m_Sector->floordata == this)
{
m_Sector->floordata = NULL;
m_Sector->floordata = nullptr;
}
if (m_Sector->ceilingdata == this)
{
m_Sector->ceilingdata = NULL;
m_Sector->ceilingdata = nullptr;
}
if (m_Sector->lightingdata == this)
{
m_Sector->lightingdata = NULL;
m_Sector->lightingdata = nullptr;
}
}
Super::OnDestroy();
@ -91,7 +91,7 @@ IMPLEMENT_POINTERS_END
DMover::DMover (sector_t *sector)
: DSectorEffect (sector)
{
interpolation = NULL;
interpolation = nullptr;
}
void DMover::OnDestroy()
@ -108,10 +108,10 @@ void DMover::Serialize(FSerializer &arc)
void DMover::StopInterpolation(bool force)
{
if (interpolation != NULL)
if (interpolation != nullptr)
{
interpolation->DelRef(force);
interpolation = NULL;
interpolation = nullptr;
}
}

View file

@ -40,6 +40,8 @@
#include "vm.h"
#include "c_dispatch.h"
#include "v_text.h"
#include "g_levellocals.h"
#include "a_dynlight.h"
static int ThinkCount;
@ -617,6 +619,13 @@ void DThinker::RunThinkers ()
count += TickThinkers(&FreshThinkers[i], &Thinkers[i]);
}
} while (count != 0);
for (auto light = level.lights; light;)
{
auto next = light->next;
light->Tick();
light = next;
}
}
else
{
@ -637,6 +646,19 @@ void DThinker::RunThinkers ()
}
} while (count != 0);
// Also profile the internal dynamic lights, even though they are not implemented as thinkers.
auto &prof = Profiles[NAME_InternalDynamicLight];
prof.timer.Clock();
for (auto light = level.lights; light;)
{
prof.numcalls++;
auto next = light->next;
light->Tick();
light = next;
}
prof.timer.Unclock();
struct SortedProfileInfo
{
const char* className;

View file

@ -75,6 +75,11 @@ bool E_RegisterHandler(DStaticEventHandler* handler)
{
// if before is not null, link it before the existing handler.
// note that before can be first handler, check for this.
if (before->prev != nullptr)
{
before->prev->next = handler;
GC::WriteBarrier(before->prev, handler);
}
handler->next = before;
GC::WriteBarrier(handler, before);
handler->prev = before->prev;
@ -530,6 +535,14 @@ bool E_CheckReplacement( PClassActor *replacee, PClassActor **replacement )
return final;
}
bool E_CheckReplacee(PClassActor **replacee, PClassActor *replacement)
{
bool final = false;
for (DStaticEventHandler *handler = E_FirstEventHandler; handler; handler = handler->next)
handler->CheckReplacee(replacee, replacement, &final);
return final;
}
void E_NewGame(EventHandlerType handlerType)
{
bool isStatic = handlerType == EventHandlerType::Global;
@ -621,6 +634,10 @@ DEFINE_FIELD_X(ReplaceEvent, FReplaceEvent, Replacee)
DEFINE_FIELD_X(ReplaceEvent, FReplaceEvent, Replacement)
DEFINE_FIELD_X(ReplaceEvent, FReplaceEvent, IsFinal)
DEFINE_FIELD_X(ReplacedEvent, FReplacedEvent, Replacee)
DEFINE_FIELD_X(ReplacedEvent, FReplacedEvent, Replacement)
DEFINE_FIELD_X(ReplacedEvent, FReplacedEvent, IsFinal)
DEFINE_ACTION_FUNCTION(DStaticEventHandler, SetOrder)
{
PARAM_SELF_PROLOGUE(DStaticEventHandler);
@ -1187,6 +1204,21 @@ void DStaticEventHandler::CheckReplacement( PClassActor *replacee, PClassActor *
}
}
void DStaticEventHandler::CheckReplacee(PClassActor **replacee, PClassActor *replacement, bool *final)
{
IFVIRTUAL(DStaticEventHandler, CheckReplacee)
{
// don't create excessive DObjects if not going to be processed anyway
if (isEmpty(func)) return;
FReplacedEvent e = { *replacee, replacement, *final };
VMValue params[2] = { (DStaticEventHandler*)this, &e };
VMCall(func, params, 2, nullptr, 0);
if (e.Replacee != replacement) // prevent infinite recursion
*replacee = e.Replacee;
*final = e.IsFinal;
}
}
void DStaticEventHandler::NewGame()
{
IFVIRTUAL(DStaticEventHandler, NewGame)

View file

@ -81,6 +81,8 @@ void E_Console(int player, FString name, int arg1, int arg2, int arg3, bool manu
// called when looking up the replacement for an actor class
bool E_CheckReplacement(PClassActor* replacee, PClassActor** replacement);
// called when looking up the replaced for an actor class
bool E_CheckReplacee(PClassActor** replacee, PClassActor* replacement);
// called on new game
void E_NewGame(EventHandlerType handlerType);
@ -187,6 +189,7 @@ public:
//
void CheckReplacement(PClassActor* replacee, PClassActor** replacement, bool* final);
void CheckReplacee(PClassActor** replacee, PClassActor* replacement, bool* final);
//
void NewGame();
@ -301,4 +304,11 @@ struct FReplaceEvent
bool IsFinal;
};
struct FReplacedEvent
{
PClassActor* Replacee;
PClassActor* Replacement;
bool IsFinal;
};
#endif

View file

@ -117,7 +117,7 @@ void FS_MapCmd(FScanner &sc)
//
//==========================================================================
void FS_EmulateCmd(char * string)
void FS_EmulateCmd(FLevelLocals *Level, char * string)
{
FScanner sc;
sc.OpenMem("RUNCMD", string, (int)strlen(string));
@ -144,7 +144,7 @@ void FS_EmulateCmd(char * string)
else if (sc.Compare("gravity"))
{
sc.MustGetFloat();
level.gravity=(float)(sc.Float*800);
Level->gravity=(float)(sc.Float*800);
while (sc.GetString())
{
if (sc.Compare(";")) break;
@ -157,7 +157,7 @@ void FS_EmulateCmd(char * string)
for(int i=0;i<MAXPLAYERS;i++)
{
// No, this is not correct. But this is the way Legacy WADs expect it to be handled!
if (players[i].mo != NULL) players[i].mo->ViewHeight = playerviewheight;
if (players[i].mo != NULL) players[i].mo->FloatVar(NAME_ViewHeight) = playerviewheight;
players[i].viewheight = playerviewheight;
players[i].Uncrouch();
}
@ -174,15 +174,15 @@ void FS_EmulateCmd(char * string)
{
sc.MustGetNumber();
// Using this disables most MAPINFO fog options!
level.fogdensity = sc.Number * 70 / 400;
level.outsidefogdensity = 0;
level.skyfog = 0;
level.info->outsidefog = 0;
Level->fogdensity = sc.Number * 70 / 400;
Level->outsidefogdensity = 0;
Level->skyfog = 0;
Level->info->outsidefog = 0;
}
else if (sc.Compare("gr_fogcolor"))
{
sc.MustGetString();
level.fadeto = (uint32_t)strtoull(sc.String, NULL, 16);
Level->fadeto = (uint32_t)strtoull(sc.String, NULL, 16);
}
else

View file

@ -7,10 +7,9 @@
struct MapData;
class AActor;
void T_PreprocessScripts();
void T_LoadScripts(MapData * map);
void T_AddSpawnedThing(AActor * );
bool T_RunScript(int snum, AActor * t_trigger);
void FS_Close();
void T_PreprocessScripts(FLevelLocals *Level);
void T_LoadScripts(FLevelLocals *Level, MapData * map);
void T_AddSpawnedThing(FLevelLocals *Level, AActor * );
bool T_RunScript(FLevelLocals *l, int snum, AActor * t_trigger);
#endif

View file

@ -222,7 +222,7 @@ static PClassActor * ActorTypes[countof(ActorNames_init)];
// Doom index is only supported for the original things up to MBF
//
//==========================================================================
PClassActor * T_GetMobjType(svalue_t arg)
PClassActor * FParser::T_GetMobjType(svalue_t arg)
{
PClassActor * pclass=NULL;
@ -256,7 +256,7 @@ PClassActor * T_GetMobjType(svalue_t arg)
// Input can be either an actor variable or an index value
//
//==========================================================================
static int T_GetPlayerNum(const svalue_t &arg)
int FParser::T_GetPlayerNum(const svalue_t &arg)
{
int playernum;
if(arg.type == svt_mobj)
@ -285,7 +285,7 @@ static int T_GetPlayerNum(const svalue_t &arg)
return playernum;
}
APlayerPawn *T_GetPlayerActor(const svalue_t &arg)
AActor *FParser::T_GetPlayerActor(const svalue_t &arg)
{
int num = T_GetPlayerNum(arg);
return num == -1 ? nullptr : players[num].mo;
@ -887,12 +887,12 @@ void FParser::SF_Spawn(void)
{
t_return.value.mobj->Angles.Yaw = angle;
if (!DFraggleThinker::ActiveThinker->nocheckposition)
if (!Level->info->fs_nocheckposition)
{
if (!P_TestMobjLocation(t_return.value.mobj))
{
if (t_return.value.mobj->flags&MF_COUNTKILL) level.total_monsters--;
if (t_return.value.mobj->flags&MF_COUNTITEM) level.total_items--;
if (t_return.value.mobj->flags&MF_COUNTKILL) Level->total_monsters--;
if (t_return.value.mobj->flags&MF_COUNTITEM) Level->total_items--;
t_return.value.mobj->Destroy();
t_return.value.mobj = NULL;
}
@ -1521,7 +1521,7 @@ void FParser::SF_StartSectorSound(void)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
sector = &level.sectors[i];
sector = &Level->sectors[i];
S_Sound(sector, CHAN_BODY, T_FindSound(stringvalue(t_argv[1])), 1.0f, ATTN_NORM);
}
}
@ -1558,7 +1558,7 @@ void FParser::SF_FloorHeight(void)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
auto &sec = level.sectors[i];
auto &sec = Level->sectors[i];
if (sec.floordata) continue; // don't move floors that are active!
if (sec.MoveFloor(
@ -1580,7 +1580,7 @@ void FParser::SF_FloorHeight(void)
script_error("sector not found with tagnum %i\n", tagnum);
return;
}
returnval = level.sectors[secnum].CenterFloor();
returnval = Level->sectors[secnum].CenterFloor();
}
// return floor height
@ -1613,7 +1613,7 @@ void FParser::SF_MoveFloor(void)
FSSectorTagIterator itr(tagnum);
while ((secnum = itr.Next()) >= 0)
{
P_CreateFloor(&level.sectors[secnum], DFloor::floorMoveToValue, NULL, platspeed, destheight, crush, 0, false, false);
P_CreateFloor(&Level->sectors[secnum], DFloor::floorMoveToValue, NULL, platspeed, destheight, crush, 0, false, false);
}
}
}
@ -1648,7 +1648,7 @@ void FParser::SF_CeilingHeight(void)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
auto &sec = level.sectors[i];
auto &sec = Level->sectors[i];
if (sec.ceilingdata) continue; // don't move ceilings that are active!
if (sec.MoveCeiling(
@ -1670,7 +1670,7 @@ void FParser::SF_CeilingHeight(void)
script_error("sector not found with tagnum %i\n", tagnum);
return;
}
returnval = level.sectors[secnum].CenterCeiling();
returnval = Level->sectors[secnum].CenterCeiling();
}
// return ceiling height
@ -1705,7 +1705,7 @@ void FParser::SF_MoveCeiling(void)
FSSectorTagIterator itr(tagnum);
while ((secnum = itr.Next()) >= 0)
{
P_CreateCeiling(&level.sectors[secnum], DCeiling::ceilMoveToValue, NULL, tagnum, platspeed, platspeed, destheight, crush, silent | 4, 0, DCeiling::ECrushMode::crushDoom);
P_CreateCeiling(&Level->sectors[secnum], DCeiling::ceilMoveToValue, NULL, tagnum, platspeed, platspeed, destheight, crush, silent | 4, 0, DCeiling::ECrushMode::crushDoom);
}
}
}
@ -1734,7 +1734,7 @@ void FParser::SF_LightLevel(void)
return;
}
sector = &level.sectors[secnum];
sector = &Level->sectors[secnum];
if(t_argc > 1) // > 1: set light level
{
@ -1744,7 +1744,7 @@ void FParser::SF_LightLevel(void)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
level.sectors[i].SetLightLevel(intvalue(t_argv[1]));
Level->sectors[i].SetLightLevel(intvalue(t_argv[1]));
}
}
@ -1768,7 +1768,7 @@ class DLightLevel : public DLighting
unsigned char destlevel;
unsigned char speed;
DLightLevel() {}
DLightLevel() = default;
public:
@ -1862,7 +1862,7 @@ void FParser::SF_FadeLight(void)
FSectorTagIterator it(sectag);
while ((i = it.Next()) >= 0)
{
if (!level.sectors[i].lightingdata) Create<DLightLevel>(&level.sectors[i],destlevel,speed);
if (!Level->sectors[i].lightingdata) Create<DLightLevel>(&Level->sectors[i],destlevel,speed);
}
}
}
@ -1887,7 +1887,7 @@ void FParser::SF_FloorTexture(void)
if(secnum < 0)
{ script_error("sector not found with tagnum %i\n", tagnum); return;}
sector = &level.sectors[secnum];
sector = &Level->sectors[secnum];
if(t_argc > 1)
{
@ -1898,7 +1898,7 @@ void FParser::SF_FloorTexture(void)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
level.sectors[i].SetTexture(sector_t::floor, picnum);
Level->sectors[i].SetTexture(sector_t::floor, picnum);
}
}
@ -1939,7 +1939,7 @@ void FParser::SF_SectorColormap(void)
if(secnum < 0)
{ script_error("sector not found with tagnum %i\n", tagnum); return;}
sector = &level.sectors[secnum];
sector = &Level->sectors[secnum];
if (t_argv[1].type==svt_string)
{
@ -1949,7 +1949,7 @@ void FParser::SF_SectorColormap(void)
while ((i = itr.Next()) >= 0)
{
sectors[i].midmap=cm;
sectors[i].heightsec=&level.sectors[i];
sectors[i].heightsec=&Level->sectors[i];
}
}
*/
@ -1977,7 +1977,7 @@ void FParser::SF_CeilingTexture(void)
if(secnum < 0)
{ script_error("sector not found with tagnum %i\n", tagnum); return;}
sector = &level.sectors[secnum];
sector = &Level->sectors[secnum];
if(t_argc > 1)
{
@ -1988,7 +1988,7 @@ void FParser::SF_CeilingTexture(void)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
level.sectors[i].SetTexture(sector_t::ceiling, picnum);
Level->sectors[i].SetTexture(sector_t::ceiling, picnum);
}
}
@ -2080,7 +2080,7 @@ void FParser::SF_CloseDoor(void)
// run console cmd
void FParser::SF_RunCommand(void)
{
FS_EmulateCmd(GetFormatString(0).LockBuffer());
FS_EmulateCmd(Level, GetFormatString(0).LockBuffer());
}
//==========================================================================
@ -2161,7 +2161,7 @@ void FParser::SF_SetLineBlocking(void)
int i;
while ((i = itr.Next()) >= 0)
{
level.lines[i].flags = (level.lines[i].flags & ~(ML_BLOCKING | ML_BLOCKEVERYTHING)) | blocking;
Level->lines[i].flags = (Level->lines[i].flags & ~(ML_BLOCKING | ML_BLOCKEVERYTHING)) | blocking;
}
}
}
@ -2184,7 +2184,7 @@ void FParser::SF_SetLineMonsterBlocking(void)
int i;
while ((i = itr.Next()) >= 0)
{
level.lines[i].flags = (level.lines[i].flags & ~ML_BLOCKMONSTERS) | blocking;
Level->lines[i].flags = (Level->lines[i].flags & ~ML_BLOCKMONSTERS) | blocking;
}
}
}
@ -2241,11 +2241,11 @@ void FParser::SF_SetLineTexture(void)
while ((i = itr.Next()) >= 0)
{
// bad sidedef, Hexen just SEGV'd here!
if (level.lines[i].sidedef[side] != NULL)
if (Level->lines[i].sidedef[side] != NULL)
{
if (position >= 0 && position <= 2)
{
level.lines[i].sidedef[side]->SetTexture(position, texturenum);
Level->lines[i].sidedef[side]->SetTexture(position, texturenum);
}
}
}
@ -2260,7 +2260,7 @@ void FParser::SF_SetLineTexture(void)
FLineIdIterator itr(tag);
while ((i = itr.Next()) >= 0)
{
side_t *sided = level.lines[i].sidedef[side];
side_t *sided = Level->lines[i].sidedef[side];
if(sided != NULL)
{
if(sections & 1) sided->SetTexture(side_t::top, picnum);
@ -3108,7 +3108,7 @@ void FParser::SF_SpawnMissile()
void FParser::SF_MapThingNumExist()
{
auto &SpawnedThings = DFraggleThinker::ActiveThinker->SpawnedThings;
auto &SpawnedThings = Level->FraggleScriptThinker->SpawnedThings;
int intval;
@ -3137,7 +3137,7 @@ void FParser::SF_MapThingNumExist()
void FParser::SF_MapThings()
{
auto &SpawnedThings = DFraggleThinker::ActiveThinker->SpawnedThings;
auto &SpawnedThings = Level->FraggleScriptThinker->SpawnedThings;
t_return.type = svt_int;
t_return.value.i = SpawnedThings.Size();
@ -3204,13 +3204,13 @@ void FParser::SF_LineFlag()
if (CheckArgs(2))
{
linenum = intvalue(t_argv[0]);
if(linenum >= level.lines.Size())
if(linenum >= Level->lines.Size())
{
script_error("LineFlag: Invalid line number.\n");
return;
}
line = &level.lines[linenum];
line = &Level->lines[linenum];
flagnum = intvalue(t_argv[1]);
if(flagnum < 0 || (flagnum > 8 && flagnum!=15))
@ -3311,7 +3311,7 @@ void FParser::SF_Resurrect()
mo->Height = mo->GetDefault()->Height;
mo->radius = mo->GetDefault()->radius;
mo->Revive();
mo->target = NULL;
mo->target = nullptr;
}
}
@ -3573,7 +3573,7 @@ void FParser::SF_SetCorona(void)
void FParser::SF_LevelNum()
{
t_return.type = svt_int;
t_return.value.f = level.levelnum;
t_return.value.f = Level->levelnum;
}
@ -3724,19 +3724,7 @@ void FParser::SF_SetColor(void)
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
if (!DFraggleThinker::ActiveThinker->setcolormaterial)
{
level.sectors[i].SetColor(color, 0);
}
else
{
// little hack for testing the D64 color stuff.
for (int j = 0; j < 4; j++) level.sectors[i].SetSpecialColor(j, color);
// simulates 'nocoloredspritelighting' settings.
int v = (color.r + color.g + color.b) / 3;
v = (255 + v + v) / 3;
level.sectors[i].SetSpecialColor(sector_t::sprites, v, v, v);
}
Level->sectors[i].SetColor(color, 0);
}
}
}
@ -3833,9 +3821,9 @@ void FParser::SF_SetLineTrigger()
mld.special = spec;
mld.tag = tag;
mld.flags = 0;
int f = level.lines[i].flags;
P_TranslateLineDef(&level.lines[i], &mld);
level.lines[i].flags = (level.lines[i].flags & (ML_MONSTERSCANACTIVATE | ML_REPEAT_SPECIAL | ML_SPAC_MASK | ML_FIRSTSIDEONLY)) |
int f = Level->lines[i].flags;
P_TranslateLineDef(&Level->lines[i], &mld);
Level->lines[i].flags = (Level->lines[i].flags & (ML_MONSTERSCANACTIVATE | ML_REPEAT_SPECIAL | ML_SPAC_MASK | ML_FIRSTSIDEONLY)) |
(f & ~(ML_MONSTERSCANACTIVATE | ML_REPEAT_SPECIAL | ML_SPAC_MASK | ML_FIRSTSIDEONLY));
}
@ -3873,7 +3861,7 @@ void FParser::RunLineSpecial(const FLineSpecial *spec)
DRunningScript *FParser::SaveCurrentScript()
{
DFraggleThinker *th = DFraggleThinker::ActiveThinker;
DFraggleThinker *th = Level->FraggleScriptThinker;
if (th)
{
DRunningScript *runscr = Create<DRunningScript>(Script->trigger, Script, Script->MakeIndex(Rover));
@ -3999,7 +3987,7 @@ void FParser::SF_StartScript()
return;
}
DFraggleThinker *th = DFraggleThinker::ActiveThinker;
DFraggleThinker *th = Level->FraggleScriptThinker;
if (th)
{
@ -4035,7 +4023,7 @@ void FParser::SF_ScriptRunning()
snum = intvalue(t_argv[0]);
for(current = DFraggleThinker::ActiveThinker->RunningScripts->next; current; current=current->next)
for(current = Level->FraggleScriptThinker->RunningScripts->next; current; current=current->next)
{
if(current->script->scriptnum == snum)
{
@ -4058,16 +4046,14 @@ void FParser::SF_ScriptRunning()
//
//==========================================================================
static int zoom=1; // Dummy - no longer needed!
void init_functions(void)
void DFraggleThinker::InitFunctions()
{
for(unsigned i=0;i<countof(ActorNames_init);i++)
{
ActorTypes[i]=PClass::FindActor(ActorNames_init[i]);
}
DFsScript * gscr = global_script;
DFsScript * gscr = GlobalScript;
// add all the functions
gscr->NewVariable("consoleplayer", svt_pInt)->value.pI = &consoleplayer;

View file

@ -33,8 +33,7 @@
#include "gi.h"
#include "g_levellocals.h"
#include "xlat/xlat.h"
void T_Init();
#include "maploader/maploader.h"
class FScriptLoader
{
@ -49,62 +48,17 @@ class FScriptLoader
int drownflag;
bool HasScripts;
bool IgnoreInfo;
FLevelLocals *Level;
void ParseInfoCmd(char *line, FString &scriptsrc);
public:
FScriptLoader(FLevelLocals *l)
{
Level = l;
}
bool ParseInfo(MapData * map);
};
struct FFsOptions : public FOptionalMapinfoData
{
FFsOptions()
{
identifier = "fragglescript";
nocheckposition = false;
setcolormaterial = false;
}
virtual FOptionalMapinfoData *Clone() const
{
FFsOptions *newopt = new FFsOptions;
newopt->identifier = identifier;
newopt->nocheckposition = nocheckposition;
newopt->setcolormaterial = setcolormaterial;
return newopt;
}
bool nocheckposition;
bool setcolormaterial;
};
DEFINE_MAP_OPTION(fs_nocheckposition, false)
{
FFsOptions *opt = info->GetOptData<FFsOptions>("fragglescript");
if (parse.CheckAssign())
{
parse.sc.MustGetNumber();
opt->nocheckposition = !!parse.sc.Number;
}
else
{
opt->nocheckposition = true;
}
}
DEFINE_MAP_OPTION(fs_setcolormaterial, false)
{
FFsOptions *opt = info->GetOptData<FFsOptions>("fragglescript");
if (parse.CheckAssign())
{
parse.sc.MustGetNumber();
opt->setcolormaterial = !!parse.sc.Number;
}
else
{
opt->setcolormaterial = true;
}
}
//-----------------------------------------------------------------------------
//
// Process the lump to strip all unneeded information from it
@ -165,13 +119,13 @@ void FScriptLoader::ParseInfoCmd(char *line, FString &scriptsrc)
while (*beg<=' ') beg++;
char * comm = strstr(beg, "//");
if (comm) *comm=0;
level.LevelName = beg;
Level->LevelName = beg;
}
else if (sc.Compare("partime"))
{
sc.MustGetStringName("=");
sc.MustGetNumber();
level.partime=sc.Number;
Level->partime=sc.Number;
}
else if (sc.Compare("music"))
{
@ -181,7 +135,7 @@ void FScriptLoader::ParseInfoCmd(char *line, FString &scriptsrc)
sc.MustGetString();
if (!FS_ChangeMusic(sc.String))
{
S_ChangeMusic(level.Music, level.musicorder);
S_ChangeMusic(Level->Music, Level->musicorder);
}
}
else if (sc.Compare("skyname"))
@ -189,32 +143,32 @@ void FScriptLoader::ParseInfoCmd(char *line, FString &scriptsrc)
sc.MustGetStringName("=");
sc.MustGetString();
sky2texture = sky1texture = level.skytexture1 = level.skytexture2 = TexMan.GetTextureID (sc.String, ETextureType::Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst);
sky2texture = sky1texture = Level->skytexture1 = Level->skytexture2 = TexMan.GetTextureID (sc.String, ETextureType::Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst);
R_InitSkyMap ();
}
else if (sc.Compare("interpic"))
{
sc.MustGetStringName("=");
sc.MustGetString();
level.info->ExitPic = sc.String;
Level->info->ExitPic = sc.String;
}
else if (sc.Compare("gravity"))
{
sc.MustGetStringName("=");
sc.MustGetNumber();
level.gravity=sc.Number*8.f;
Level->gravity=sc.Number*8.f;
}
else if (sc.Compare("nextlevel"))
{
sc.MustGetStringName("=");
sc.MustGetString();
level.NextMap = sc.String;
Level->NextMap = sc.String;
}
else if (sc.Compare("nextsecret"))
{
sc.MustGetStringName("=");
sc.MustGetString();
level.NextSecretMap = sc.String;
Level->NextSecretMap = sc.String;
}
else if (sc.Compare("drown"))
{
@ -228,7 +182,7 @@ void FScriptLoader::ParseInfoCmd(char *line, FString &scriptsrc)
while (*beg<' ') beg++;
char * comm = strstr(beg, "//");
if (comm) *comm=0;
FS_EmulateCmd(beg);
FS_EmulateCmd(Level, beg);
}
else if (sc.Compare("ignore"))
{
@ -303,23 +257,17 @@ bool FScriptLoader::ParseInfo(MapData * map)
}
if (HasScripts)
{
Create<DFraggleThinker>();
DFraggleThinker::ActiveThinker->LevelScript->data = copystring(scriptsrc.GetChars());
if (drownflag==-1) drownflag = (level.maptype != MAPTYPE_DOOM || fsglobal);
if (!drownflag) level.airsupply=0; // Legacy doesn't to water damage so we need to check if it has to be disabled here.
FFsOptions *opt = level.info->GetOptData<FFsOptions>("fragglescript", false);
if (opt != NULL)
if (Level->FraggleScriptThinker)
{
DFraggleThinker::ActiveThinker->nocheckposition = opt->nocheckposition;
DFraggleThinker::ActiveThinker->setcolormaterial = opt->setcolormaterial;
}
else
{
DFraggleThinker::ActiveThinker->nocheckposition = false;
DFraggleThinker::ActiveThinker->setcolormaterial = false;
I_Error("Only one FraggleThinker is allowed to exist at a time.\nCheck your code.");
}
auto th = Create<DFraggleThinker>();
th->LevelScript->data = copystring(scriptsrc.GetChars());
Level->FraggleScriptThinker = th;
if (drownflag==-1) drownflag = (Level->maptype != MAPTYPE_DOOM || fsglobal);
if (!drownflag) Level->airsupply=0; // Legacy doesn't to water damage so we need to check if it has to be disabled here.
}
@ -334,12 +282,9 @@ bool FScriptLoader::ParseInfo(MapData * map)
//
//-----------------------------------------------------------------------------
void T_LoadScripts(MapData *map)
void T_LoadScripts(FLevelLocals *Level, MapData *map)
{
FScriptLoader parser;
T_Init();
FScriptLoader parser(Level);
bool HasScripts = parser.ParseInfo(map);
// Hack for Legacy compatibility: Since 272 is normally an MBF sky transfer we have to patch it.
@ -348,12 +293,10 @@ void T_LoadScripts(MapData *map)
// This code then then swaps 270 and 272 - but only if this is either Doom or Heretic and
// the default translator is being used.
// Custom translators will not be patched.
if ((gameinfo.gametype == GAME_Doom || gameinfo.gametype == GAME_Heretic) && level.info->Translator.IsEmpty() &&
level.maptype == MAPTYPE_DOOM && SimpleLineTranslations.Size() > 272 && SimpleLineTranslations[272 - 2*HasScripts].special == FS_Execute)
if ((gameinfo.gametype == GAME_Doom || gameinfo.gametype == GAME_Heretic) && Level->info->Translator.IsEmpty() &&
Level->maptype == MAPTYPE_DOOM && SimpleLineTranslations.Size() > 272 && SimpleLineTranslations[272 - 2*HasScripts].special == FS_Execute)
{
FLineTrans t = SimpleLineTranslations[270];
SimpleLineTranslations[270] = SimpleLineTranslations[272];
SimpleLineTranslations[272] = t;
std::swap(SimpleLineTranslations[270], SimpleLineTranslations[272]);
}
}
@ -364,11 +307,11 @@ void T_LoadScripts(MapData *map)
//
//-----------------------------------------------------------------------------
void T_AddSpawnedThing(AActor * ac)
void T_AddSpawnedThing(FLevelLocals *Level, AActor * ac)
{
if (DFraggleThinker::ActiveThinker)
if (Level->FraggleScriptThinker)
{
auto &SpawnedThings = DFraggleThinker::ActiveThinker->SpawnedThings;
auto &SpawnedThings = Level->FraggleScriptThinker->SpawnedThings;
SpawnedThings.Push(GC::ReadBarrier(ac));
}
}

View file

@ -89,7 +89,7 @@ void FParser::OPequals(svalue_t &result, int start, int n, int stop)
if(var)
{
EvaluateExpression(result, n+1, stop);
var->SetValue (result);
var->SetValue(Level, result);
}
else
{
@ -490,12 +490,12 @@ void FParser::OPincrement(svalue_t &result, int start, int n, int stop)
{
result.value.i = intvalue(result) + 1;
result.type = svt_int;
var->SetValue (result);
var->SetValue(Level, result);
}
else
{
result.setDouble(floatvalue(result)+1);
var->SetValue (result);
var->SetValue(Level, result);
}
}
else if(stop == n) // n++
@ -515,12 +515,12 @@ void FParser::OPincrement(svalue_t &result, int start, int n, int stop)
{
newvalue.type = svt_int;
newvalue.value.i = intvalue(result) + 1;
var->SetValue (newvalue);
var->SetValue(Level, newvalue);
}
else
{
newvalue.setDouble(floatvalue(result)+1);
var->SetValue (newvalue);
var->SetValue(Level, newvalue);
}
}
else
@ -553,13 +553,13 @@ void FParser::OPdecrement(svalue_t &result, int start, int n, int stop)
{
result.value.i = intvalue(result) - 1;
result.type = svt_int;
var->SetValue (result);
var->SetValue(Level, result);
}
else
{
result.setDouble(floatvalue(result)-1);
result.type = svt_fixed;
var->SetValue (result);
var->SetValue(Level, result);
}
}
else if(stop == n) // n++
@ -579,12 +579,12 @@ void FParser::OPdecrement(svalue_t &result, int start, int n, int stop)
{
newvalue.type = svt_int;
newvalue.value.i = intvalue(result) - 1;
var->SetValue (newvalue);
var->SetValue(Level, newvalue);
}
else
{
newvalue.setDouble(floatvalue(result)-1);
var->SetValue (newvalue);
var->SetValue(Level, newvalue);
}
}
else

View file

@ -43,6 +43,7 @@
#include "t_script.h"
#include "w_wad.h"
#include "serializer.h"
#include "g_levellocals.h"
//==========================================================================
@ -129,7 +130,7 @@ void DFsScript::ClearSections()
var->Destroy();
var = next;
}
sections[i] = NULL;
sections[i] = nullptr;
}
}
@ -338,7 +339,7 @@ void DFsScript::DryRunScript()
char *rover = data;
// allocate space for the tokens
FParser parse(this);
FParser parse(&level, this);
try
{
while(rover < end && *rover)
@ -428,7 +429,7 @@ void DFsScript::ParseInclude(char *lumpname)
ProcessFindChar(lump, 0);
// now parse the lump
FParser parse(this);
FParser parse(&level, this);
parse.Run(lump, lump, lump+lumplen);
// free the lump

View file

@ -40,19 +40,6 @@
#include "serializer.h"
#include "g_levellocals.h"
//==========================================================================
//
// global variables
// These two are the last remaining ones:
// - The global script contains static data so it must be global
// - The trigger is referenced by a global variable. However, it is set
// each time a script is started so that's not a problem.
//
//==========================================================================
DFsScript *global_script;
AActor *trigger_obj;
//==========================================================================
//
//
@ -122,7 +109,7 @@ void DFsScript::ClearChildren()
for(j=0;j<MAXSCRIPTS;j++) if (children[j])
{
children[j]->Destroy();
children[j]=NULL;
children[j]=nullptr;
}
}
@ -136,15 +123,15 @@ DFsScript::DFsScript()
{
int i;
for(i=0; i<SECTIONSLOTS; i++) sections[i] = NULL;
for(i=0; i<VARIABLESLOTS; i++) variables[i] = NULL;
for(i=0; i<MAXSCRIPTS; i++) children[i] = NULL;
for(i=0; i<SECTIONSLOTS; i++) sections[i] = nullptr;
for(i=0; i<VARIABLESLOTS; i++) variables[i] = nullptr;
for(i=0; i<MAXSCRIPTS; i++) children[i] = nullptr;
data = NULL;
data = nullptr;
scriptnum = -1;
len = 0;
parent = NULL;
trigger = NULL;
parent = nullptr;
trigger = nullptr;
lastiftrue = false;
}
@ -157,8 +144,8 @@ DFsScript::DFsScript()
DFsScript::~DFsScript()
{
if (data != NULL) delete[] data;
data = NULL;
if (data != nullptr) delete[] data;
data = nullptr;
}
//==========================================================================
@ -172,11 +159,11 @@ void DFsScript::OnDestroy()
ClearVariables(true);
ClearSections();
ClearChildren();
parent = NULL;
if (data != NULL) delete [] data;
data = NULL;
parent = NULL;
trigger = NULL;
parent = nullptr;
if (data != nullptr) delete [] data;
data = nullptr;
parent = nullptr;
trigger = nullptr;
Super::OnDestroy();
}
@ -189,8 +176,8 @@ void DFsScript::OnDestroy()
void DFsScript::Serialize(FSerializer &arc)
{
Super::Serialize(arc);
// don't save a reference to the global script
if (parent == global_script) parent = nullptr;
// don't save a reference to the global script, which contains unserializable data.
if (parent == level.FraggleScriptThinker->GlobalScript) parent = nullptr;
arc("data", data)
("scriptnum", scriptnum)
@ -202,7 +189,7 @@ void DFsScript::Serialize(FSerializer &arc)
.Array("variables", variables, VARIABLESLOTS)
.Array("children", children, MAXSCRIPTS);
if (parent == nullptr) parent = global_script;
if (parent == nullptr) parent = level.FraggleScriptThinker->GlobalScript;
}
//==========================================================================
@ -215,7 +202,7 @@ void DFsScript::Serialize(FSerializer &arc)
void DFsScript::ParseScript(char *position)
{
if (position == NULL)
if (position == nullptr)
{
lastiftrue = false;
position = data;
@ -228,11 +215,11 @@ void DFsScript::ParseScript(char *position)
return;
}
trigger_obj = trigger; // set trigger
level.FraggleScriptThinker->trigger_obj = trigger; // set trigger
try
{
FParser parse(this);
FParser parse(&level, this);
parse.Run(position, data, data + len);
}
catch (CFraggleScriptError &err)
@ -270,7 +257,7 @@ IMPLEMENT_POINTERS_END
DRunningScript::DRunningScript(AActor *trigger, DFsScript *owner, int index)
{
prev = next = NULL;
prev = next = nullptr;
script = owner;
GC::WriteBarrier(this, script);
save_point = index;
@ -278,9 +265,9 @@ DRunningScript::DRunningScript(AActor *trigger, DFsScript *owner, int index)
wait_data = 0;
this->trigger = trigger;
if (owner == NULL)
if (owner == nullptr)
{
for(int i=0; i< VARIABLESLOTS; i++) variables[i] = NULL;
for(int i=0; i< VARIABLESLOTS; i++) variables[i] = nullptr;
}
else
{
@ -333,7 +320,7 @@ void DRunningScript::OnDestroy()
current->Destroy();
current = next; // go to next in chain
}
variables[i] = NULL;
variables[i] = nullptr;
}
Super::OnDestroy();
}
@ -369,10 +356,9 @@ IMPLEMENT_CLASS(DFraggleThinker, false, true)
IMPLEMENT_POINTERS_START(DFraggleThinker)
IMPLEMENT_POINTER(RunningScripts)
IMPLEMENT_POINTER(LevelScript)
IMPLEMENT_POINTER(GlobalScript)
IMPLEMENT_POINTERS_END
TObjPtr<DFraggleThinker*> DFraggleThinker::ActiveThinker;
//==========================================================================
//
//
@ -382,20 +368,18 @@ TObjPtr<DFraggleThinker*> DFraggleThinker::ActiveThinker;
DFraggleThinker::DFraggleThinker()
: DThinker(STAT_SCRIPTS)
{
if (ActiveThinker)
GlobalScript = Create<DFsScript>();
GC::WriteBarrier(this, GlobalScript);
// do not create resources which will be filled in by the serializer if being called from there.
if (!bSerialOverride)
{
I_Error ("Only one FraggleThinker is allowed to exist at a time.\nCheck your code.");
}
else
{
ActiveThinker = this;
RunningScripts = Create<DRunningScript>();
LevelScript = Create<DFsScript>();
LevelScript->parent = global_script;
GC::WriteBarrier(this, RunningScripts);
LevelScript = Create<DFsScript>();
LevelScript->parent = GlobalScript;
GC::WriteBarrier(this, LevelScript);
nocheckposition = false;
}
InitFunctions();
}
//==========================================================================
@ -411,16 +395,18 @@ void DFraggleThinker::OnDestroy()
{
DRunningScript *q = p;
p = p->next;
q->prev = q->next = NULL;
q->prev = q->next = nullptr;
q->Destroy();
}
RunningScripts = NULL;
RunningScripts = nullptr;
GlobalScript->Destroy();
GlobalScript = nullptr;
LevelScript->Destroy();
LevelScript = NULL;
LevelScript = nullptr;
SpawnedThings.Clear();
ActiveThinker = NULL;
Super::OnDestroy();
}
@ -432,11 +418,11 @@ void DFraggleThinker::OnDestroy()
void DFraggleThinker::Serialize(FSerializer &arc)
{
// The global script is not serialized because the data it points to is not serializable.
Super::Serialize(arc);
arc("levelscript", LevelScript)
("runningscripts", RunningScripts)
("spawnedthings", SpawnedThings)
("nocheckposition", nocheckposition);
("spawnedthings", SpawnedThings);
}
//==========================================================================
@ -522,7 +508,7 @@ void DFraggleThinker::Tick()
{
current->script->variables[i] = current->variables[i];
GC::WriteBarrier(current->script, current->variables[i]);
current->variables[i] = NULL;
current->variables[i] = nullptr;
}
current->script->trigger = current->trigger; // copy trigger
@ -616,9 +602,9 @@ void DFraggleThinker::AddRunningScript(DRunningScript *runscr)
//
//==========================================================================
void T_PreprocessScripts()
void T_PreprocessScripts(FLevelLocals *Level)
{
DFraggleThinker *th = DFraggleThinker::ActiveThinker;
DFraggleThinker *th = Level->FraggleScriptThinker;
if (th)
{
// run the levelscript first
@ -638,9 +624,9 @@ void T_PreprocessScripts()
//
//==========================================================================
bool T_RunScript(int snum, AActor * t_trigger)
bool T_RunScript(FLevelLocals *Level, int snum, AActor * t_trigger)
{
DFraggleThinker *th = DFraggleThinker::ActiveThinker;
DFraggleThinker *th = Level->FraggleScriptThinker;
if (th)
{
// [CO] It is far too dangerous to start the script right away.
@ -662,35 +648,7 @@ bool T_RunScript(int snum, AActor * t_trigger)
//==========================================================================
//
//
//
//==========================================================================
void FS_Close()
{
if (global_script != NULL)
{
GC::DelSoftRoot(global_script);
global_script->Destroy();
global_script = NULL;
}
}
void T_Init()
{
void init_functions();
if (global_script == NULL)
{
global_script = Create<DFsScript>();
GC::AddSoftRoot(global_script);
init_functions();
}
}
//==========================================================================
//
//
// This isn't network safe. FraggleScript as a whole most likely isn't...
//
//==========================================================================
@ -704,6 +662,6 @@ CCMD(fpuke)
}
else
{
T_RunScript(atoi(argv[1]), players[consoleplayer].mo);
T_RunScript(&level, atoi(argv[1]), players[consoleplayer].mo);
}
}

View file

@ -129,7 +129,7 @@ int intvalue(const svalue_t & v);
fsfix fixedvalue(const svalue_t & v);
double floatvalue(const svalue_t & v);
const char *stringvalue(const svalue_t & v);
AActor *actorvalue(const svalue_t &svalue);
AActor *actorvalue(FLevelLocals *Level, const svalue_t &svalue);
//==========================================================================
//
@ -185,7 +185,7 @@ public:
DFsVariable(const char *_name = "");
void GetValue(svalue_t &result);
void SetValue(const svalue_t &newvalue);
void SetValue(FLevelLocals *Level, const svalue_t &newvalue);
void Serialize(FSerializer &ar);
};
@ -232,7 +232,7 @@ public:
DFsSection()
{
next = NULL;
next = nullptr;
}
void Serialize(FSerializer &ar);
@ -398,6 +398,7 @@ struct FParser
char *Tokens[T_MAXTOKENS];
tokentype_t TokenType[T_MAXTOKENS];
int NumTokens;
FLevelLocals *Level;
DFsScript *Script; // the current script
DFsSection *Section;
DFsSection *PrevSection;
@ -408,8 +409,9 @@ struct FParser
svalue_t t_return; // returned value
FString t_func; // name of current function
FParser(DFsScript *scr)
FParser(FLevelLocals *l, DFsScript *scr)
{
Level = l;
LineStart = NULL;
Rover = NULL;
Tokens[0] = new char[scr->len+32]; // 32 for safety. FS seems to need a few bytes more than the script's actual length.
@ -482,6 +484,15 @@ struct FParser
FString GetFormatString(int startarg);
bool CheckArgs(int cnt);
PClassActor * T_GetMobjType(svalue_t arg);
int T_GetPlayerNum(const svalue_t &arg);
AActor *T_GetPlayerActor(const svalue_t &arg);
AActor* actorvalue(const svalue_t &svalue)
{
return ::actorvalue(Level, svalue);
}
void SF_Print();
void SF_Rnd();
void SF_Continue();
@ -678,11 +689,12 @@ class DFraggleThinker : public DThinker
HAS_OBJECT_POINTERS
public:
int zoom = 1;
AActor *trigger_obj; // this is a transient pointer not being subjected to GC.
TObjPtr<DFsScript*> GlobalScript;
TObjPtr<DFsScript*> LevelScript;
TObjPtr<DRunningScript*> RunningScripts;
TArray<TObjPtr<AActor*> > SpawnedThings;
bool nocheckposition = false;
bool setcolormaterial = false;
DFraggleThinker();
void OnDestroy() override;
@ -690,6 +702,7 @@ public:
void Serialize(FSerializer & arc);
void Tick();
void InitFunctions();
size_t PropagateMark();
size_t PointerSubstitution (DObject *old, DObject *notOld);
bool wait_finished(DRunningScript *script);
@ -707,11 +720,7 @@ public:
#include "t_fs.h"
void script_error(const char *s, ...) GCCPRINTF(1,2);
void FS_EmulateCmd(char * string);
extern AActor *trigger_obj;
extern DFsScript *global_script;
void FS_EmulateCmd(FLevelLocals *l, char * string);
#endif

View file

@ -29,6 +29,7 @@
//
#include "t_script.h"
#include "g_levellocals.h"
//==========================================================================
//
@ -467,7 +468,7 @@ void FParser::EvaluateFunction(svalue_t &result, int start, int stop)
}
// all the functions are stored in the global script
else if( !(func = global_script->VariableForName (Tokens[start])) )
else if( !(func = Level->FraggleScriptThinker->GlobalScript->VariableForName (Tokens[start])) )
{
script_error("no such function: '%s'\n",Tokens[start]);
}
@ -551,7 +552,7 @@ void FParser::OPstructure(svalue_t &result, int start, int n, int stop)
svalue_t argv[MAXARGS];
// all the functions are stored in the global script
if( !(func = global_script->VariableForName (Tokens[n+1])) )
if( !(func = Level->FraggleScriptThinker->GlobalScript->VariableForName (Tokens[n+1])) )
{
script_error("no such function: '%s'\n",Tokens[n+1]);
}

View file

@ -42,6 +42,7 @@
#include "t_script.h"
#include "a_pickups.h"
#include "serializer.h"
#include "g_levellocals.h"
//==========================================================================
@ -122,7 +123,7 @@ const char *stringvalue(const svalue_t & v)
//
//==========================================================================
AActor* actorvalue(const svalue_t &svalue)
AActor* actorvalue(FLevelLocals *Level, const svalue_t &svalue)
{
int intval;
@ -138,9 +139,9 @@ AActor* actorvalue(const svalue_t &svalue)
}
else
{
auto &SpawnedThings = DFraggleThinker::ActiveThinker->SpawnedThings;
auto &SpawnedThings = Level->FraggleScriptThinker->SpawnedThings;
// this requires some creativity. We use the intvalue
// as the thing number of a thing in the level.
// as the thing number of a thing in the level
intval = intvalue(svalue);
if(intval < 0 || intval >= (int)SpawnedThings.Size())
@ -178,9 +179,9 @@ DFsVariable::DFsVariable(const char * _name)
{
Name=_name;
type=svt_int;
actor = NULL;
actor = nullptr;
value.i=0;
next=NULL;
next = nullptr;
}
//==========================================================================
@ -234,7 +235,7 @@ void DFsVariable::GetValue(svalue_t &returnvar)
//
//==========================================================================
void DFsVariable::SetValue(const svalue_t &newvalue)
void DFsVariable::SetValue(FLevelLocals *Level, const svalue_t &newvalue)
{
if(type == svt_const)
{
@ -264,7 +265,7 @@ void DFsVariable::SetValue(const svalue_t &newvalue)
break;
case svt_mobj:
actor = actorvalue(newvalue);
actor = actorvalue(Level, newvalue);
break;
case svt_pInt:
@ -272,7 +273,7 @@ void DFsVariable::SetValue(const svalue_t &newvalue)
break;
case svt_pMobj:
*value.pMobj = actorvalue(newvalue);
*value.pMobj = actorvalue(Level, newvalue);
break;
case svt_function:

View file

@ -71,6 +71,7 @@
#include "serializer.h"
#include "vm.h"
#include "dobjgc.h"
#include "gi.h"
#include "g_hub.h"
#include "g_levellocals.h"
@ -181,8 +182,6 @@ short consistancy[MAXPLAYERS][BACKUPTICS];
#define TURBOTHRESHOLD 12800
float normforwardmove[2] = {0x19, 0x32}; // [RH] For setting turbo from console
float normsidemove[2] = {0x18, 0x28}; // [RH] Ditto
int forwardmove[2], sidemove[2];
int angleturn[4] = {640, 1280, 320, 320}; // + slow turn
@ -223,8 +222,14 @@ EXTERN_CVAR (Int, team)
CVAR (Bool, teamplay, false, CVAR_SERVERINFO)
// Workaround for x64 code generation bug in MSVC 2015
// Optimized targets contain illegal instructions in the function below
#if defined _M_X64 && _MSC_VER < 1910
#pragma optimize("", off)
#endif // _M_X64 && _MSC_VER < 1910
// [RH] Allow turbo setting anytime during game
CUSTOM_CVAR (Float, turbo, 100.f, 0)
CUSTOM_CVAR (Float, turbo, 100.f, CVAR_NOINITCALL)
{
if (self < 10.f)
{
@ -238,13 +243,17 @@ CUSTOM_CVAR (Float, turbo, 100.f, 0)
{
double scale = self * 0.01;
forwardmove[0] = (int)(normforwardmove[0]*scale);
forwardmove[1] = (int)(normforwardmove[1]*scale);
sidemove[0] = (int)(normsidemove[0]*scale);
sidemove[1] = (int)(normsidemove[1]*scale);
forwardmove[0] = (int)(gameinfo.normforwardmove[0]*scale);
forwardmove[1] = (int)(gameinfo.normforwardmove[1]*scale);
sidemove[0] = (int)(gameinfo.normsidemove[0]*scale);
sidemove[1] = (int)(gameinfo.normsidemove[1]*scale);
}
}
#if defined _M_X64 && _MSC_VER < 1910
#pragma optimize("", on)
#endif // _M_X64 && _MSC_VER < 1910
CCMD (turnspeeds)
{
if (argv.argc() == 1)
@ -285,7 +294,7 @@ CCMD (slot)
if (slot < NUM_WEAPON_SLOTS && mo)
{
// Needs to be redone
IFVIRTUALPTR(mo, APlayerPawn, PickWeapon)
IFVIRTUALPTRNAME(mo, NAME_PlayerPawn, PickWeapon)
{
VMValue param[] = { mo, slot, !(dmflags2 & DF2_DONTCHECKAMMO) };
VMReturn ret((void**)&SendItemUse);
@ -326,7 +335,7 @@ CCMD (weapnext)
if (mo)
{
// Needs to be redone
IFVIRTUALPTR(mo, APlayerPawn, PickNextWeapon)
IFVIRTUALPTRNAME(mo, NAME_PlayerPawn, PickNextWeapon)
{
VMValue param[] = { mo };
VMReturn ret((void**)&SendItemUse);
@ -352,7 +361,7 @@ CCMD (weapprev)
if (mo)
{
// Needs to be redone
IFVIRTUALPTR(mo, APlayerPawn, PickPrevWeapon)
IFVIRTUALPTRNAME(mo, NAME_PlayerPawn, PickPrevWeapon)
{
VMValue param[] = { mo };
VMReturn ret((void**)&SendItemUse);
@ -421,14 +430,14 @@ CCMD (invuse)
{
if (players[consoleplayer].inventorytics == 0)
{
if (players[consoleplayer].mo) SendItemUse = players[consoleplayer].mo->InvSel;
if (players[consoleplayer].mo) SendItemUse = players[consoleplayer].mo->PointerVar<AActor>(NAME_InvSel);
}
players[consoleplayer].inventorytics = 0;
}
CCMD(invquery)
{
AActor *inv = players[consoleplayer].mo->InvSel;
AActor *inv = players[consoleplayer].mo->PointerVar<AActor>(NAME_InvSel);
if (inv != NULL)
{
Printf(PRINT_HIGH, "%s (%dx)\n", inv->GetTag(), inv->IntVar(NAME_Amount));
@ -447,7 +456,7 @@ CCMD (invdrop)
{
if (players[consoleplayer].mo)
{
SendItemDrop = players[consoleplayer].mo->InvSel;
SendItemDrop = players[consoleplayer].mo->PointerVar<AActor>(NAME_InvSel);
SendItemDropAmount = -1;
}
}
@ -467,40 +476,17 @@ CCMD (drop)
}
}
PClassActor *GetFlechetteType(AActor *other);
CCMD (useflechette)
{ // Select from one of arti_poisonbag1-3, whichever the player has
static const ENamedName bagnames[3] =
{
if (who == nullptr) return;
IFVIRTUALPTRNAME(who, NAME_PlayerPawn, GetFlechetteItem)
{
NAME_ArtiPoisonBag3, // use type 3 first because that's the default when the player has none specified.
NAME_ArtiPoisonBag1,
NAME_ArtiPoisonBag2
};
VMValue params[] = { who };
AActor *cls;
VMReturn ret((void**)&cls);
VMCall(func, params, 1, &ret, 1);
if (who == NULL)
return;
PClassActor *type = who->FlechetteType;
if (type != NULL)
{
AActor *item;
if ( (item = who->FindInventory (type) ))
{
SendItemUse = item;
return;
}
}
// The default flechette could not be found, or the player had no default. Try all 3 types then.
for (int j = 0; j < 3; ++j)
{
AActor *item;
if ( (item = who->FindInventory (bagnames[j])) )
{
SendItemUse = item;
break;
}
if (cls != nullptr) SendItemUse = cls;
}
}
@ -511,7 +497,7 @@ CCMD (select)
auto item = who->FindInventory(argv[1]);
if (item != NULL)
{
who->InvSel = item;
who->PointerVar<AActor>(NAME_InvSel) = item;
}
}
who->player->inventorytics = 5*TICRATE;
@ -1035,9 +1021,8 @@ void G_Ticker ()
if (ToggleFullscreen)
{
static char toggle_fullscreen[] = "toggle fullscreen";
ToggleFullscreen = false;
AddCommandString (toggle_fullscreen);
AddCommandString ("toggle fullscreen");
}
// do things to change the game state
@ -1187,6 +1172,7 @@ void G_Ticker ()
// [ZZ] also tick the UI part of the events
E_UiTick();
C_RunDelayedCommands();
// do main actions
switch (gamestate)
@ -1266,7 +1252,7 @@ void G_PlayerReborn (int player)
int chasecam;
uint8_t currclass;
userinfo_t userinfo; // [RH] Save userinfo
APlayerPawn *actor;
AActor *actor;
PClassActor *cls;
FString log;
DBot *Bot; //Added by MC:
@ -1313,7 +1299,12 @@ void G_PlayerReborn (int player)
if (gamestate != GS_TITLELEVEL)
{
// [GRB] Give inventory specified in DECORATE
actor->GiveDefaultInventory ();
IFVIRTUALPTRNAME(actor, NAME_PlayerPawn, GiveDefaultInventory)
{
VMValue params[1] = { actor };
VMCall(func, params, 1, nullptr, 0);
}
p->ReadyWeapon = p->PendingWeapon;
}
@ -1701,11 +1692,11 @@ void G_DoPlayerPop(int playernum)
}
// [RH] Make the player disappear
FBehavior::StaticStopMyScripts(players[playernum].mo);
level.Behaviors.StopMyScripts(players[playernum].mo);
// [ZZ] fire player disconnect hook
E_PlayerDisconnected(playernum);
// [RH] Let the scripts know the player left
FBehavior::StaticStartTypedScripts(SCRIPT_Disconnect, players[playernum].mo, true, playernum, true);
level.Behaviors.StartTypedScripts(SCRIPT_Disconnect, players[playernum].mo, true, playernum, true);
if (players[playernum].mo != NULL)
{
P_DisconnectEffect(players[playernum].mo);
@ -1717,7 +1708,7 @@ void G_DoPlayerPop(int playernum)
players[playernum].mo->Destroy();
}
players[playernum].mo = NULL;
players[playernum].camera = NULL;
players[playernum].camera = nullptr;
}
players[playernum].DestroyPSprites();
@ -2024,8 +2015,6 @@ CUSTOM_CVAR (Int, autosavecount, 4, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
self = 0;
}
extern void P_CalcHeight (player_t *);
void G_DoAutoSave ()
{
FString description;
@ -2095,9 +2084,9 @@ static void PutSaveComment (FSerializer &arc)
comment.Format("%s - %s\n", level.MapName.GetChars(), level.LevelName.GetChars());
// Append elapsed time
const char *const time = GStrings("SAVECOMMENT_TIME");
levelTime = level.time / TICRATE;
comment.AppendFormat("time: %02d:%02d:%02d",
levelTime/3600, (levelTime%3600)/60, levelTime%60);
comment.AppendFormat("%s: %02d:%02d:%02d", time, levelTime/3600, (levelTime%3600)/60, levelTime%60);
// Write out the comment
arc.AddString("Comment", comment);
@ -2783,7 +2772,7 @@ bool G_CheckDemoStatus (void)
for (int i = 1; i < MAXPLAYERS; i++)
playeringame[i] = 0;
consoleplayer = 0;
players[0].camera = NULL;
players[0].camera = nullptr;
if (StatusBar != NULL)
{
StatusBar->AttachToPlayer (&players[0]);

View file

@ -104,22 +104,11 @@ struct Keygroup
struct Lock
{
TArray<Keygroup *> keylist;
TArray<Keygroup> keylist;
TArray<FSoundID> locksound;
FString Message;
FString RemoteMsg;
int rgb;
Lock()
{
rgb=0;
}
~Lock()
{
for(unsigned int i=0;i<keylist.Size();i++) delete keylist[i];
keylist.Clear();
}
int rgb = 0;
bool check(AActor * owner)
{
@ -138,25 +127,21 @@ struct Lock
}
else for(unsigned int i=0;i<keylist.Size();i++)
{
if (!keylist[i]->check(owner)) return false;
if (!keylist[i].check(owner)) return false;
}
return true;
}
};
static TMap<int, Lock> Locks;
static bool keysdone = false; // have the locks been initialized?
static TArray<PClassActor *> KeyTypes; // List of all keys sorted by lock. This is for use by the status bar to draw ordered key lists.
//===========================================================================
//
//
//===========================================================================
static Lock *locks[256]; // all valid locks
static bool keysdone=false; // have the locks been initialized?
static int currentnumber; // number to be assigned to next key
static bool ignorekey; // set to true when the current lock is not being used
static TArray<PClassActor *> KeyTypes; // List of all keys sorted by lock.
static void ClearLocks();
static const char * keywords_lock[]={
"ANY",
"MESSAGE",
@ -171,7 +156,7 @@ static const char * keywords_lock[]={
//
//===========================================================================
static void AddOneKey(Keygroup *keygroup, PClassActor *mi, FScanner &sc)
static void AddOneKey(Keygroup *keygroup, PClassActor *mi, FScanner &sc, bool ignorekey, int &currentnumber)
{
if (mi)
{
@ -208,26 +193,18 @@ static void AddOneKey(Keygroup *keygroup, PClassActor *mi, FScanner &sc)
//
//===========================================================================
static Keygroup *ParseKeygroup(FScanner &sc)
static void ParseKeygroup(Keygroup *keygroup, FScanner &sc, bool ignorekey, int &currentnumber)
{
Keygroup *keygroup;
PClassActor *mi;
sc.MustGetStringName("{");
keygroup = new Keygroup;
while (!sc.CheckString("}"))
{
sc.MustGetString();
mi = PClass::FindActor(sc.String);
AddOneKey(keygroup, mi, sc);
}
if (keygroup->anykeylist.Size() == 0)
{
delete keygroup;
return NULL;
AddOneKey(keygroup, mi, sc, ignorekey, currentnumber);
}
keygroup->anykeylist.ShrinkToFit();
return keygroup;
}
//===========================================================================
@ -252,13 +229,11 @@ static void PrintMessage (const char *str)
//
//===========================================================================
static void ParseLock(FScanner &sc)
static void ParseLock(FScanner &sc, int &currentnumber)
{
int i,r,g,b;
int keynum;
Lock sink;
Lock *lock = &sink;
Keygroup *keygroup;
PClassActor *mi;
sc.MustGetNumber();
@ -271,23 +246,16 @@ static void ParseLock(FScanner &sc)
sc.MustGetStringName("{");
}
ignorekey = true;
if (keynum > 0 && keynum <= 255)
{
lock = new Lock;
if (locks[keynum])
{
delete locks[keynum];
}
locks[keynum] = lock;
locks[keynum]->locksound.Push("*keytry");
locks[keynum]->locksound.Push("misc/keytry");
ignorekey=false;
}
else if (keynum != -1)
if (keynum == 0 || keynum < -1)
{
sc.ScriptError("Lock index %d out of range", keynum);
}
bool ignorekey = keynum == -1; // tell the parsing functions to ignore what they read for other games' keys.
auto lock = keynum == -1? &sink : &Locks.InsertNew(keynum);
lock->locksound.Push("*keytry");
lock->locksound.Push("misc/keytry");
while (!sc.CheckString("}"))
{
@ -295,12 +263,15 @@ static void ParseLock(FScanner &sc)
switch(i = sc.MatchString(keywords_lock))
{
case 0: // Any
keygroup = ParseKeygroup(sc);
if (keygroup)
{
lock->keylist.Reserve(1);
ParseKeygroup(&lock->keylist.Last(), sc, ignorekey, currentnumber);
if (lock->keylist.Last().anykeylist.Size() == 0)
{
lock->keylist.Push(keygroup);
lock->keylist.Pop();
}
break;
}
case 1: // message
sc.MustGetString();
@ -344,12 +315,11 @@ static void ParseLock(FScanner &sc)
mi = PClass::FindActor(sc.String);
if (mi)
{
keygroup = new Keygroup;
AddOneKey(keygroup, mi, sc);
if (keygroup)
lock->keylist.Reserve(1);
AddOneKey(&lock->keylist.Last(), mi, sc, ignorekey, currentnumber);
if (lock->keylist.Last().anykeylist.Size() == 0)
{
keygroup->anykeylist.ShrinkToFit();
lock->keylist.Push(keygroup);
lock->keylist.Pop();
}
}
break;
@ -389,15 +359,7 @@ static void ClearLocks()
}
}
}
for(i = 0; i < 256; i++)
{
if (locks[i] != NULL)
{
delete locks[i];
locks[i] = NULL;
}
}
currentnumber = 0;
Locks.Clear();
keysdone = false;
}
@ -455,7 +417,7 @@ static void CreateSortedKeyList()
void P_InitKeyMessages()
{
int lastlump, lump;
int lastlump, lump, currentnumber = 0;
lastlump = 0;
@ -467,12 +429,13 @@ void P_InitKeyMessages()
{
if (sc.Compare("LOCK"))
{
ParseLock(sc);
ParseLock(sc, currentnumber);
}
else if (sc.Compare("CLEARLOCKS"))
{
// clear all existing lock definitions and key numbers
ClearLocks();
currentnumber = 0;
}
else
{
@ -485,17 +448,6 @@ void P_InitKeyMessages()
keysdone = true;
}
//===========================================================================
//
// P_DeinitKeyMessages
//
//===========================================================================
void P_DeinitKeyMessages()
{
ClearLocks();
}
//===========================================================================
//
// P_CheckKeys
@ -513,13 +465,14 @@ int P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet)
int numfailsounds;
if (owner == NULL) return false;
if (keynum<=0 || keynum>255) return true;
if (keynum<=0) return true;
// Just a safety precaution. The messages should have been initialized upon game start.
if (!keysdone) P_InitKeyMessages();
FSoundID failage[2] = { "*keytry", "misc/keytry" };
if (!locks[keynum])
auto lock = Locks.CheckKey(keynum);
if (!lock)
{
if (quiet) return false;
if (keynum == 103 && (gameinfo.flags & GI_SHAREWARE))
@ -532,11 +485,11 @@ int P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet)
}
else
{
if (locks[keynum]->check(owner)) return true;
if (lock->check(owner)) return true;
if (quiet) return false;
failtext = remote? locks[keynum]->RemoteMsg : locks[keynum]->Message;
failsound = &locks[keynum]->locksound[0];
numfailsounds = locks[keynum]->locksound.Size();
failtext = remote? lock->RemoteMsg : lock->Message;
failsound = &lock->locksound[0];
numfailsounds = lock->locksound.Size();
}
// If we get here, that means the actor isn't holding an appropriate key.
@ -570,11 +523,13 @@ int P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet)
//
//==========================================================================
int P_GetMapColorForLock (int lock)
int P_GetMapColorForLock (int locknum)
{
if (lock > 0 && lock < 256)
if (locknum > 0)
{
if (locks[lock]) return locks[lock]->rgb;
auto lock = Locks.CheckKey(locknum);
if (lock) return lock->rgb;
}
return -1;
}
@ -587,13 +542,20 @@ int P_GetMapColorForLock (int lock)
int P_GetMapColorForKey (AActor * key)
{
int i;
decltype(Locks)::Iterator it(Locks);
decltype(Locks)::Pair *pair;
for (i = 0; i < 256; i++)
int foundlock = INT_MAX;
int rgb = 0;
while (it.NextPair(pair))
{
if (locks[i] && locks[i]->check(key)) return locks[i]->rgb;
if (pair->Key < foundlock && pair->Value.check(key))
{
rgb = pair->Value.rgb;
foundlock = pair->Key;
}
}
return 0;
return rgb;
}

View file

@ -6,7 +6,6 @@ class PClassActor;
int P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet = false);
void P_InitKeyMessages ();
void P_DeinitKeyMessages ();
int P_GetMapColorForLock (int lock);
int P_GetMapColorForKey (AActor *key);
int P_GetKeyTypeCount();

View file

@ -53,12 +53,12 @@
//
//===========================================================================
FString WeaponSection;
static FString WeaponSection;
TArray<FString> KeyConfWeapons;
FWeaponSlots *PlayingKeyConf;
static FWeaponSlots *PlayingKeyConf;
TArray<PClassActor *> Weapons_ntoh;
TMap<PClassActor *, int> Weapons_hton;
static TArray<PClassActor *> Weapons_ntoh;
static TMap<PClassActor *, int> Weapons_hton;
static int ntoh_cmp(const void *a, const void *b);
@ -491,7 +491,7 @@ void FWeaponSlots::SendDifferences(int playernum, const FWeaponSlots &other)
void FWeaponSlots::SetFromPlayer(PClassActor *type)
{
Clear();
auto Slot = ((APlayerPawn*)GetDefaultByType(type))->Slot;
auto Slot = &GetDefaultByType(type)->NameVar(NAME_Slot);
for (int i = 0; i < NUM_WEAPON_SLOTS; ++i)
{
if (Slot[i] != NAME_None)
@ -748,15 +748,14 @@ void P_PlaybackKeyConfWeapons(FWeaponSlots *slots)
PlayingKeyConf = slots;
for (unsigned int i = 0; i < KeyConfWeapons.Size(); ++i)
{
FString cmd(KeyConfWeapons[i]);
AddCommandString(cmd.LockBuffer());
AddCommandString(KeyConfWeapons[i]);
}
PlayingKeyConf = nullptr;
}
//===========================================================================
//
// APlayerPawn :: SetupWeaponSlots
// SetupWeaponSlots
//
// Sets up the default weapon slots for this player. If this is also the
// local player, determines local modifications and sends those across the
@ -764,7 +763,7 @@ void P_PlaybackKeyConfWeapons(FWeaponSlots *slots)
//
//===========================================================================
void FWeaponSlots::SetupWeaponSlots(APlayerPawn *pp)
void FWeaponSlots::SetupWeaponSlots(AActor *pp)
{
auto player = pp->player;
if (player != nullptr && player->mo == pp)

View file

@ -2,7 +2,6 @@
#include "a_pickups.h"
class PClassActor;
class APlayerPawn;
class FWeaponSlot
{
@ -69,7 +68,7 @@ public:
void SendDifferences(int playernum, const FWeaponSlots &other);
int RestoreSlots (FConfigFile *config, const char *section);
void PrintSettings();
static void SetupWeaponSlots(APlayerPawn *pp);
static void SetupWeaponSlots(AActor *pp);
void AddSlot(int slot, PClassActor *type, bool feedback);
void AddSlotDefault(int slot, PClassActor *type, bool feedback);

View file

@ -78,6 +78,7 @@
#include "vm.h"
#include "events.h"
#include "i_music.h"
#include "a_dynlight.h"
#include "gi.h"
@ -88,7 +89,7 @@
#include "p_maputl.h"
void STAT_StartNewGame(const char *lev);
void STAT_ChangeLevel(const char *newl);
void STAT_ChangeLevel(const char *newl, FLevelLocals *Level);
EXTERN_CVAR(Bool, save_formatted)
EXTERN_CVAR (Float, sv_gravity)
@ -127,7 +128,7 @@ CUSTOM_CVAR(Int, gl_lightmode, 3, CVAR_ARCHIVE | CVAR_NOINITCALL)
else if (newself > 4) newself = 8;
else if (newself < 0) newself = 0;
if (self != newself) self = newself;
else if ((level.info == nullptr || level.info->lightmode == ELightMode::NotSet)) level.lightmode = (ELightMode)*self;
else if ((level.info == nullptr || level.info->lightmode == ELightMode::NotSet)) level.lightMode = (ELightMode)*self;
}
@ -340,8 +341,8 @@ void G_NewInit ()
int i;
// Destory all old player refrences that may still exist
TThinkerIterator<APlayerPawn> it(STAT_TRAVELLING);
APlayerPawn *pawn, *next;
TThinkerIterator<AActor> it(NAME_PlayerPawn, STAT_TRAVELLING);
AActor *pawn, *next;
next = it.Next();
while ((pawn = next) != NULL)
@ -464,13 +465,16 @@ void G_InitNew (const char *mapname, bool bTitleLevel)
ST_CreateStatusBar(bTitleLevel);
setsizeneeded = true;
if (gameinfo.gametype == GAME_Strife || (SBarInfoScript[SCRIPT_CUSTOM] != NULL && SBarInfoScript[SCRIPT_CUSTOM]->GetGameType() == GAME_Strife))
const bool setlogtext = !savegamerestore && (gameinfo.gametype == GAME_Strife
|| (SBarInfoScript[SCRIPT_CUSTOM] != nullptr && SBarInfoScript[SCRIPT_CUSTOM]->GetGameType() == GAME_Strife));
if (setlogtext)
{
// Set the initial quest log text for Strife.
for (i = 0; i < MAXPLAYERS; ++i)
{
if (playeringame[i])
players[i].SetLogText ("Find help");
players[i].SetLogText ("$TXT_FINDHELP");
}
}
@ -640,14 +644,14 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill
// [RH] Give scripts a chance to do something
unloading = true;
FBehavior::StaticStartTypedScripts (SCRIPT_Unloading, NULL, false, 0, true);
level.Behaviors.StartTypedScripts (SCRIPT_Unloading, NULL, false, 0, true);
// [ZZ] safe world unload
E_WorldUnloaded();
// [ZZ] unsafe world unload (changemap != map)
E_WorldUnloadedUnsafe();
unloading = false;
STAT_ChangeLevel(nextlevel);
STAT_ChangeLevel(nextlevel, &level);
if (thiscluster && (thiscluster->flags & CLUSTER_HUB))
{
@ -853,7 +857,7 @@ void G_DoCompleted (void)
G_SnapshotLevel ();
// Do not free any global strings this level might reference
// while it's not loaded.
FBehavior::StaticLockLevelVarStrings();
level.Behaviors.LockLevelVarStrings(level.levelnum);
}
else
{ // Make sure we don't have a snapshot lying around from before.
@ -1088,7 +1092,7 @@ void G_DoLoadLevel (int position, bool autosave, bool newGame)
if (fromSnapshot)
{
// ENTER scripts are being handled when the player gets spawned, this cannot be changed due to its effect on voodoo dolls.
FBehavior::StaticStartTypedScripts(SCRIPT_Return, players[ii].mo, true);
level.Behaviors.StartTypedScripts(SCRIPT_Return, players[ii].mo, true);
}
}
}
@ -1096,7 +1100,7 @@ void G_DoLoadLevel (int position, bool autosave, bool newGame)
if (level.FromSnapshot)
{
// [Nash] run REOPEN scripts upon map re-entry
FBehavior::StaticStartTypedScripts(SCRIPT_Reopen, NULL, false);
level.Behaviors.StartTypedScripts(SCRIPT_Reopen, NULL, false);
}
StatusBar->AttachToPlayer (&players[consoleplayer]);
@ -1288,7 +1292,7 @@ void G_StartTravel ()
{
AActor *pawn = players[i].mo;
AActor *inv;
players[i].camera = NULL;
players[i].camera = nullptr;
// Only living players travel. Dead ones get a new body on the new level.
if (players[i].health > 0)
@ -1298,11 +1302,13 @@ void G_StartTravel ()
pawn->RemoveFromHash ();
pawn->tid = tid; // Restore TID (but no longer linked into the hash chain)
pawn->ChangeStatNum (STAT_TRAVELLING);
pawn->DeleteAttachedLights();
for (inv = pawn->Inventory; inv != NULL; inv = inv->Inventory)
{
inv->ChangeStatNum (STAT_TRAVELLING);
inv->UnlinkFromWorld (nullptr);
inv->DeleteAttachedLights();
}
}
}
@ -1324,15 +1330,15 @@ void G_StartTravel ()
int G_FinishTravel ()
{
TThinkerIterator<APlayerPawn> it (STAT_TRAVELLING);
APlayerPawn *pawn, *pawndup, *oldpawn, *next;
TThinkerIterator<AActor> it (NAME_PlayerPawn, STAT_TRAVELLING);
AActor *pawn, *pawndup, *oldpawn, *next;
AActor *inv;
FPlayerStart *start;
int pnum;
int failnum = 0;
//
APlayerPawn* pawns[MAXPLAYERS];
AActor* pawns[MAXPLAYERS];
int pawnsnum = 0;
next = it.Next ();
@ -1388,11 +1394,11 @@ int G_FinishTravel ()
{
P_FindFloorCeiling(pawn);
}
pawn->target = NULL;
pawn->lastenemy = NULL;
pawn->target = nullptr;
pawn->lastenemy = nullptr;
pawn->player->mo = pawn;
pawn->player->camera = pawn;
pawn->player->viewheight = pawn->ViewHeight;
pawn->player->viewheight = pawn->player->DefaultViewHeight();
pawn->flags2 &= ~MF2_BLASTED;
if (oldpawn != nullptr)
{
@ -1527,11 +1533,12 @@ void G_InitLevelLocals ()
level.DefaultEnvironment = info->DefaultEnvironment;
level.lightmode = info->lightmode == ELightMode::NotSet? (ELightMode)*gl_lightmode : info->lightmode;
level.lightMode = info->lightmode == ELightMode::NotSet? (ELightMode)*gl_lightmode : info->lightmode;
level.brightfog = info->brightfog < 0? gl_brightfog : !!info->brightfog;
level.lightadditivesurfaces = info->lightadditivesurfaces < 0 ? gl_lightadditivesurfaces : !!info->lightadditivesurfaces;
level.notexturefill = info->notexturefill < 0 ? gl_notexturefill : !!info->notexturefill;
FLightDefaults::SetAttenuationForLevel();
}
//==========================================================================
@ -1682,8 +1689,8 @@ void G_UnSnapshotLevel (bool hubLoad)
G_SerializeLevel (arc, hubLoad);
level.FromSnapshot = true;
TThinkerIterator<APlayerPawn> it;
APlayerPawn *pawn, *next;
TThinkerIterator<AActor> it(NAME_PlayerPawn);
AActor *pawn, *next;
next = it.Next();
while ((pawn = next) != 0)
@ -1714,7 +1721,7 @@ void G_UnSnapshotLevel (bool hubLoad)
if (hubLoad)
{
// Unlock ACS global strings that were locked when the snapshot was made.
FBehavior::StaticUnlockLevelVarStrings();
level.Behaviors.UnlockLevelVarStrings(level.levelnum);
}
}
@ -1964,7 +1971,14 @@ void FLevelLocals::Tick ()
void FLevelLocals::Mark()
{
GC::Mark(SpotState);
GC::Mark(FraggleScriptThinker);
GC::Mark(ACSThinker);
canvasTextureInfo.Mark();
for (auto &c : CorpseQueue)
{
GC::Mark(c);
}
for (auto &s : sectorPortals)
{
GC::Mark(s.mSkybox);
@ -2132,7 +2146,7 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, SphericalCoords)
ACTION_RETURN_VEC3(DVector3(
deltaangle(vecTo.Angle(), viewYaw).Degrees,
deltaangle(-vecTo.Pitch(), viewPitch).Degrees,
deltaangle(vecTo.Pitch(), viewPitch).Degrees,
vecTo.Length()
));
}

View file

@ -263,25 +263,6 @@ class DScroller;
class FScanner;
struct level_info_t;
struct FOptionalMapinfoData
{
FOptionalMapinfoData *Next = nullptr;
FName identifier = NAME_None;
virtual ~FOptionalMapinfoData() {}
virtual FOptionalMapinfoData *Clone() const = 0;
};
struct FOptionalMapinfoDataPtr
{
FOptionalMapinfoData *Ptr;
FOptionalMapinfoDataPtr() throw() : Ptr(NULL) {}
~FOptionalMapinfoDataPtr() { if (Ptr!=NULL) delete Ptr; }
FOptionalMapinfoDataPtr(const FOptionalMapinfoDataPtr &p) throw() : Ptr(p.Ptr->Clone()) {}
FOptionalMapinfoDataPtr &operator= (FOptionalMapinfoDataPtr &p) throw() { Ptr = p.Ptr->Clone(); return *this; }
};
typedef TMap<FName, FOptionalMapinfoDataPtr> FOptData;
typedef TMap<int, FName> FMusicMap;
enum EMapType : int
@ -315,18 +296,6 @@ struct FExitText
}
};
enum class ELightMode : int8_t
{
NotSet = -1,
LinearStandard = 0,
DoomBright = 1,
Doom = 2,
DoomDark = 3,
DoomLegacy = 4,
ZDoomSoftware = 8,
DoomSoftware = 16
};
struct level_info_t
{
@ -398,7 +367,6 @@ struct level_info_t
double teamdamage;
FOptData optdata;
FMusicMap MusicMap;
TArray<FSpecialAction> specialactions;
@ -416,6 +384,10 @@ struct level_info_t
FVector3 skyrotatevector;
FVector3 skyrotatevector2;
FString EDName;
FString acsName;
bool fs_nocheckposition;
level_info_t()
{
@ -434,24 +406,6 @@ struct level_info_t
deferred.Clear();
}
level_info_t *CheckLevelRedirect ();
template<class T>
T *GetOptData(FName id, bool create = true)
{
FOptionalMapinfoDataPtr *pdat = optdata.CheckKey(id);
if (pdat != NULL)
{
return static_cast<T*>(pdat->Ptr);
}
else if (create)
{
T *newobj = new T;
optdata[id].Ptr = newobj;
return newobj;
}
else return NULL;
}
};

View file

@ -42,18 +42,25 @@
#include "portal.h"
#include "p_blockmap.h"
#include "p_local.h"
#include "po_man.h"
#include "p_acs.h"
#include "p_destructible.h"
#include "r_data/r_sections.h"
#include "r_data/r_canvastexture.h"
class DACSThinker;
class DFraggleThinker;
class DSpotState;
struct FLevelData
{
TArray<vertex_t> vertexes;
TArray<sector_t> sectors;
TArray<line_t*> linebuffer; // contains the line lists for the sectors.
TArray<subsector_t*> subsectorbuffer; // contains the subsector lists for the sectors.
TArray<line_t> lines;
TArray<side_t> sides;
TArray<seg_t *> segbuffer; // contains the seg links for the sidedefs.
TArray<seg_t> segs;
TArray<subsector_t> subsectors;
TArray<node_t> nodes;
@ -62,6 +69,7 @@ struct FLevelData
node_t *headgamenode;
TArray<uint8_t> rejectmatrix;
TArray<zone_t> Zones;
TArray<FPolyObj> Polyobjects;
TArray<FSectorPortal> sectorPortals;
TArray<FLinePortal> linePortals;
@ -79,6 +87,7 @@ struct FLevelData
TMap<int, FHealthGroup> healthGroups;
FBlockmap blockmap;
TArray<polyblock_t *> PolyBlockMap;
// These are copies of the loaded map data that get used by the savegame code to skip unaltered fields
// Without such a mechanism the savegame format would become too slow and large because more than 80-90% are normally still unaltered.
@ -91,6 +100,7 @@ struct FLevelData
FPlayerStart playerstarts[MAXPLAYERS];
TArray<FPlayerStart> AllPlayerStarts;
FBehaviorContainer Behaviors;
};
struct FLevelLocals : public FLevelData
@ -100,6 +110,8 @@ struct FLevelLocals : public FLevelData
void AddScroller(int secnum);
void SetInterMusic(const char *nextmap);
void SetMusicVolume(float v);
void ClearLevelData();
void ClearPortals();
uint8_t md5[16]; // for savegame validation. If the MD5 does not match the savegame won't be loaded.
int time; // time in the hub
@ -186,10 +198,20 @@ struct FLevelLocals : public FLevelData
float MusicVolume;
// Hardware render stuff that can either be set via CVAR or MAPINFO
ELightMode lightmode;
ELightMode lightMode;
bool brightfog;
bool lightadditivesurfaces;
bool notexturefill;
int ImpactDecalCount;
FDynamicLight *lights;
// links to global game objects
TArray<TObjPtr<AActor *>> CorpseQueue;
TObjPtr<DFraggleThinker *> FraggleScriptThinker = nullptr;
TObjPtr<DACSThinker*> ACSThinker = nullptr;
TObjPtr<DSpotState *> SpotState = nullptr;
bool IsJumpingAllowed() const;
bool IsCrouchingAllowed() const;
@ -210,67 +232,17 @@ struct FLevelLocals : public FLevelData
return savegamerestore
|| (info != nullptr && info->Snapshot.mBuffer != nullptr && info->isValid());
}
bool isSoftwareLighting() const
{
return lightmode >= ELightMode::ZDoomSoftware;
}
bool isDarkLightMode() const
{
return !!((int)lightmode & (int)ELightMode::Doom);
}
void SetFallbackLightMode()
{
lightmode = ELightMode::Doom;
}
};
#ifndef NO_DEFINE_LEVEL
extern FLevelLocals level;
inline int vertex_t::Index() const
{
return int(this - &level.vertexes[0]);
}
inline int side_t::Index() const
{
return int(this - &level.sides[0]);
}
inline int line_t::Index() const
{
return int(this - &level.lines[0]);
}
inline int seg_t::Index() const
{
return int(this - &level.segs[0]);
}
inline int subsector_t::Index() const
{
return int(this - &level.subsectors[0]);
}
inline int node_t::Index() const
{
return int(this - &level.nodes[0]);
}
inline FSectorPortal *line_t::GetTransferredPortal()
{
return portaltransferred >= level.sectorPortals.Size() ? (FSectorPortal*)nullptr : &level.sectorPortals[portaltransferred];
}
inline int sector_t::Index() const
{
return int(this - &level.sectors[0]);
}
inline FSectorPortal *sector_t::GetPortal(int plane)
{
return &level.sectorPortals[Portals[plane]];

View file

@ -1445,6 +1445,34 @@ DEFINE_MAP_OPTION(skyrotate2, false)
info->skyrotatevector2.MakeUnit();
}
DEFINE_MAP_OPTION(fs_nocheckposition, false)
{
if (parse.CheckAssign())
{
parse.sc.MustGetNumber();
info->fs_nocheckposition = !!parse.sc.Number;
}
else
{
info->fs_nocheckposition = true;
}
}
DEFINE_MAP_OPTION(edata, false)
{
parse.ParseAssign();
parse.sc.MustGetString();
info->EDName = parse.sc.String;
}
DEFINE_MAP_OPTION(loadacs, false)
{
parse.ParseAssign();
parse.sc.MustGetString();
info->acsName = parse.sc.String;
}
//==========================================================================
//
// All flag based map options

View file

@ -60,7 +60,7 @@ void A_Unblock(AActor *self, bool drop)
self->Conversation = NULL;
// If the actor has attached metadata for items to drop, drop those.
if (drop && !self->IsKindOf (RUNTIME_CLASS (APlayerPawn))) // [GRB]
if (drop && !self->IsKindOf(NAME_PlayerPawn)) // [GRB]
{
auto di = self->GetDropItems();
@ -88,109 +88,21 @@ void A_Unblock(AActor *self, bool drop)
//
//----------------------------------------------------------------------------
// Corpse queue for monsters - this should be saved out
class DCorpsePointer : public DThinker
{
DECLARE_CLASS (DCorpsePointer, DThinker)
HAS_OBJECT_POINTERS
public:
DCorpsePointer (AActor *ptr);
void Queue();
void OnDestroy() override;
void Serialize(FSerializer &arc);
TObjPtr<AActor*> Corpse;
uint32_t Count; // Only the first corpse pointer's count is valid.
private:
DCorpsePointer () {}
};
IMPLEMENT_CLASS(DCorpsePointer, false, true)
IMPLEMENT_POINTERS_START(DCorpsePointer)
IMPLEMENT_POINTER(Corpse)
IMPLEMENT_POINTERS_END
CUSTOM_CVAR(Int, sv_corpsequeuesize, 64, CVAR_ARCHIVE|CVAR_SERVERINFO)
{
if (self > 0)
{
TThinkerIterator<DCorpsePointer> iterator (STAT_CORPSEPOINTER);
DCorpsePointer *first = iterator.Next ();
while (first != NULL && first->Count > (uint32_t)self)
auto &corpsequeue = level.CorpseQueue;
while (corpsequeue.Size() > (unsigned)self)
{
DCorpsePointer *next = iterator.Next ();
first->Destroy ();
first = next;
AActor *corpse = corpsequeue[0];
if (corpse) corpse->Destroy();
corpsequeue.Delete(0);
}
}
}
DCorpsePointer::DCorpsePointer(AActor *ptr)
: DThinker(STAT_CORPSEPOINTER), Corpse(ptr)
{
Count = 0;
}
void DCorpsePointer::Queue()
{
// Thinkers are added to the end of their respective lists, so
// the first thinker in the list is the oldest one.
TThinkerIterator<DCorpsePointer> iterator (STAT_CORPSEPOINTER);
DCorpsePointer *first = iterator.Next ();
if (first != nullptr)
{
if (first != this)
{
if (first->Count >= (uint32_t)sv_corpsequeuesize)
{
DCorpsePointer *next = iterator.Next();
first->Destroy();
first = next;
}
}
++first->Count;
}
}
void DCorpsePointer::OnDestroy ()
{
// Store the count of corpses in the first thinker in the list
TThinkerIterator<DCorpsePointer> iterator (STAT_CORPSEPOINTER);
DCorpsePointer *first = iterator.Next ();
// During a serialization unwind the thinker list won't be available.
if (first != nullptr)
{
int prevCount = first->Count;
if (first == this)
{
first = iterator.Next();
}
if (first != NULL)
{
first->Count = prevCount - 1;
}
}
if (Corpse != NULL)
{
Corpse->Destroy();
}
Super::OnDestroy();
}
void DCorpsePointer::Serialize(FSerializer &arc)
{
Super::Serialize(arc);
arc("corpse", Corpse)
("count", Count);
}
// throw another corpse on the queue
DEFINE_ACTION_FUNCTION(AActor, A_QueueCorpse)
@ -199,28 +111,28 @@ DEFINE_ACTION_FUNCTION(AActor, A_QueueCorpse)
if (sv_corpsequeuesize > 0)
{
auto p = Create<DCorpsePointer> (self);
p->Queue();
auto &corpsequeue = level.CorpseQueue;
while (corpsequeue.Size() >= (unsigned)sv_corpsequeuesize)
{
AActor *corpse = corpsequeue[0];
if (corpse) corpse->Destroy();
corpsequeue.Delete(0);
}
corpsequeue.Push(self);
}
return 0;
}
// Remove an self from the queue (for resurrection)
// Remove an actor from the queue (for resurrection)
DEFINE_ACTION_FUNCTION(AActor, A_DeQueueCorpse)
{
PARAM_SELF_PROLOGUE(AActor);
TThinkerIterator<DCorpsePointer> iterator (STAT_CORPSEPOINTER);
DCorpsePointer *corpsePtr;
while ((corpsePtr = iterator.Next()) != NULL)
auto &corpsequeue = level.CorpseQueue;
auto index = corpsequeue.FindEx([=](auto &element) { return element == self; });
if (index < corpsequeue.Size())
{
if (corpsePtr->Corpse == self)
{
corpsePtr->Corpse = NULL;
corpsePtr->Destroy ();
return 0;
}
corpsequeue.Delete(index);
}
return 0;
}

View file

@ -45,11 +45,14 @@
#include "g_levellocals.h"
#include "vm.h"
static double DecalWidth, DecalLeft, DecalRight;
static double SpreadZ;
static const DBaseDecal *SpreadSource;
static const FDecalTemplate *SpreadTemplate;
static TArray<side_t *> SpreadStack;
struct SpreadInfo
{
double DecalWidth, DecalLeft, DecalRight;
double SpreadZ;
const DBaseDecal *SpreadSource;
const FDecalTemplate *SpreadTemplate;
TArray<side_t *> SpreadStack;
};
static int ImpactCount;
@ -399,11 +402,11 @@ static side_t *NextWall (const side_t *wall)
return NULL;
}
void DBaseDecal::SpreadLeft (double r, vertex_t *v1, side_t *feelwall, F3DFloor *ffloor)
void DBaseDecal::SpreadLeft (double r, vertex_t *v1, side_t *feelwall, F3DFloor *ffloor, SpreadInfo *spread)
{
double ldx, ldy;
SpreadStack.Push (feelwall);
spread->SpreadStack.Push (feelwall);
while (r < 0 && feelwall->LeftSide != NO_SIDE)
{
@ -415,21 +418,21 @@ void DBaseDecal::SpreadLeft (double r, vertex_t *v1, side_t *feelwall, F3DFloor
feelwall = &level.sides[feelwall->LeftSide];
GetWallStuff (feelwall, v1, ldx, ldy);
double wallsize = Length (ldx, ldy);
r += DecalLeft;
r += spread->DecalLeft;
x += r*ldx / wallsize;
y += r*ldy / wallsize;
r = wallsize + startr;
SpreadSource->CloneSelf (SpreadTemplate, x, y, SpreadZ, feelwall, ffloor);
SpreadStack.Push (feelwall);
spread->SpreadSource->CloneSelf (spread->SpreadTemplate, x, y, spread->SpreadZ, feelwall, ffloor);
spread->SpreadStack.Push (feelwall);
side_t *nextwall = NextWall (feelwall);
if (nextwall != NULL && nextwall->LeftSide != NO_SIDE)
{
int i;
for (i = SpreadStack.Size(); i-- > 0; )
for (i = spread->SpreadStack.Size(); i-- > 0; )
{
if (SpreadStack[i] == nextwall)
if (spread->SpreadStack[i] == nextwall)
break;
}
if (i == -1)
@ -437,18 +440,18 @@ void DBaseDecal::SpreadLeft (double r, vertex_t *v1, side_t *feelwall, F3DFloor
vertex_t *v2;
GetWallStuff (nextwall, v2, ldx, ldy);
SpreadLeft (startr, v2, nextwall, ffloor);
SpreadLeft (startr, v2, nextwall, ffloor, spread);
}
}
}
}
void DBaseDecal::SpreadRight (double r, side_t *feelwall, double wallsize, F3DFloor *ffloor)
void DBaseDecal::SpreadRight (double r, side_t *feelwall, double wallsize, F3DFloor *ffloor, SpreadInfo *spread)
{
vertex_t *v1;
double x, y, ldx, ldy;
SpreadStack.Push (feelwall);
spread->SpreadStack.Push (feelwall);
while (r > wallsize && feelwall->RightSide != NO_SIDE)
{
@ -459,32 +462,33 @@ void DBaseDecal::SpreadRight (double r, side_t *feelwall, double wallsize, F3DFl
{
int i;
for (i = SpreadStack.Size(); i-- > 0; )
for (i = spread->SpreadStack.Size(); i-- > 0; )
{
if (SpreadStack[i] == nextwall)
if (spread->SpreadStack[i] == nextwall)
break;
}
if (i == -1)
{
SpreadRight (r, nextwall, wallsize, ffloor);
SpreadRight (r, nextwall, wallsize, ffloor, spread);
}
}
r = DecalWidth - r + wallsize - DecalLeft;
r = spread->DecalWidth - r + wallsize - spread->DecalLeft;
GetWallStuff (feelwall, v1, ldx, ldy);
x = v1->fX();
y = v1->fY();
wallsize = Length (ldx, ldy);
x -= r*ldx / wallsize;
y -= r*ldy / wallsize;
r = DecalRight - r;
SpreadSource->CloneSelf (SpreadTemplate, x, y, SpreadZ, feelwall, ffloor);
SpreadStack.Push (feelwall);
r = spread->DecalRight - r;
spread->SpreadSource->CloneSelf (spread->SpreadTemplate, x, y, spread->SpreadZ, feelwall, ffloor);
spread->SpreadStack.Push (feelwall);
}
}
void DBaseDecal::Spread (const FDecalTemplate *tpl, side_t *wall, double x, double y, double z, F3DFloor * ffloor)
{
SpreadInfo spread;
FTexture *tex;
vertex_t *v1;
double rorg, ldx, ldy;
@ -499,21 +503,20 @@ void DBaseDecal::Spread (const FDecalTemplate *tpl, side_t *wall, double x, doub
int dwidth = tex->GetDisplayWidth ();
DecalWidth = dwidth * ScaleX;
DecalLeft = tex->GetDisplayLeftOffset() * ScaleX;
DecalRight = DecalWidth - DecalLeft;
SpreadSource = this;
SpreadTemplate = tpl;
SpreadZ = z;
spread.DecalWidth = dwidth * ScaleX;
spread.DecalLeft = tex->GetDisplayLeftOffset() * ScaleX;
spread.DecalRight = spread.DecalWidth - spread.DecalLeft;
spread.SpreadSource = this;
spread.SpreadTemplate = tpl;
spread.SpreadZ = z;
// Try spreading left first
SpreadLeft (rorg - DecalLeft, v1, wall, ffloor);
SpreadStack.Clear ();
SpreadLeft (rorg - spread.DecalLeft, v1, wall, ffloor, &spread);
spread.SpreadStack.Clear ();
// Then try spreading right
SpreadRight (rorg + DecalRight, wall,
Length (wall->linedef->Delta().X, wall->linedef->Delta().Y), ffloor);
SpreadStack.Clear ();
SpreadRight (rorg + spread.DecalRight, wall,
Length (wall->linedef->Delta().X, wall->linedef->Delta().Y), ffloor, &spread);
}
DBaseDecal *DBaseDecal::CloneSelf (const FDecalTemplate *tpl, double ix, double iy, double iz, side_t *wall, F3DFloor * ffloor) const
@ -545,9 +548,9 @@ CUSTOM_CVAR (Int, cl_maxdecals, 1024, CVAR_ARCHIVE)
}
else
{
while (ImpactCount > self)
while (level.ImpactDecalCount > self)
{
DThinker *thinker = DThinker::FirstThinker (STAT_AUTODECAL);
DThinker *thinker = DThinker::FirstThinker(STAT_AUTODECAL);
if (thinker != NULL)
{
thinker->Destroy();
@ -559,23 +562,22 @@ CUSTOM_CVAR (Int, cl_maxdecals, 1024, CVAR_ARCHIVE)
DImpactDecal::DImpactDecal ()
: DBaseDecal (STAT_AUTODECAL, 0.)
{
ImpactCount++;
}
DImpactDecal::DImpactDecal (double z)
: DBaseDecal (STAT_AUTODECAL, z)
{
ImpactCount++;
}
void DImpactDecal::CheckMax ()
{
if (ImpactCount >= cl_maxdecals)
if (++level.ImpactDecalCount >= cl_maxdecals)
{
DThinker *thinker = DThinker::FirstThinker (STAT_AUTODECAL);
if (thinker != NULL)
{
thinker->Destroy();
level.ImpactDecalCount--;
}
}
}
@ -610,7 +612,6 @@ DImpactDecal *DImpactDecal::StaticCreate (const FDecalTemplate *tpl, const DVect
else lowercolor = color;
StaticCreate (tpl_low, pos, wall, ffloor, lowercolor);
}
DImpactDecal::CheckMax();
decal = Create<DImpactDecal>(pos.Z);
if (decal == NULL)
{
@ -621,6 +622,7 @@ DImpactDecal *DImpactDecal::StaticCreate (const FDecalTemplate *tpl, const DVect
{
return NULL;
}
decal->CheckMax();
tpl->ApplyToDecal (decal, wall);
if (color != 0)
@ -646,12 +648,12 @@ DBaseDecal *DImpactDecal::CloneSelf (const FDecalTemplate *tpl, double ix, doubl
return NULL;
}
DImpactDecal::CheckMax();
DImpactDecal *decal = Create<DImpactDecal>(iz);
if (decal != NULL)
{
if (decal->StickToWall (wall, ix, iy, ffloor).isValid())
{
decal->CheckMax();
tpl->ApplyToDecal (decal, wall);
decal->AlphaColor = AlphaColor;
decal->RenderFlags = (decal->RenderFlags & RF_DECALMASK) |
@ -666,12 +668,6 @@ DBaseDecal *DImpactDecal::CloneSelf (const FDecalTemplate *tpl, double ix, doubl
return decal;
}
void DImpactDecal::OnDestroy ()
{
ImpactCount--;
Super::OnDestroy();
}
CCMD (countdecals)
{
Printf ("%d impact decals\n", ImpactCount);

View file

@ -63,7 +63,11 @@
#include "g_levellocals.h"
#include "a_dynlight.h"
#include "actorinlines.h"
#include "memarena.h"
static FMemArena DynLightArena(sizeof(FDynamicLight) * 200);
static TArray<FDynamicLight*> FreeList;
static FRandom randLight;
CUSTOM_CVAR (Bool, gl_lights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
@ -71,8 +75,6 @@ CUSTOM_CVAR (Bool, gl_lights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOIN
else AActor::DeleteAllAttachedLights();
}
CVAR (Bool, gl_attachedlights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
//==========================================================================
//
//==========================================================================
@ -87,105 +89,142 @@ DEFINE_CLASS_PROPERTY(type, S, DynamicLight)
int style = MatchString(str, ltype_names);
if (style < 0) I_Error("Unknown light type '%s'", str);
defaults->lighttype = ltype_values[style];
defaults->IntVar(NAME_lighttype) = ltype_values[style];
}
//==========================================================================
//
// Actor classes
//
// For flexibility all functionality has been packed into a single class
// which is controlled by flags
//
//==========================================================================
IMPLEMENT_CLASS(ADynamicLight, false, false)
DEFINE_FIELD(ADynamicLight, SpotInnerAngle)
DEFINE_FIELD(ADynamicLight, SpotOuterAngle)
static FRandom randLight;
//==========================================================================
//
// Base class
//
//==========================================================================
//==========================================================================
//
//
//
//==========================================================================
void ADynamicLight::Serialize(FSerializer &arc)
static FDynamicLight *GetLight()
{
Super::Serialize (arc);
auto def = static_cast<ADynamicLight*>(GetDefault());
arc("lightflags", lightflags, def->lightflags)
("lighttype", lighttype, def->lighttype)
("tickcount", m_tickCount, def->m_tickCount)
("currentradius", m_currentRadius, def->m_currentRadius)
("spotinnerangle", SpotInnerAngle, def->SpotInnerAngle)
("spotouterangle", SpotOuterAngle, def->SpotOuterAngle);
if (lighttype == PulseLight)
arc("lastupdate", m_lastUpdate, def->m_lastUpdate)
("cycler", m_cycler, def->m_cycler);
// Remap the old flags.
if (SaveVersion < 4552)
FDynamicLight *ret;
if (FreeList.Size())
{
lightflags = 0;
if (flags4 & MF4_MISSILEEVENMORE) lightflags |= LF_SUBTRACTIVE;
if (flags4 & MF4_MISSILEMORE) lightflags |= LF_ADDITIVE;
if (flags4 & MF4_SEESDAGGERS) lightflags |= LF_DONTLIGHTSELF;
if (flags4 & MF4_INCOMBAT) lightflags |= LF_ATTENUATE;
if (flags4 & MF4_STANDSTILL) lightflags |= LF_NOSHADOWMAP;
if (flags4 & MF4_EXTREMEDEATH) lightflags |= LF_DONTLIGHTACTORS;
flags4 &= ~(MF4_SEESDAGGERS); // this flag is dangerous and must be cleared. The others do not matter.
FreeList.Pop(ret);
}
else ret = (FDynamicLight*)DynLightArena.Alloc(sizeof(FDynamicLight));
memset(ret, 0, sizeof(*ret));
ret->next = level.lights;
level.lights = ret;
if (ret->next) ret->next->prev = ret;
ret->visibletoplayer = true;
ret->mShadowmapIndex = 1024;
ret->Pos.X = -10000000; // not a valid coordinate.
return ret;
}
//==========================================================================
//
// Attaches a dynamic light descriptor to a dynamic light actor.
// Owned lights do not use this function.
//
//==========================================================================
void AttachLight(AActor *self)
{
auto light = GetLight();
light->pSpotInnerAngle = &self->AngleVar(NAME_SpotInnerAngle);
light->pSpotOuterAngle = &self->AngleVar(NAME_SpotOuterAngle);
light->pPitch = &self->Angles.Pitch;
light->pLightFlags = (LightFlags*)&self->IntVar(NAME_lightflags);
light->pArgs = self->args;
light->specialf1 = DAngle(double(self->SpawnAngle)).Normalized360().Degrees;
light->Sector = self->Sector;
light->target = self;
light->mShadowmapIndex = 1024;
light->m_active = false;
light->visibletoplayer = true;
light->lighttype = (uint8_t)self->IntVar(NAME_lighttype);
self->AttachedLights.Push(light);
}
DEFINE_ACTION_FUNCTION_NATIVE(ADynamicLight, AttachLight, AttachLight)
{
PARAM_SELF_PROLOGUE(AActor);
AttachLight(self);
return 0;
}
//==========================================================================
//
//
//
//==========================================================================
void ActivateLight(AActor *self)
{
for (auto l : self->AttachedLights) l->Activate();
}
DEFINE_ACTION_FUNCTION_NATIVE(ADynamicLight, ActivateLight, ActivateLight)
{
PARAM_SELF_PROLOGUE(AActor);
ActivateLight(self);
return 0;
}
//==========================================================================
//
//
//
//==========================================================================
void DeactivateLight(AActor *self)
{
for (auto l : self->AttachedLights) l->Deactivate();
}
DEFINE_ACTION_FUNCTION_NATIVE(ADynamicLight, DeactivateLight, DeactivateLight)
{
PARAM_SELF_PROLOGUE(AActor);
DeactivateLight(self);
return 0;
}
//==========================================================================
//
//
//
//==========================================================================
static void SetOffset(AActor *self, double x, double y, double z)
{
for (auto l : self->AttachedLights)
{
l->SetOffset(DVector3(x, y, z));
}
}
void ADynamicLight::PostSerialize()
DEFINE_ACTION_FUNCTION_NATIVE(ADynamicLight, SetOffset, SetOffset)
{
Super::PostSerialize();
// The default constructor which is used for creating objects before deserialization will not set this variable.
// It needs to be true for all placed lights.
visibletoplayer = true;
mShadowmapIndex = 1024;
LinkLight();
PARAM_SELF_PROLOGUE(AActor);
PARAM_FLOAT(x);
PARAM_FLOAT(y);
PARAM_FLOAT(z);
SetOffset(self, x, y, z);
return 0;
}
//==========================================================================
//
// [TS]
//
//
//==========================================================================
void ADynamicLight::BeginPlay()
void FDynamicLight::ReleaseLight()
{
//Super::BeginPlay();
ChangeStatNum(STAT_DLIGHT);
specialf1 = DAngle(double(SpawnAngle)).Normalized360().Degrees;
visibletoplayer = true;
mShadowmapIndex = 1024;
}
//==========================================================================
//
// [TS]
//
//==========================================================================
void ADynamicLight::PostBeginPlay()
{
Super::PostBeginPlay();
if (!(SpawnFlags & MTF_DORMANT))
{
Activate (nullptr);
}
subsector = R_PointInSubsector(Pos());
assert(prev != nullptr || this == level.lights);
if (prev != nullptr) prev->next = next;
else level.lights = next;
if (next != nullptr) next->prev = prev;
next = prev = nullptr;
FreeList.Push(this);
}
@ -194,21 +233,19 @@ void ADynamicLight::PostBeginPlay()
// [TS]
//
//==========================================================================
void ADynamicLight::Activate(AActor *activator)
void FDynamicLight::Activate()
{
//Super::Activate(activator);
flags2&=~MF2_DORMANT;
m_currentRadius = float(args[LIGHT_INTENSITY]);
m_active = true;
m_currentRadius = float(GetIntensity());
m_tickCount = 0;
if (lighttype == PulseLight)
{
float pulseTime = float(specialf1 / TICRATE);
m_lastUpdate = level.maptime;
if (!swapped) m_cycler.SetParams(float(args[LIGHT_SECONDARY_INTENSITY]), float(args[LIGHT_INTENSITY]), pulseTime);
else m_cycler.SetParams(float(args[LIGHT_INTENSITY]), float(args[LIGHT_SECONDARY_INTENSITY]), pulseTime);
if (!swapped) m_cycler.SetParams(float(GetSecondaryIntensity()), float(GetIntensity()), pulseTime);
else m_cycler.SetParams(float(GetIntensity()), float(GetSecondaryIntensity()), pulseTime);
m_cycler.ShouldCycle(true);
m_cycler.SetCycleType(CYCLE_Sin);
m_currentRadius = float(m_cycler.GetVal());
@ -222,28 +259,27 @@ void ADynamicLight::Activate(AActor *activator)
// [TS]
//
//==========================================================================
void ADynamicLight::Deactivate(AActor *activator)
void FDynamicLight::Tick()
{
//Super::Deactivate(activator);
flags2|=MF2_DORMANT;
}
//==========================================================================
//
// [TS]
//
//==========================================================================
void ADynamicLight::Tick()
{
if (IsOwned())
if (!target)
{
if (!target || !target->state)
// How did we get here? :?
ReleaseLight();
return;
}
if (owned)
{
if (!target->state)
{
this->Destroy();
Deactivate();
return;
}
if (target->flags & MF_UNMORPHED)
{
m_active = false;
return;
}
if (target->flags & MF_UNMORPHED) return;
visibletoplayer = target->IsVisibleToPlayer(); // cache this value for the renderer to speed up calculations.
}
@ -266,25 +302,23 @@ void ADynamicLight::Tick()
case FlickerLight:
{
int rnd = randLight();
float pct = float(specialf1 / 360.f);
m_currentRadius = float(args[LIGHT_INTENSITY + (rnd >= pct * 255)]);
int rnd = randLight(360);
m_currentRadius = float((rnd < int(specialf1))? GetIntensity() : GetSecondaryIntensity());
break;
}
case RandomFlickerLight:
{
int flickerRange = args[LIGHT_SECONDARY_INTENSITY] - args[LIGHT_INTENSITY];
int flickerRange = GetSecondaryIntensity() - GetIntensity();
float amt = randLight() / 255.f;
if (m_tickCount > specialf1)
{
m_tickCount = 0;
}
if (m_tickCount++ == 0 || m_currentRadius > args[LIGHT_SECONDARY_INTENSITY])
if (m_tickCount++ == 0 || m_currentRadius > GetSecondaryIntensity())
{
m_currentRadius = float(args[LIGHT_INTENSITY] + (amt * flickerRange));
m_currentRadius = float(GetIntensity() + (amt * flickerRange));
}
break;
}
@ -302,14 +336,14 @@ void ADynamicLight::Tick()
case RandomColorFlickerLight:
{
int flickerRange = args[LIGHT_SECONDARY_INTENSITY] - args[LIGHT_INTENSITY];
int flickerRange = GetSecondaryIntensity() - GetIntensity();
float amt = randLight() / 255.f;
m_tickCount++;
if (m_tickCount > specialf1)
{
m_currentRadius = args[LIGHT_INTENSITY] + (amt * flickerRange);
m_currentRadius = GetIntensity() + (amt * flickerRange);
m_tickCount = 0;
}
break;
@ -319,7 +353,7 @@ void ADynamicLight::Tick()
case SectorLight:
{
float intensity;
float scale = args[LIGHT_SCALE] / 8.f;
float scale = GetIntensity() / 8.f;
if (scale == 0.f) scale = 1.f;
@ -331,7 +365,7 @@ void ADynamicLight::Tick()
}
case PointLight:
m_currentRadius = float(args[LIGHT_INTENSITY]);
m_currentRadius = float(GetIntensity());
break;
}
if (m_currentRadius <= 0) m_currentRadius = 1;
@ -346,45 +380,37 @@ void ADynamicLight::Tick()
//
//
//==========================================================================
void ADynamicLight::UpdateLocation()
void FDynamicLight::UpdateLocation()
{
double oldx= X();
double oldy= Y();
double oldradius= radius;
float intensity;
float oldradius = radius;
if (IsActive())
{
if (target)
{
DAngle angle = target->Angles.Yaw;
double s = angle.Sin();
double c = angle.Cos();
AActor *target = this->target; // perform the read barrier only once.
DVector3 pos = target->Vec3Offset(m_off.X * c + m_off.Y * s, m_off.X * s - m_off.Y * c, m_off.Z + target->GetBobOffset());
SetXYZ(pos); // attached lights do not need to go into the regular blockmap
Prev = target->Pos();
subsector = R_PointInSubsector(Prev);
Sector = subsector->sector;
// Offset is calculated in relation to the owning actor.
DAngle angle = target->Angles.Yaw;
double s = angle.Sin();
double c = angle.Cos();
// Some z-coordinate fudging to prevent the light from getting too close to the floor or ceiling planes. With proper attenuation this would render them invisible.
// A distance of 5 is needed so that the light's effect doesn't become too small.
if (Z() < target->floorz + 5.) SetZ(target->floorz + 5.);
else if (Z() > target->ceilingz - 5.) SetZ(target->ceilingz - 5.);
}
else
{
if (Z() < floorz + 5.) SetZ(floorz + 5.);
else if (Z() > ceilingz - 5.) SetZ(ceilingz - 5.);
}
Pos = target->Vec3Offset(m_off.X * c + m_off.Y * s, m_off.X * s - m_off.Y * c, m_off.Z + target->GetBobOffset());
Sector = target->subsector->sector; // Get the render sector. target->Sector is the sector according to play logic.
// Some z-coordinate fudging to prevent the light from getting too close to the floor or ceiling planes. With proper attenuation this would render them invisible.
// A distance of 5 is needed so that the light's effect doesn't become too small.
if (Z() < target->floorz + 5.) Pos.Z = target->floorz + 5.;
else if (Z() > target->ceilingz - 5.) Pos.Z = target->ceilingz - 5.;
// The radius being used here is always the maximum possible with the
// current settings. This avoids constant relinking of flickering lights
float intensity;
if (lighttype == FlickerLight || lighttype == RandomFlickerLight || lighttype == PulseLight)
{
intensity = float(MAX(args[LIGHT_INTENSITY], args[LIGHT_SECONDARY_INTENSITY]));
intensity = float(MAX(GetIntensity(), GetSecondaryIntensity()));
}
else
{
@ -401,60 +427,6 @@ void ADynamicLight::UpdateLocation()
}
}
//==========================================================================
//
//
//
//==========================================================================
void ADynamicLight::SetOrigin(double x, double y, double z, bool moving)
{
Super::SetOrigin(x, y, z, moving);
LinkLight();
}
//==========================================================================
//
//
//
//==========================================================================
void ADynamicLight::SetOffset(const DVector3 &pos)
{
m_off = pos;
UpdateLocation();
}
static void SetOffset(ADynamicLight *self, const DVector3 &pos)
{
self->SetOffset(pos);
}
DEFINE_ACTION_FUNCTION_NATIVE(ADynamicLight, SetOffset, SetOffset)
{
PARAM_SELF_PROLOGUE(ADynamicLight)
PARAM_FLOAT(x)
PARAM_FLOAT(y)
PARAM_FLOAT(z)
self->SetOffset(DVector3(x, y, z));
return 0;
}
//==========================================================================
//
// The target pointer in dynamic lights should never be substituted unless
// notOld is nullptr (which indicates that the object was destroyed by force.)
//
//==========================================================================
size_t ADynamicLight::PointerSubstitution (DObject *old, DObject *notOld)
{
AActor *saved_target = target;
size_t ret = Super::PointerSubstitution(old, notOld);
if (notOld != nullptr) target = saved_target;
return ret;
}
//=============================================================================
//
// These have been copied from the secnode code and modified for the light links
@ -466,7 +438,7 @@ size_t ADynamicLight::PointerSubstitution (DObject *old, DObject *notOld)
//
//=============================================================================
FLightNode * AddLightNode(FLightNode ** thread, void * linkto, ADynamicLight * light, FLightNode *& nextnode)
FLightNode * AddLightNode(FLightNode ** thread, void * linkto, FDynamicLight * light, FLightNode *& nextnode)
{
FLightNode * node;
@ -541,7 +513,7 @@ static FLightNode * DeleteLightNode(FLightNode * node)
//
//==========================================================================
double ADynamicLight::DistToSeg(const DVector3 &pos, vertex_t *start, vertex_t *end)
double FDynamicLight::DistToSeg(const DVector3 &pos, vertex_t *start, vertex_t *end)
{
double u, px, py;
@ -576,7 +548,7 @@ struct LightLinkEntry
};
static TArray<LightLinkEntry> collected_ss;
void ADynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section, float radius)
void FDynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section, float radius)
{
if (!section) return;
collected_ss.Clear();
@ -621,7 +593,7 @@ void ADynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section,
if (othersect->validcount != ::validcount)
{
othersect->validcount = ::validcount;
collected_ss.Push({ othersect, PosRelative(other) });
collected_ss.Push({ othersect, PosRelative(other->frontsector->PortalGroup) });
}
}
}
@ -672,7 +644,7 @@ void ADynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section,
if (othersect->validcount != dl_validcount)
{
othersect->validcount = dl_validcount;
collected_ss.Push({ othersect, PosRelative(othersub->sector) });
collected_ss.Push({ othersect, PosRelative(othersub->sector->PortalGroup) });
}
}
}
@ -687,12 +659,12 @@ void ADynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section,
if (othersect->validcount != dl_validcount)
{
othersect->validcount = dl_validcount;
collected_ss.Push({ othersect, PosRelative(othersub->sector) });
collected_ss.Push({ othersect, PosRelative(othersub->sector->PortalGroup) });
}
}
}
}
shadowmapped = hitonesidedback && !(lightflags & LF_NOSHADOWMAP);
shadowmapped = hitonesidedback && !DontShadowmap();
}
//==========================================================================
@ -701,7 +673,7 @@ void ADynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section,
//
//==========================================================================
void ADynamicLight::LinkLight()
void FDynamicLight::LinkLight()
{
// mark the old light nodes
FLightNode * node;
@ -722,11 +694,11 @@ void ADynamicLight::LinkLight()
if (radius>0)
{
// passing in radius*radius allows us to do a distance check without any calls to sqrt
FSection *sect = R_PointInSubsector(Pos())->section;
FSection *sect = R_PointInSubsector(Pos)->section;
dl_validcount++;
::validcount++;
CollectWithinRadius(Pos(), sect, float(radius*radius));
CollectWithinRadius(Pos, sect, float(radius*radius));
}
@ -762,32 +734,13 @@ void ADynamicLight::LinkLight()
// Deletes the link lists
//
//==========================================================================
void ADynamicLight::UnlinkLight ()
void FDynamicLight::UnlinkLight ()
{
if (owned && target != nullptr)
{
// Delete reference in owning actor
for(int c=target->AttachedLights.Size()-1; c>=0; c--)
{
if (target->AttachedLights[c] == this)
{
target->AttachedLights.Delete(c);
break;
}
}
}
while (touching_sides) touching_sides = DeleteLightNode(touching_sides);
while (touching_sector) touching_sector = DeleteLightNode(touching_sector);
shadowmapped = false;
}
void ADynamicLight::OnDestroy()
{
UnlinkLight();
Super::OnDestroy();
}
//==========================================================================
//
//
@ -796,23 +749,19 @@ void ADynamicLight::OnDestroy()
void AActor::AttachLight(unsigned int count, const FLightDefaults *lightdef)
{
ADynamicLight *light;
FDynamicLight *light;
if (count < AttachedLights.Size())
{
light = barrier_cast<ADynamicLight*>(AttachedLights[count]);
light = AttachedLights[count];
assert(light != nullptr);
}
else
{
light = Spawn<ADynamicLight>(Pos(), NO_REPLACE);
light->target = this;
light->owned = true;
light->ObjectFlags |= OF_Transient;
//light->lightflags |= LF_ATTENUATE;
light = GetLight();
light->SetActor(this, true);
AttachedLights.Push(light);
}
light->flags2&=~MF2_DORMANT;
lightdef->ApplyProperties(light);
}
@ -831,11 +780,8 @@ void AActor::SetDynamicLights()
if (state == nullptr) return;
if (LightAssociations.Size() > 0)
{
ADynamicLight *lights, *tmpLight;
unsigned int i;
lights = tmpLight = nullptr;
for (i = 0; i < LightAssociations.Size(); i++)
{
if (LightAssociations[i]->Sprite() == sprite &&
@ -858,24 +804,24 @@ void AActor::SetDynamicLights()
for(;count<AttachedLights.Size();count++)
{
AttachedLights[count]->flags2 |= MF2_DORMANT;
memset(AttachedLights[count]->args, 0, 3*sizeof(args[0]));
AttachedLights[count]->Deactivate();
}
}
//==========================================================================
//
// Needed for garbage collection
//
//
//==========================================================================
size_t AActor::PropagateMark()
void AActor::DeleteAttachedLights()
{
for (unsigned i = 0; i<AttachedLights.Size(); i++)
for (auto l : AttachedLights)
{
GC::Mark(AttachedLights[i]);
l->UnlinkLight();
l->ReleaseLight();
}
return Super::PropagateMark();
AttachedLights.Clear();
}
//==========================================================================
@ -888,21 +834,10 @@ void AActor::DeleteAllAttachedLights()
{
TThinkerIterator<AActor> it;
AActor * a;
ADynamicLight * l;
while ((a=it.Next()))
{
a->AttachedLights.Clear();
}
TThinkerIterator<ADynamicLight> it2;
l=it2.Next();
while (l)
{
ADynamicLight * ll = it2.Next();
if (l->owned) l->Destroy();
l=ll;
a->DeleteAttachedLights();
}
}
@ -919,7 +854,18 @@ void AActor::RecreateAllAttachedLights()
while ((a=it.Next()))
{
a->SetDynamicLights();
if (!a->IsKindOf(NAME_DynamicLight))
{
a->SetDynamicLights();
}
else if (a->AttachedLights.Size() == 0)
{
::AttachLight(a);
if (!(a->flags2 & MF2_DORMANT))
{
::ActivateLight(a);
}
}
}
}
@ -934,17 +880,16 @@ CCMD(listlights)
int walls, sectors;
int allwalls=0, allsectors=0, allsubsecs = 0;
int i=0, shadowcount = 0;
ADynamicLight * dl;
TThinkerIterator<ADynamicLight> it;
FDynamicLight * dl;
while ((dl=it.Next()))
for (dl = level.lights; dl; dl = dl->next)
{
walls=0;
sectors=0;
Printf("%s at (%f, %f, %f), color = 0x%02x%02x%02x, radius = %f %s %s",
dl->target? dl->target->GetClass()->TypeName.GetChars() : dl->GetClass()->TypeName.GetChars(),
dl->X(), dl->Y(), dl->Z(), dl->args[LIGHT_RED],
dl->args[LIGHT_GREEN], dl->args[LIGHT_BLUE], dl->radius, (dl->lightflags & LF_ATTENUATE)? "attenuated" : "", dl->shadowmapped? "shadowmapped" : "");
dl->target->GetClass()->TypeName.GetChars(),
dl->X(), dl->Y(), dl->Z(), dl->GetRed(), dl->GetGreen(), dl->GetBlue(),
dl->radius, dl->IsAttenuated()? "attenuated" : "", dl->shadowmapped? "shadowmapped" : "");
i++;
shadowcount += dl->shadowmapped;
@ -981,4 +926,3 @@ CCMD(listlights)
Printf("%i dynamic lights, %d shadowmapped, %d walls, %d sectors\n\n\n", i, shadowcount, allwalls, allsectors);
}

View file

@ -2,15 +2,14 @@
#include "c_cvars.h"
#include "actor.h"
#include "cycler.h"
#include "g_levellocals.h"
EXTERN_CVAR(Bool, r_dynlights)
EXTERN_CVAR(Bool, gl_lights)
EXTERN_CVAR(Bool, gl_attachedlights)
struct side_t;
struct seg_t;
class ADynamicLight;
class FSerializer;
struct FSectionLine;
@ -34,7 +33,6 @@ enum
LIGHT_BLUE = 2,
LIGHT_INTENSITY = 3,
LIGHT_SECONDARY_INTENSITY = 4,
LIGHT_SCALE = 3,
};
enum LightFlag
@ -48,6 +46,9 @@ enum LightFlag
LF_SPOT = 64
};
typedef TFlags<LightFlag> LightFlags;
DEFINE_TFLAGS_OPERATORS(LightFlags)
//==========================================================================
//
// Light definitions
@ -58,22 +59,23 @@ class FLightDefaults
public:
FLightDefaults(FName name, ELightType type);
void ApplyProperties(ADynamicLight * light) const;
void ApplyProperties(FDynamicLight * light) const;
FName GetName() const { return m_Name; }
void SetParameter(double p) { m_Param = p; }
void SetArg(int arg, int val) { m_Args[arg] = val; }
int GetArg(int arg) { return m_Args[arg]; }
uint8_t GetAttenuate() const { return m_attenuate; }
void SetOffset(float* ft) { m_Pos.X = ft[0]; m_Pos.Z = ft[1]; m_Pos.Y = ft[2]; }
void SetSubtractive(bool subtract) { m_subtractive = subtract; }
void SetAdditive(bool add) { m_additive = add; }
void SetDontLightSelf(bool add) { m_dontlightself = add; }
void SetAttenuate(bool on) { m_attenuate = on; }
void SetHalo(bool halo) { m_halo = halo; }
void SetDontLightActors(bool on) { m_dontlightactors = on; }
void SetSpot(bool spot) { m_spot = spot; }
void SetSubtractive(bool subtract) { if (subtract) m_lightFlags |= LF_SUBTRACTIVE; else m_lightFlags &= ~LF_SUBTRACTIVE; }
void SetAdditive(bool add) { if (add) m_lightFlags |= LF_ADDITIVE; else m_lightFlags &= ~LF_ADDITIVE; }
void SetDontLightSelf(bool add) { if (add) m_lightFlags |= LF_DONTLIGHTSELF; else m_lightFlags &= ~LF_DONTLIGHTSELF; }
void SetAttenuate(bool on) { m_attenuate = on; if (on) m_lightFlags |= LF_ATTENUATE; else m_lightFlags &= ~LF_ATTENUATE; }
void SetDontLightActors(bool on) { if (on) m_lightFlags |= LF_DONTLIGHTACTORS; else m_lightFlags &= ~LF_DONTLIGHTACTORS; }
void SetNoShadowmap(bool on) { if (on) m_lightFlags |= LF_NOSHADOWMAP; else m_lightFlags &= ~LF_NOSHADOWMAP; }
void SetSpot(bool spot) { if (spot) m_lightFlags |= LF_SPOT; else m_lightFlags &= ~LF_SPOT; }
void SetSpotInnerAngle(double angle) { m_spotInnerAngle = angle; }
void SetSpotOuterAngle(double angle) { m_spotOuterAngle = angle; }
static void SetAttenuationForLevel();
void OrderIntensities()
{
@ -91,15 +93,13 @@ protected:
DVector3 m_Pos = { 0,0,0 };
ELightType m_type;
int8_t m_attenuate = -1;
bool m_subtractive = false;
bool m_additive = false;
bool m_halo = false;
bool m_dontlightself = false;
bool m_dontlightactors = false;
LightFlags m_lightFlags = 0;
bool m_swapped = false;
bool m_spot = false;
double m_spotInnerAngle = 10.0;
double m_spotOuterAngle = 25.0;
bool m_explicitPitch = false;
DAngle m_spotInnerAngle = 10.0;
DAngle m_spotOuterAngle = 25.0;
DAngle m_pitch = 0.0;
};
//==========================================================================
@ -148,18 +148,13 @@ protected:
};
typedef TFlags<LightFlag> LightFlags;
DEFINE_TFLAGS_OPERATORS(LightFlags)
struct FLightNode
{
FLightNode ** prevTarget;
FLightNode * nextTarget;
FLightNode ** prevLight;
FLightNode * nextLight;
ADynamicLight * lightsource;
FDynamicLight * lightsource;
union
{
side_t * targLine;
@ -168,72 +163,89 @@ struct FLightNode
};
};
//
// Base class
//
// [CO] I merged everything together in this one class so that I don't have
// to create and re-create an excessive amount of objects
//
class ADynamicLight : public AActor
struct FDynamicLight
{
friend class FLightDefaults;
DECLARE_CLASS(ADynamicLight, AActor)
public:
virtual void Tick();
void Serialize(FSerializer &arc);
void PostSerialize();
uint8_t GetRed() const { return args[LIGHT_RED]; }
uint8_t GetGreen() const { return args[LIGHT_GREEN]; }
uint8_t GetBlue() const { return args[LIGHT_BLUE]; }
inline DVector3 PosRelative(int portalgroup) const
{
return Pos + level.Displacements.getOffset(Sector->PortalGroup, portalgroup);
}
bool ShouldLightActor(AActor *check)
{
return visibletoplayer && IsActive() && (!((*pLightFlags) & LF_DONTLIGHTSELF) || target != check) && !((*pLightFlags) & LF_DONTLIGHTACTORS);
}
void SetOffset(const DVector3 &pos)
{
m_off = pos;
}
bool IsActive() const { return m_active; }
float GetRadius() const { return (IsActive() ? m_currentRadius * 2.f : 0.f); }
int GetRed() const { return pArgs[LIGHT_RED]; }
int GetGreen() const { return pArgs[LIGHT_GREEN]; }
int GetBlue() const { return pArgs[LIGHT_BLUE]; }
int GetIntensity() const { return pArgs[LIGHT_INTENSITY]; }
int GetSecondaryIntensity() const { return pArgs[LIGHT_SECONDARY_INTENSITY]; }
bool IsSubtractive() const { return !!((*pLightFlags) & LF_SUBTRACTIVE); }
bool IsAdditive() const { return !!((*pLightFlags) & LF_ADDITIVE); }
bool IsSpot() const { return !!((*pLightFlags) & LF_SPOT); }
bool IsAttenuated() const { return !!((*pLightFlags) & LF_ATTENUATE); }
bool DontShadowmap() const { return !!((*pLightFlags) & LF_NOSHADOWMAP); }
bool DontLightSelf() const { return !!((*pLightFlags) & (LF_DONTLIGHTSELF|LF_DONTLIGHTACTORS)); } // dontlightactors implies dontlightself.
bool DontLightActors() const { return !!((*pLightFlags) & LF_DONTLIGHTACTORS); }
void Deactivate() { m_active = false; }
void Activate();
void SetActor(AActor *ac, bool isowned) { target = ac; owned = isowned; }
double X() const { return Pos.X; }
double Y() const { return Pos.Y; }
double Z() const { return Pos.Z; }
void Tick();
void UpdateLocation();
void LinkLight();
void UnlinkLight();
size_t PointerSubstitution(DObject *old, DObject *notOld);
void BeginPlay();
void SetOrigin(double x, double y, double z, bool moving = false);
void PostBeginPlay();
void OnDestroy() override;
void Activate(AActor *activator);
void Deactivate(AActor *activator);
void SetOffset(const DVector3 &pos);
void UpdateLocation();
bool IsOwned() const { return owned; }
bool IsActive() const { return !(flags2&MF2_DORMANT); }
bool IsSubtractive() { return !!(lightflags & LF_SUBTRACTIVE); }
bool IsAdditive() { return !!(lightflags & LF_ADDITIVE); }
bool IsSpot() { return !!(lightflags & LF_SPOT); }
FState *targetState;
FLightNode * touching_sides;
FLightNode * touching_sector;
void ReleaseLight();
private:
double DistToSeg(const DVector3 &pos, vertex_t *start, vertex_t *end);
void CollectWithinRadius(const DVector3 &pos, FSection *section, float radius);
protected:
DVector3 m_off;
float m_currentRadius;
unsigned int m_lastUpdate;
FCycler m_cycler;
subsector_t * subsector;
public:
FCycler m_cycler;
DVector3 Pos;
DVector3 m_off;
// This date can either come from the owning actor or from a light definition
// To avoid having to copy these around every tic, these are pointers to the source data.
const DAngle *pSpotInnerAngle;
const DAngle *pSpotOuterAngle;
const DAngle *pPitch; // This is to handle pitch overrides through GLDEFS, it can either point to the target's pitch or the light definition.
const int *pArgs;
const LightFlags *pLightFlags;
double specialf1;
FDynamicLight *next, *prev;
sector_t *Sector;
TObjPtr<AActor *> target;
FLightNode * touching_sides;
FLightNode * touching_sector;
float radius; // The maximum size the light can be with its current settings.
float m_currentRadius; // The current light size.
int m_tickCount;
int m_lastUpdate;
int mShadowmapIndex;
bool m_active;
bool visibletoplayer;
bool shadowmapped;
uint8_t lighttype;
bool owned;
bool halo;
uint8_t color2[3];
bool visibletoplayer;
bool swapped;
bool shadowmapped;
int bufferindex;
LightFlags lightflags;
DAngle SpotInnerAngle;
DAngle SpotOuterAngle;
int mShadowmapIndex;
bool explicitpitch;
};

View file

@ -43,14 +43,10 @@ IMPLEMENT_POINTERS_START(DFlashFader)
IMPLEMENT_POINTER(ForWho)
IMPLEMENT_POINTERS_END
DFlashFader::DFlashFader ()
{
}
DFlashFader::DFlashFader (float r1, float g1, float b1, float a1,
float r2, float g2, float b2, float a2,
float time, AActor *who, bool terminate)
: TotalTics ((int)(time*TICRATE)), StartTic (level.time), ForWho (who)
: TotalTics ((int)(time*TICRATE)), RemainingTics(TotalTics), ForWho (who)
{
Blends[0][0]=r1; Blends[0][1]=g1; Blends[0][2]=b1; Blends[0][3]=a1;
Blends[1][0]=r2; Blends[1][1]=g2; Blends[1][2]=b2; Blends[1][3]=a2;
@ -68,7 +64,7 @@ void DFlashFader::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc("totaltics", TotalTics)
("starttic", StartTic)
("remainingtics", RemainingTics)
("forwho", ForWho)
.Array("blends", Blends[0], 8);
}
@ -80,13 +76,13 @@ void DFlashFader::Tick ()
Destroy ();
return;
}
if (level.time >= StartTic+TotalTics)
if (--RemainingTics <= 0)
{
SetBlend (1.f);
Destroy ();
return;
}
SetBlend ((float)(level.time - StartTic) / (float)TotalTics);
SetBlend (1.f - (float)RemainingTics / (float)TotalTics);
}
void DFlashFader::SetBlend (float time)
@ -105,6 +101,6 @@ void DFlashFader::SetBlend (float time)
void DFlashFader::Cancel ()
{
TotalTics = level.time - StartTic;
RemainingTics = 0;
Blends[1][3] = 0.f;
}

View file

@ -157,7 +157,7 @@ void DLightningThinker::LightningFlash ()
// [ZZ] just in case
E_WorldLightning();
// start LIGHTNING scripts
FBehavior::StaticStartTypedScripts (SCRIPT_Lightning, NULL, false); // [RH] Run lightning scripts
level.Behaviors.StartTypedScripts (SCRIPT_Lightning, NULL, false); // [RH] Run lightning scripts
// Calculate the next lighting flash
if (!NextLightningFlash)

View file

@ -19,23 +19,9 @@
//
#include "info.h"
#include "a_pickups.h"
#include "p_local.h"
#include "gi.h"
#include "a_sharedglobal.h"
#include "sbar.h"
#include "a_morph.h"
#include "doomstat.h"
#include "serializer.h"
#include "p_enemy.h"
#include "d_player.h"
#include "r_data/sprites.h"
#include "g_levellocals.h"
#include "actor.h"
#include "vm.h"
static FRandom pr_morphmonst ("MorphMonster");
bool P_MorphActor(AActor *activator, AActor *victim, PClassActor *ptype, PClassActor *mtype, int duration, int style, PClassActor *enter_flash, PClassActor *exit_flash)
{
IFVIRTUALPTR(victim, AActor, Morph)

View file

@ -9,6 +9,7 @@ struct vertex_t;
struct side_t;
struct F3DFloor;
class DBaseDecal;
struct SpreadInfo;
class DBaseDecal *ShootDecal(const FDecalTemplate *tpl, AActor *basisactor, sector_t *sec, double x, double y, double z, DAngle angle, double tracedist, bool permanent);
void SprayDecal(AActor *shooter, const char *name,double distance = 172.);
@ -52,8 +53,8 @@ protected:
void CalcFracPos(side_t *wall, double x, double y);
void Remove ();
static void SpreadLeft (double r, vertex_t *v1, side_t *feelwall, F3DFloor *ffloor);
static void SpreadRight (double r, side_t *feelwall, double wallsize, F3DFloor *ffloor);
static void SpreadLeft (double r, vertex_t *v1, side_t *feelwall, F3DFloor *ffloor, SpreadInfo *spread);
static void SpreadRight (double r, side_t *feelwall, double wallsize, F3DFloor *ffloor, SpreadInfo *spread);
};
class DImpactDecal : public DBaseDecal
@ -67,11 +68,10 @@ public:
static DImpactDecal *StaticCreate(const FDecalTemplate *tpl, const DVector3 &pos, side_t *wall, F3DFloor * ffloor, PalEntry color = 0);
void BeginPlay ();
void OnDestroy() override;
protected:
DBaseDecal *CloneSelf(const FDecalTemplate *tpl, double x, double y, double z, side_t *wall, F3DFloor * ffloor) const;
static void CheckMax ();
void CheckMax ();
private:
DImpactDecal();
@ -95,11 +95,11 @@ public:
protected:
float Blends[2][4];
int TotalTics;
int StartTic;
int RemainingTics;
TObjPtr<AActor*> ForWho;
bool Terminate;
void SetBlend (float time);
DFlashFader ();
DFlashFader() = default;
};
enum

View file

@ -42,7 +42,6 @@
static FRandom pr_spot ("SpecialSpot");
IMPLEMENT_CLASS(DSpotState, false, false)
TObjPtr<DSpotState*> DSpotState::SpotState;
//----------------------------------------------------------------------------
//
@ -198,16 +197,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FSpotList &list, FSpot
//----------------------------------------------------------------------------
DSpotState::DSpotState ()
: DThinker (STAT_INFO)
{
if (SpotState)
{
I_Error ("Only one SpotState is allowed to exist at a time.\nCheck your code.");
}
else
{
SpotState = this;
}
}
//----------------------------------------------------------------------------
@ -219,8 +209,6 @@ DSpotState::DSpotState ()
void DSpotState::OnDestroy ()
{
SpotLists.Reset();
SpotState = NULL;
Super::OnDestroy();
}
@ -240,18 +228,6 @@ void DSpotState::Tick ()
//
//----------------------------------------------------------------------------
DSpotState *DSpotState::GetSpotState(bool create)
{
if (SpotState == NULL && create) SpotState = Create<DSpotState>();
return SpotState;
}
//----------------------------------------------------------------------------
//
//
//
//----------------------------------------------------------------------------
FSpotList *DSpotState::FindSpotList(PClassActor *type)
{
if (type == nullptr) return nullptr;

View file

@ -7,10 +7,9 @@
struct FSpotList;
class DSpotState : public DThinker
class DSpotState : public DObject
{
DECLARE_CLASS(DSpotState, DThinker)
static TObjPtr<DSpotState*> SpotState;
DECLARE_CLASS(DSpotState, DObject)
TArray<FSpotList> SpotLists;
public:

View file

@ -251,7 +251,6 @@ struct FMugShotState
TArray<FMugShotFrame> Frames;
FMugShotState(FName name);
~FMugShotState();
void Tick();
void Reset();
FMugShotFrame &GetCurrentFrame() { return Frames[Position]; }
@ -454,6 +453,7 @@ public:
void RefreshBackground () const;
void RefreshViewBorder ();
private:
DObject *AltHud = nullptr;

View file

@ -126,16 +126,6 @@ FMugShotState::FMugShotState(FName name)
Random = M_Random();
}
//===========================================================================
//
// MugShotState destructor
//
//===========================================================================
FMugShotState::~FMugShotState()
{
}
//===========================================================================
//
// FMugShotState :: Tick
@ -471,7 +461,7 @@ FTexture *FMugShot::GetFace(player_t *player, const char *default_face, int accu
{
int angle = UpdateState(player, stateflags);
int level = 0;
int max = player->mo->MugShotMaxHealth;
int max = player->mo->IntVar(NAME_MugShotMaxHealth);
if (max < 0)
{
max = player->mo->GetMaxHealth();
@ -487,7 +477,7 @@ FTexture *FMugShot::GetFace(player_t *player, const char *default_face, int accu
if (CurrentState != NULL)
{
int skin = player->userinfo.GetSkin();
const char *skin_face = (stateflags & FMugShot::CUSTOM) ? nullptr : (player->morphTics ? ((APlayerPawn*)GetDefaultByType(player->MorphedPlayerClass))->Face.GetChars() : Skins[skin].Face.GetChars());
const char *skin_face = (stateflags & FMugShot::CUSTOM) ? nullptr : (player->morphTics ? (GetDefaultByType(player->MorphedPlayerClass))->NameVar(NAME_Face).GetChars() : Skins[skin].Face.GetChars());
return CurrentState->GetCurrentFrameTexture(default_face, skin_face, level, angle);
}
return NULL;

View file

@ -241,7 +241,7 @@ class CommandDrawImage : public SBarInfoCommandFlowControl
applyscale = false;
}
if(type == PLAYERICON)
texture = TexMan.GetTexture(statusBar->CPlayer->mo->ScoreIcon, true);
texture = TexMan.ByIndex(statusBar->CPlayer->mo->IntVar(NAME_ScoreIcon), true);
else if(type == AMMO1)
{
auto ammo = statusBar->ammo1;
@ -293,8 +293,8 @@ class CommandDrawImage : public SBarInfoCommandFlowControl
}
else if(type == INVENTORYICON)
texture = TexMan.GetTexture(sprite, true);
else if(type == SELECTEDINVENTORYICON && statusBar->CPlayer->mo->InvSel != NULL)
texture = TexMan.GetTexture(statusBar->CPlayer->mo->InvSel->TextureIDVar(NAME_Icon), true);
else if(type == SELECTEDINVENTORYICON && statusBar->CPlayer->mo->PointerVar<AActor>(NAME_InvSel) != NULL)
texture = TexMan.GetTexture(statusBar->CPlayer->mo->PointerVar<AActor>(NAME_InvSel)->TextureIDVar(NAME_Icon), true);
else if(image >= 0)
texture = statusBar->Images[image];
@ -892,7 +892,7 @@ class CommandDrawString : public SBarInfoCommand
SetStringToTag(statusBar->CPlayer->ReadyWeapon);
break;
case INVENTORYTAG:
SetStringToTag(statusBar->CPlayer->mo->InvSel);
SetStringToTag(statusBar->CPlayer->mo->PointerVar<AActor>(NAME_InvSel));
break;
case PLAYERNAME:
// Can't think of a good way to detect changes to this, so
@ -904,7 +904,7 @@ class CommandDrawString : public SBarInfoCommand
if(ACS_GlobalVars[valueArgument] != cache)
{
cache = ACS_GlobalVars[valueArgument];
str = FBehavior::StaticLookupString(ACS_GlobalVars[valueArgument]);
str = level.Behaviors.LookupString(ACS_GlobalVars[valueArgument]);
RealignString();
}
break;
@ -912,7 +912,7 @@ class CommandDrawString : public SBarInfoCommand
if(ACS_GlobalArrays[valueArgument][consoleplayer] != cache)
{
cache = ACS_GlobalArrays[valueArgument][consoleplayer];
str = FBehavior::StaticLookupString(ACS_GlobalArrays[valueArgument][consoleplayer]);
str = level.Behaviors.LookupString(ACS_GlobalArrays[valueArgument][consoleplayer]);
RealignString();
}
break;
@ -923,7 +923,7 @@ class CommandDrawString : public SBarInfoCommand
break;
}
case LOGTEXT:
str = statusBar->CPlayer->LogText;
str = GStrings(statusBar->CPlayer->LogText);
break;
default:
break;
@ -1465,8 +1465,8 @@ class CommandDrawNumber : public CommandDrawString
break;
}
case SELECTEDINVENTORY:
if(statusBar->CPlayer->mo->InvSel != NULL)
num = statusBar->CPlayer->mo->InvSel->IntVar(NAME_Amount);
if(statusBar->CPlayer->mo->PointerVar<AActor>(NAME_InvSel) != NULL)
num = statusBar->CPlayer->mo->PointerVar<AActor>(NAME_InvSel)->IntVar(NAME_Amount);
break;
case ACCURACY:
num = statusBar->CPlayer->mo->accuracy;
@ -1691,7 +1691,7 @@ class CommandDrawSelectedInventory : public CommandDrawImage, private CommandDra
if(alternateOnEmpty)
SBarInfoCommandFlowControl::Draw(block, statusBar);
if(statusBar->CPlayer->mo->InvSel != NULL && !(level.flags & LEVEL_NOINVENTORYBAR))
if(statusBar->CPlayer->mo->PointerVar<AActor>(NAME_InvSel) != NULL && !(level.flags & LEVEL_NOINVENTORYBAR))
{
if(artiflash && statusBar->wrapper->artiflashTick)
{
@ -1708,7 +1708,7 @@ class CommandDrawSelectedInventory : public CommandDrawImage, private CommandDra
}
CommandDrawImage::Draw(block, statusBar);
}
if(alwaysShowCounter || statusBar->CPlayer->mo->InvSel->IntVar(NAME_Amount) != 1)
if(alwaysShowCounter || statusBar->CPlayer->mo->PointerVar<AActor>(NAME_InvSel)->IntVar(NAME_Amount) != 1)
CommandDrawNumber::Draw(block, statusBar);
}
}
@ -1791,7 +1791,7 @@ class CommandDrawSelectedInventory : public CommandDrawImage, private CommandDra
{
SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged);
SetTruth(statusBar->CPlayer->mo->InvSel == NULL || (level.flags & LEVEL_NOINVENTORYBAR), block, statusBar);
SetTruth(statusBar->CPlayer->mo->PointerVar<AActor>(NAME_InvSel) == NULL || (level.flags & LEVEL_NOINVENTORYBAR), block, statusBar);
CommandDrawImage::Tick(block, statusBar, hudChanged);
CommandDrawNumber::Tick(block, statusBar, hudChanged);
@ -2119,11 +2119,12 @@ class CommandDrawInventoryBar : public SBarInfoCommand
AActor *item;
unsigned int i = 0;
auto &InvFirst = statusBar->CPlayer->mo->PointerVar<AActor>(NAME_InvFirst);
// If the player has no artifacts, don't draw the bar
statusBar->CPlayer->mo->InvFirst = statusBar->wrapper->ValidateInvFirst(size);
if(statusBar->CPlayer->mo->InvFirst != NULL || alwaysShow)
InvFirst = statusBar->wrapper->ValidateInvFirst(size);
if (InvFirst != nullptr || alwaysShow)
{
for(item = statusBar->CPlayer->mo->InvFirst, i = 0; item != NULL && i < size; item = NextInv(item), ++i)
for(item = InvFirst, i = 0; item != NULL && i < size; item = NextInv(item), ++i)
{
SBarInfoCoordinate rx = x + (!vertical ? i*spacing : 0);
SBarInfoCoordinate ry = y + (vertical ? i*spacing : 0);
@ -2132,7 +2133,7 @@ class CommandDrawInventoryBar : public SBarInfoCommand
if(style != STYLE_Strife) //Strife draws the cursor before the icons
statusBar->DrawGraphic(TexMan.GetTexture(item->TextureIDVar(NAME_Icon), true), rx - (style == STYLE_HexenStrict ? 2 : 0), ry - (style == STYLE_HexenStrict ? 1 : 0), block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), false, item->IntVar(NAME_Amount) <= 0);
if(item == statusBar->CPlayer->mo->InvSel)
if(item == statusBar->CPlayer->mo->PointerVar<AActor>(NAME_InvSel))
{
if(style == STYLE_Heretic)
statusBar->DrawGraphic(statusBar->Images[statusBar->invBarOffset + imgSELECTBOX], rx, ry+29, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets());
@ -2157,7 +2158,7 @@ class CommandDrawInventoryBar : public SBarInfoCommand
statusBar->DrawGraphic(statusBar->Images[statusBar->invBarOffset + imgARTIBOX], x + (!vertical ? (i*spacing) : 0), y + (vertical ? (i*spacing) : 0), block->XOffset(), block->YOffset(), bgalpha, block->FullScreenOffsets());
// Is there something to the left?
if (!noArrows && PrevInv(statusBar->CPlayer->mo->InvFirst))
if (!noArrows && InvFirst && PrevInv(statusBar->CPlayer->mo->PointerVar<AActor>(NAME_InvFirst)))
{
int offset = (style != STYLE_Strife ? (style != STYLE_HexenStrict ? -12 : -10) : 14);
int yOffset = style != STYLE_HexenStrict ? 0 : -1;

View file

@ -55,6 +55,7 @@
#include "vm.h"
#include "p_acs.h"
#include "sbarinfo.h"
#include "gstrings.h"
#include "events.h"
#include "../version.h"
@ -436,7 +437,7 @@ void DBaseStatusBar::OnDestroy ()
msg->Destroy();
msg = next;
}
Messages[i] = NULL;
Messages[i] = nullptr;
}
if (AltHud) AltHud->Destroy();
Super::OnDestroy();
@ -594,7 +595,7 @@ void DBaseStatusBar::Tick ()
for (size_t i = 0; i < countof(Messages); ++i)
{
DHUDMessageBase *msg = Messages[i];
DHUDMessageBase **prev = &Messages[i];
TObjPtr<DHUDMessageBase *>*prev = &Messages[i];
while (msg)
{
@ -657,7 +658,7 @@ void DBaseStatusBar::CallTick()
void DBaseStatusBar::AttachMessage (DHUDMessageBase *msg, uint32_t id, int layer)
{
DHUDMessageBase *old = NULL;
DHUDMessageBase **prev;
TObjPtr<DHUDMessageBase *>*prev;
old = (id == 0 || id == 0xFFFFFFFF) ? NULL : DetachMessage (id);
if (old != NULL)
@ -698,7 +699,7 @@ DHUDMessageBase *DBaseStatusBar::DetachMessage (DHUDMessageBase *msg)
for (size_t i = 0; i < countof(Messages); ++i)
{
DHUDMessageBase *probe = Messages[i];
DHUDMessageBase **prev = &Messages[i];
TObjPtr<DHUDMessageBase *>*prev = &Messages[i];
while (probe && probe != msg)
{
@ -708,7 +709,7 @@ DHUDMessageBase *DBaseStatusBar::DetachMessage (DHUDMessageBase *msg)
if (probe != NULL)
{
*prev = probe->Next;
probe->Next = NULL;
probe->Next = nullptr;
return probe;
}
}
@ -720,7 +721,7 @@ DHUDMessageBase *DBaseStatusBar::DetachMessage (uint32_t id)
for (size_t i = 0; i < countof(Messages); ++i)
{
DHUDMessageBase *probe = Messages[i];
DHUDMessageBase **prev = &Messages[i];
TObjPtr<DHUDMessageBase *>*prev = &Messages[i];
while (probe && probe->SBarID != id)
{
@ -730,7 +731,7 @@ DHUDMessageBase *DBaseStatusBar::DetachMessage (uint32_t id)
if (probe != NULL)
{
*prev = probe->Next;
probe->Next = NULL;
probe->Next = nullptr;
return probe;
}
}
@ -749,7 +750,7 @@ void DBaseStatusBar::DetachAllMessages ()
{
DHUDMessageBase *probe = Messages[i];
Messages[i] = NULL;
Messages[i] = nullptr;
while (probe != NULL)
{
DHUDMessageBase *next = probe->Next;
@ -774,6 +775,49 @@ void DBaseStatusBar::ShowPlayerName ()
1.5f, 0.92f, 0, 0, color, 2.f, 0.35f), MAKE_ID('P','N','A','M'));
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static FTextureID GetBorderTexture(FLevelLocals *Level)
{
if (Level != nullptr && Level->info != nullptr && Level->info->BorderTexture.Len() != 0)
{
auto picnum = TexMan.CheckForTexture (Level->info->BorderTexture, ETextureType::Flat);
if (picnum.isValid()) return picnum;
}
return TexMan.CheckForTexture (gameinfo.BorderFlat, ETextureType::Flat);
}
//==========================================================================
//
// R_RefreshViewBorder
//
// Draws the border around the player view, if needed.
//
//==========================================================================
void DBaseStatusBar::RefreshViewBorder ()
{
if (setblocks < 10)
{
int Width = screen->GetWidth();
if (viewwidth == Width)
{
return;
}
auto tex = GetBorderTexture(&level);
screen->DrawBorder (tex, 0, 0, Width, viewwindowy);
screen->DrawBorder (tex, 0, viewwindowy, viewwindowx, viewheight + viewwindowy);
screen->DrawBorder (tex, viewwindowx + viewwidth, viewwindowy, Width, viewheight + viewwindowy);
screen->DrawBorder (tex, 0, viewwindowy + viewheight, Width, StatusBar->GetTopOfStatusbar());
screen->DrawFrame (viewwindowx, viewwindowy, viewwidth, viewheight);
}
}
//---------------------------------------------------------------------------
//
// RefreshBackground
@ -787,13 +831,17 @@ void DBaseStatusBar::RefreshBackground () const
float ratio = ActiveRatio (SCREENWIDTH, SCREENHEIGHT);
x = ST_X;
y = SBarTop;
if (x == 0 && y == SCREENHEIGHT) return;
auto tex = GetBorderTexture(&level);
if(!CompleteBorder)
{
if(y < SCREENHEIGHT)
{
screen->DrawBorder (x+1, y, SCREENWIDTH, y+1);
screen->DrawBorder (x+1, SCREENHEIGHT-1, SCREENWIDTH, SCREENHEIGHT);
screen->DrawBorder (tex, x+1, y, SCREENWIDTH, y+1);
screen->DrawBorder (tex, x+1, SCREENHEIGHT-1, SCREENWIDTH, SCREENHEIGHT);
}
}
else
@ -812,8 +860,8 @@ void DBaseStatusBar::RefreshBackground () const
x2 = SCREENWIDTH;
}
screen->DrawBorder (0, y, x+1, SCREENHEIGHT);
screen->DrawBorder (x2-1, y, SCREENWIDTH, SCREENHEIGHT);
screen->DrawBorder (tex, 0, y, x+1, SCREENHEIGHT);
screen->DrawBorder (tex, x2-1, y, SCREENWIDTH, SCREENHEIGHT);
if (setblocks >= 10)
{
@ -1017,7 +1065,7 @@ void DBaseStatusBar::DrawLog ()
hudheight = SCREENHEIGHT / scale;
int linelen = hudwidth<640? Scale(hudwidth,9,10)-40 : 560;
auto lines = V_BreakLines (SmallFont, linelen, CPlayer->LogText);
auto lines = V_BreakLines (SmallFont, linelen, GStrings(CPlayer->LogText));
int height = 20;
for (unsigned i = 0; i < lines.Size(); i++) height += SmallFont->GetHeight () + 1;

View file

@ -40,9 +40,13 @@
#include "v_video.h"
#include "g_level.h"
#include "vm.h"
#include "c_cvars.h"
gameinfo_t gameinfo;
EXTERN_CVAR(Float, turbo)
DEFINE_GLOBAL(gameinfo)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, backpacktype)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, Armor2Percent)
@ -67,6 +71,8 @@ DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, defKickback)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, healthpic)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, berserkpic)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, defaultdropstyle)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, normforwardmove)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, normsidemove)
const char *GameNames[17] =
{
@ -186,6 +192,16 @@ const char* GameInfoBorders[] =
gameinfo.key = sc.Float; \
}
#define GAMEINFOKEY_TWODOUBLES(key, variable) \
else if(nextKey.CompareNoCase(variable) == 0) \
{ \
sc.MustGetValue(true); \
gameinfo.key[0] = sc.Float; \
sc.MustGetToken(','); \
sc.MustGetValue(true); \
gameinfo.key[1] = sc.Float; \
}
#define GAMEINFOKEY_COLOR(key, variable) \
else if(nextKey.CompareNoCase(variable) == 0) \
{ \
@ -250,7 +266,7 @@ void FMapInfoParser::ParseGameInfo()
sc.MustGetToken('{');
while(sc.GetToken())
{
if (sc.TokenType == '}') return;
if (sc.TokenType == '}') break;
sc.TokenMustBe(TK_Identifier);
FString nextKey = sc.String;
@ -337,84 +353,86 @@ void FMapInfoParser::ParseGameInfo()
}
// Insert valid keys here.
GAMEINFOKEY_STRING(mCheatKey, "cheatKey")
GAMEINFOKEY_STRING(mEasyKey, "easyKey")
GAMEINFOKEY_STRING(TitlePage, "titlePage")
GAMEINFOKEY_STRINGARRAY(creditPages, "addcreditPage", 8, false)
GAMEINFOKEY_STRINGARRAY(creditPages, "CreditPage", 8, true)
GAMEINFOKEY_STRINGARRAY(PlayerClasses, "addplayerclasses", 0, false)
GAMEINFOKEY_STRINGARRAY(PlayerClasses, "playerclasses", 0, true)
GAMEINFOKEY_MUSIC(titleMusic, titleOrder, "titleMusic")
GAMEINFOKEY_FLOAT(titleTime, "titleTime")
GAMEINFOKEY_FLOAT(advisoryTime, "advisoryTime")
GAMEINFOKEY_FLOAT(pageTime, "pageTime")
GAMEINFOKEY_STRING(chatSound, "chatSound")
GAMEINFOKEY_MUSIC(finaleMusic, finaleOrder, "finaleMusic")
GAMEINFOKEY_STRING(FinaleFlat, "finaleFlat")
GAMEINFOKEY_STRINGARRAY(finalePages, "finalePage", 8, true)
GAMEINFOKEY_STRINGARRAY(infoPages, "addinfoPage", 8, false)
GAMEINFOKEY_STRINGARRAY(infoPages, "infoPage", 8, true)
GAMEINFOKEY_STRINGARRAY(PrecachedClasses, "precacheclasses", 0, false)
GAMEINFOKEY_STRINGARRAY(PrecachedTextures, "precachetextures", 0, false)
GAMEINFOKEY_SOUNDARRAY(PrecachedSounds, "precachesounds", 0, false)
GAMEINFOKEY_STRINGARRAY(EventHandlers, "addeventhandlers", 0, false)
GAMEINFOKEY_STRINGARRAY(EventHandlers, "eventhandlers", 0, true)
GAMEINFOKEY_STRING(PauseSign, "pausesign")
GAMEINFOKEY_STRING(quitSound, "quitSound")
GAMEINFOKEY_STRING(BorderFlat, "borderFlat")
GAMEINFOKEY_DOUBLE(telefogheight, "telefogheight")
GAMEINFOKEY_DOUBLE(gibfactor, "gibfactor")
GAMEINFOKEY_INT(defKickback, "defKickback")
GAMEINFOKEY_STRING(SkyFlatName, "SkyFlatName")
GAMEINFOKEY_STRING(translator, "translator")
GAMEINFOKEY_COLOR(pickupcolor, "pickupcolor")
GAMEINFOKEY_COLOR(defaultbloodcolor, "defaultbloodcolor")
GAMEINFOKEY_COLOR(defaultbloodparticlecolor, "defaultbloodparticlecolor")
GAMEINFOKEY_STRING(backpacktype, "backpacktype")
GAMEINFOKEY_STRING_STAMPED(statusbar, "statusbar", statusbarfile)
GAMEINFOKEY_STRING_STAMPED(statusbarclass, "statusbarclass", statusbarclassfile)
GAMEINFOKEY_MUSIC(intermissionMusic, intermissionOrder, "intermissionMusic")
GAMEINFOKEY_STRING(CursorPic, "CursorPic")
GAMEINFOKEY_STRING(MessageBoxClass, "MessageBoxClass")
GAMEINFOKEY_BOOL(noloopfinalemusic, "noloopfinalemusic")
GAMEINFOKEY_BOOL(drawreadthis, "drawreadthis")
GAMEINFOKEY_BOOL(swapmenu, "swapmenu")
GAMEINFOKEY_BOOL(dontcrunchcorpses, "dontcrunchcorpses")
GAMEINFOKEY_BOOL(correctprintbold, "correctprintbold")
GAMEINFOKEY_BOOL(intermissioncounter, "intermissioncounter")
GAMEINFOKEY_BOOL(nightmarefast, "nightmarefast")
GAMEINFOKEY_COLOR(dimcolor, "dimcolor")
GAMEINFOKEY_FLOAT(dimamount, "dimamount")
GAMEINFOKEY_FLOAT(bluramount, "bluramount")
GAMEINFOKEY_STRING(mSliderColor, "menuslidercolor")
GAMEINFOKEY_INT(definventorymaxamount, "definventorymaxamount")
GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime")
GAMEINFOKEY_INT(defaultdropstyle, "defaultdropstyle")
GAMEINFOKEY_STRING(Endoom, "endoom")
GAMEINFOKEY_STRINGARRAY(quitmessages, "addquitmessages", 0, false)
GAMEINFOKEY_STRINGARRAY(quitmessages, "quitmessages", 0, true)
GAMEINFOKEY_STRING(mTitleColor, "menufontcolor_title")
GAMEINFOKEY_STRING(mFontColor, "menufontcolor_label")
GAMEINFOKEY_STRING(mFontColorValue, "menufontcolor_value")
GAMEINFOKEY_STRING(mFontColorMore, "menufontcolor_action")
GAMEINFOKEY_STRING(mFontColorHeader, "menufontcolor_header")
GAMEINFOKEY_STRING(mFontColorHighlight, "menufontcolor_highlight")
GAMEINFOKEY_STRING(mFontColorSelection, "menufontcolor_selection")
GAMEINFOKEY_STRING(mBackButton, "menubackbutton")
GAMEINFOKEY_INT(TextScreenX, "textscreenx")
GAMEINFOKEY_INT(TextScreenY, "textscreeny")
GAMEINFOKEY_STRING(DefaultEndSequence, "defaultendsequence")
GAMEINFOKEY_STRING(DefaultConversationMenuClass, "defaultconversationmenuclass")
GAMEINFOKEY_FONT(mStatscreenMapNameFont, "statscreen_mapnamefont")
GAMEINFOKEY_FONT(mStatscreenFinishedFont, "statscreen_finishedfont")
GAMEINFOKEY_FONT(mStatscreenEnteringFont, "statscreen_enteringfont")
GAMEINFOKEY_PATCH(mStatscreenFinishedFont, "statscreen_finishedpatch")
GAMEINFOKEY_PATCH(mStatscreenEnteringFont, "statscreen_enteringpatch")
GAMEINFOKEY_BOOL(norandomplayerclass, "norandomplayerclass")
GAMEINFOKEY_BOOL(forcekillscripts, "forcekillscripts") // [JM] Force kill scripts on thing death. (MF7_NOKILLSCRIPTS overrides.)
GAMEINFOKEY_STRING(Dialogue, "dialogue")
GAMEINFOKEY_STRING(statusscreen_single, "statscreen_single")
GAMEINFOKEY_STRING(statusscreen_coop, "statscreen_coop")
GAMEINFOKEY_STRING(statusscreen_dm, "statscreen_dm")
GAMEINFOKEY_STRING(mEasyKey, "easyKey")
GAMEINFOKEY_STRING(TitlePage, "titlePage")
GAMEINFOKEY_STRINGARRAY(creditPages, "addcreditPage", 8, false)
GAMEINFOKEY_STRINGARRAY(creditPages, "CreditPage", 8, true)
GAMEINFOKEY_STRINGARRAY(PlayerClasses, "addplayerclasses", 0, false)
GAMEINFOKEY_STRINGARRAY(PlayerClasses, "playerclasses", 0, true)
GAMEINFOKEY_MUSIC(titleMusic, titleOrder, "titleMusic")
GAMEINFOKEY_FLOAT(titleTime, "titleTime")
GAMEINFOKEY_FLOAT(advisoryTime, "advisoryTime")
GAMEINFOKEY_FLOAT(pageTime, "pageTime")
GAMEINFOKEY_STRING(chatSound, "chatSound")
GAMEINFOKEY_MUSIC(finaleMusic, finaleOrder, "finaleMusic")
GAMEINFOKEY_STRING(FinaleFlat, "finaleFlat")
GAMEINFOKEY_STRINGARRAY(finalePages, "finalePage", 8, true)
GAMEINFOKEY_STRINGARRAY(infoPages, "addinfoPage", 8, false)
GAMEINFOKEY_STRINGARRAY(infoPages, "infoPage", 8, true)
GAMEINFOKEY_STRINGARRAY(PrecachedClasses, "precacheclasses", 0, false)
GAMEINFOKEY_STRINGARRAY(PrecachedTextures, "precachetextures", 0, false)
GAMEINFOKEY_SOUNDARRAY(PrecachedSounds, "precachesounds", 0, false)
GAMEINFOKEY_STRINGARRAY(EventHandlers, "addeventhandlers", 0, false)
GAMEINFOKEY_STRINGARRAY(EventHandlers, "eventhandlers", 0, true)
GAMEINFOKEY_STRING(PauseSign, "pausesign")
GAMEINFOKEY_STRING(quitSound, "quitSound")
GAMEINFOKEY_STRING(BorderFlat, "borderFlat")
GAMEINFOKEY_DOUBLE(telefogheight, "telefogheight")
GAMEINFOKEY_DOUBLE(gibfactor, "gibfactor")
GAMEINFOKEY_INT(defKickback, "defKickback")
GAMEINFOKEY_STRING(SkyFlatName, "SkyFlatName")
GAMEINFOKEY_STRING(translator, "translator")
GAMEINFOKEY_COLOR(pickupcolor, "pickupcolor")
GAMEINFOKEY_COLOR(defaultbloodcolor, "defaultbloodcolor")
GAMEINFOKEY_COLOR(defaultbloodparticlecolor, "defaultbloodparticlecolor")
GAMEINFOKEY_STRING(backpacktype, "backpacktype")
GAMEINFOKEY_STRING_STAMPED(statusbar, "statusbar", statusbarfile)
GAMEINFOKEY_STRING_STAMPED(statusbarclass, "statusbarclass", statusbarclassfile)
GAMEINFOKEY_MUSIC(intermissionMusic, intermissionOrder, "intermissionMusic")
GAMEINFOKEY_STRING(CursorPic, "CursorPic")
GAMEINFOKEY_STRING(MessageBoxClass, "MessageBoxClass")
GAMEINFOKEY_BOOL(noloopfinalemusic, "noloopfinalemusic")
GAMEINFOKEY_BOOL(drawreadthis, "drawreadthis")
GAMEINFOKEY_BOOL(swapmenu, "swapmenu")
GAMEINFOKEY_BOOL(dontcrunchcorpses, "dontcrunchcorpses")
GAMEINFOKEY_BOOL(correctprintbold, "correctprintbold")
GAMEINFOKEY_BOOL(intermissioncounter, "intermissioncounter")
GAMEINFOKEY_BOOL(nightmarefast, "nightmarefast")
GAMEINFOKEY_COLOR(dimcolor, "dimcolor")
GAMEINFOKEY_FLOAT(dimamount, "dimamount")
GAMEINFOKEY_FLOAT(bluramount, "bluramount")
GAMEINFOKEY_STRING(mSliderColor, "menuslidercolor")
GAMEINFOKEY_INT(definventorymaxamount, "definventorymaxamount")
GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime")
GAMEINFOKEY_INT(defaultdropstyle, "defaultdropstyle")
GAMEINFOKEY_STRING(Endoom, "endoom")
GAMEINFOKEY_STRINGARRAY(quitmessages, "addquitmessages", 0, false)
GAMEINFOKEY_STRINGARRAY(quitmessages, "quitmessages", 0, true)
GAMEINFOKEY_STRING(mTitleColor, "menufontcolor_title")
GAMEINFOKEY_STRING(mFontColor, "menufontcolor_label")
GAMEINFOKEY_STRING(mFontColorValue, "menufontcolor_value")
GAMEINFOKEY_STRING(mFontColorMore, "menufontcolor_action")
GAMEINFOKEY_STRING(mFontColorHeader, "menufontcolor_header")
GAMEINFOKEY_STRING(mFontColorHighlight, "menufontcolor_highlight")
GAMEINFOKEY_STRING(mFontColorSelection, "menufontcolor_selection")
GAMEINFOKEY_STRING(mBackButton, "menubackbutton")
GAMEINFOKEY_INT(TextScreenX, "textscreenx")
GAMEINFOKEY_INT(TextScreenY, "textscreeny")
GAMEINFOKEY_STRING(DefaultEndSequence, "defaultendsequence")
GAMEINFOKEY_STRING(DefaultConversationMenuClass, "defaultconversationmenuclass")
GAMEINFOKEY_FONT(mStatscreenMapNameFont, "statscreen_mapnamefont")
GAMEINFOKEY_FONT(mStatscreenFinishedFont, "statscreen_finishedfont")
GAMEINFOKEY_FONT(mStatscreenEnteringFont, "statscreen_enteringfont")
GAMEINFOKEY_PATCH(mStatscreenFinishedFont, "statscreen_finishedpatch")
GAMEINFOKEY_PATCH(mStatscreenEnteringFont, "statscreen_enteringpatch")
GAMEINFOKEY_BOOL(norandomplayerclass, "norandomplayerclass")
GAMEINFOKEY_BOOL(forcekillscripts, "forcekillscripts") // [JM] Force kill scripts on thing death. (MF7_NOKILLSCRIPTS overrides.)
GAMEINFOKEY_STRING(Dialogue, "dialogue")
GAMEINFOKEY_STRING(statusscreen_single, "statscreen_single")
GAMEINFOKEY_STRING(statusscreen_coop, "statscreen_coop")
GAMEINFOKEY_STRING(statusscreen_dm, "statscreen_dm")
GAMEINFOKEY_TWODOUBLES(normforwardmove, "normforwardmove")
GAMEINFOKEY_TWODOUBLES(normsidemove, "normsidemove")
else
{
@ -425,6 +443,7 @@ void FMapInfoParser::ParseGameInfo()
SkipToNext();
}
}
turbo.Callback();
}
const char *gameinfo_t::GetFinalePage(unsigned int num) const

View file

@ -193,6 +193,8 @@ struct gameinfo_t
FName statusscreen_dm;
int healthpic; // These get filled in from ALTHUDCF
int berserkpic;
double normforwardmove[2];
double normsidemove[2];
const char *GetFinalePage(unsigned int num) const;
};

View file

@ -254,7 +254,9 @@ sector_t *FGLRenderer::RenderView(player_t* player)
bool saved_niv = NoInterpolateView;
NoInterpolateView = false;
// prepare all camera textures that have been used in the last frame
level.canvasTextureInfo.UpdateAll([&](AActor *camera, FCanvasTexture *camtex, double fov)
auto Level = &level;
gl_RenderState.CheckTimer(Level->ShaderStartTime);
Level->canvasTextureInfo.UpdateAll([&](AActor *camera, FCanvasTexture *camtex, double fov)
{
RenderTextureView(camtex, camera, fov);
});
@ -273,7 +275,6 @@ sector_t *FGLRenderer::RenderView(player_t* player)
fovratio = ratio;
}
UpdateShadowMap();
retsec = RenderViewpoint(r_viewpoint, player->camera, NULL, r_viewpoint.FieldOfView.Degrees, ratio, fovratio, true, true);
}
All.Unclock();
@ -362,7 +363,7 @@ void FGLRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, i
FRenderViewpoint savevp;
sector_t *viewsector = RenderViewpoint(savevp, players[consoleplayer].camera, &bounds, r_viewpoint.FieldOfView.Degrees, 1.6f, 1.6f, true, false);
glDisable(GL_STENCIL_TEST);
gl_RenderState.SetSoftLightLevel(-1);
gl_RenderState.SetNoSoftLightLevel();
CopyToBackbuffer(&bounds, false);
// strictly speaking not needed as the glReadPixels should block until the scene is rendered, but this is to safeguard against shitty drivers

View file

@ -48,7 +48,6 @@ namespace OpenGLRenderer
FGLRenderState gl_RenderState;
static VSMatrix identityMatrix(1);
TArray<VSMatrix> gl_MatrixStack;
static void matrixToGL(const VSMatrix &mat, int loc)
{
@ -94,12 +93,6 @@ void FGLRenderState::Reset()
bool FGLRenderState::ApplyShader()
{
static uint64_t firstFrame = 0;
// if firstFrame is not yet initialized, initialize it to current time
// if we're going to overflow a float (after ~4.6 hours, or 24 bits), re-init to regain precision
if ((firstFrame == 0) || (screen->FrameTime - firstFrame >= 1<<24) || level.ShaderStartTime >= firstFrame)
firstFrame = screen->FrameTime;
static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f };
if (mSpecialEffect > EFF_NONE)
{
@ -596,4 +589,12 @@ bool FGLRenderState::SetDepthClamp(bool on)
return res;
}
void FGLRenderState::CheckTimer(uint64_t ShaderStartTime)
{
// if firstFrame is not yet initialized, initialize it to current time
// if we're going to overflow a float (after ~4.6 hours, or 24 bits), re-init to regain precision
if ((firstFrame == 0) || (screen->FrameTime - firstFrame >= 1 << 24) || ShaderStartTime >= firstFrame)
firstFrame = screen->FrameTime;
}
}

View file

@ -39,7 +39,6 @@ namespace OpenGLRenderer
class FShader;
struct GLSectorPlane;
extern TArray<VSMatrix> gl_MatrixStack;
enum EPassType
{
@ -51,6 +50,8 @@ enum EPassType
class FGLRenderState : public FRenderState
{
uint64_t firstFrame = 0;
uint8_t mLastDepthClamp : 1;
float mGlossiness, mSpecularLevel;
@ -103,6 +104,7 @@ public:
void Apply();
void ApplyBuffers();
void ApplyBlendMode();
void CheckTimer(uint64_t ShaderStartTime);
void ResetVertexBuffer()
{

View file

@ -152,6 +152,9 @@ sector_t * FGLRenderer::RenderViewpoint (FRenderViewpoint &mainvp, AActor * came
{
R_SetupFrame (mainvp, r_viewwindow, camera);
if (mainview && toscreen)
UpdateShadowMap();
// Render (potentially) multiple views for stereo 3d
// Fixme. The view offsetting should be done with a static table and not require setup of the entire render state for the mode.
auto vrmode = VRMode::GetVRMode(mainview && toscreen);

View file

@ -65,9 +65,8 @@ void GLBuffer::Bind()
}
void GLBuffer::SetData(size_t size, void *data, bool staticdata)
void GLBuffer::SetData(size_t size, const void *data, bool staticdata)
{
assert(nomap); // once it's mappable, it cannot be recreated anymore.
Bind();
if (data != nullptr)
{
@ -92,6 +91,12 @@ void GLBuffer::SetData(size_t size, void *data, bool staticdata)
InvalidateBufferState();
}
void GLBuffer::SetSubData(size_t offset, size_t size, const void *data)
{
Bind();
glBufferSubData(mUseType, offset, size, data);
}
void GLBuffer::Map()
{
assert(nomap == false); // do not allow mapping of static buffers. Vulkan cannot do that so it should be blocked in OpenGL, too.

View file

@ -22,7 +22,8 @@ protected:
GLBuffer(int usetype);
~GLBuffer();
void SetData(size_t size, void *data, bool staticdata) override;
void SetData(size_t size, const void *data, bool staticdata) override;
void SetSubData(size_t offset, size_t size, const void *data) override;
void Map() override;
void Unmap() override;
void Resize(size_t newsize) override;

View file

@ -58,12 +58,7 @@ void gl_LoadExtensions();
void gl_PrintStartupLog();
void Draw2D(F2DDrawer *drawer, FRenderState &state);
CUSTOM_CVAR(Int, vid_hwgamma, 2, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
if (self < 0 || self > 2) self = 2;
if (screen != nullptr) screen->SetGamma();
}
extern bool vid_hdr_active;
namespace OpenGLRenderer
{
@ -281,35 +276,6 @@ void OpenGLFrameBuffer::SetVSync(bool vsync)
glBindFramebuffer(GL_READ_FRAMEBUFFER, oldReadFramebufferBinding);
}
//===========================================================================
//
// DoSetGamma
//
// (Unfortunately Windows has some safety precautions that block gamma ramps
// that are considered too extreme. As a result this doesn't work flawlessly)
//
//===========================================================================
void OpenGLFrameBuffer::SetGamma()
{
bool useHWGamma = m_supportsGamma && ((vid_hwgamma == 0) || (vid_hwgamma == 2 && IsFullscreen()));
if (useHWGamma)
{
uint16_t gammaTable[768];
// This formula is taken from Doomsday
BuildGammaTable(gammaTable);
SetGammaTable(gammaTable);
HWGammaActive = true;
}
else if (HWGammaActive)
{
ResetGammaTable();
HWGammaActive = false;
}
}
//===========================================================================
//
//
@ -465,7 +431,9 @@ TArray<uint8_t> OpenGLFrameBuffer::GetScreenshotBuffer(int &pitch, ESSType &colo
color_type = SS_RGB;
// Screenshot should not use gamma correction if it was already applied to rendered image
gamma = 1 == vid_hwgamma || (2 == vid_hwgamma && !fullscreen) ? 1.0f : Gamma;
gamma = 1;
if (vid_hdr_active && fullscreen)
gamma *= 2.2f;
return ScreenshotBuffer;
}

View file

@ -24,9 +24,6 @@ public:
void InitializeState() override;
void Update() override;
// Color correction
void SetGamma();
void CleanForRestart() override;
void UpdatePalette() override;
uint32_t GetCaps() override;

View file

@ -97,7 +97,10 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int
}
*/
bool firstCall = glTexID == 0;
if (firstCall) glGenTextures(1,&glTexID);
if (firstCall)
{
glGenTextures(1, &glTexID);
}
int textureBinding = UINT_MAX;
if (texunit == -1) glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
@ -211,7 +214,8 @@ uint8_t *FHardwareTexture::MapBuffer()
//===========================================================================
FHardwareTexture::~FHardwareTexture()
{
glDeleteBuffers(1, &glBufferID);
if (glTexID != 0) glDeleteTextures(1, &glTexID);
if (glBufferID != 0) glDeleteBuffers(1, &glBufferID);
}

View file

@ -207,9 +207,10 @@ void HU_GetPlayerWidths(int &maxnamewidth, int &maxscorewidth, int &maxiconheigh
{
maxnamewidth = width;
}
if (players[i].mo->ScoreIcon.isValid())
auto icon = FSetTextureID(players[i].mo->IntVar(NAME_ScoreIcon));
if (icon.isValid())
{
FTexture *pic = TexMan.GetTexture(players[i].mo->ScoreIcon);
FTexture *pic = TexMan.GetTexture(icon);
width = pic->GetDisplayWidth() - pic->GetDisplayLeftOffset() + 2;
if (width > maxscorewidth)
{
@ -420,9 +421,10 @@ static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2,
screen->DrawText (SmallFont, color, col2, y + ypadding, player->playerstate == PST_DEAD && !deathmatch ? "DEAD" : str,
DTA_CleanNoMove, true, TAG_DONE);
if (player->mo->ScoreIcon.isValid())
auto icon = FSetTextureID(player->mo->IntVar(NAME_ScoreIcon));
if (icon.isValid())
{
FTexture *pic = TexMan.GetTexture(player->mo->ScoreIcon);
FTexture *pic = TexMan.GetTexture(icon);
screen->DrawTexture (pic, col3, y,
DTA_CleanNoMove, true,
TAG_DONE);

View file

@ -47,7 +47,8 @@ public:
IBuffer &operator=(const IBuffer &) = delete;
virtual ~IBuffer() = default;
virtual void SetData(size_t size, void *data, bool staticdata = true) = 0;
virtual void SetData(size_t size, const void *data, bool staticdata = true) = 0;
virtual void SetSubData(size_t offset, size_t size, const void *data) = 0;
virtual void *Lock(unsigned int size) = 0;
virtual void Unlock() = 0;
virtual void Resize(size_t newsize) = 0;

View file

@ -27,42 +27,49 @@
namespace hwrenderer
{
LevelAABBTree::LevelAABBTree()
LevelAABBTree::LevelAABBTree(FLevelLocals *lev)
{
Level = lev;
// Calculate the center of all lines
TArray<FVector2> centroids;
for (unsigned int i = 0; i < level.lines.Size(); i++)
for (unsigned int i = 0; i < Level->lines.Size(); i++)
{
FVector2 v1 = { (float)level.lines[i].v1->fX(), (float)level.lines[i].v1->fY() };
FVector2 v2 = { (float)level.lines[i].v2->fX(), (float)level.lines[i].v2->fY() };
FVector2 v1 = { (float)Level->lines[i].v1->fX(), (float)Level->lines[i].v1->fY() };
FVector2 v2 = { (float)Level->lines[i].v2->fX(), (float)Level->lines[i].v2->fY() };
centroids.Push((v1 + v2) * 0.5f);
}
// Create a list of level lines we want to add:
TArray<int> line_elements;
for (unsigned int i = 0; i < level.lines.Size(); i++)
// Create the static subtree
if (!GenerateTree(&centroids[0], false))
return;
int staticroot = nodes.Size() - 1;
dynamicStartNode = nodes.Size();
dynamicStartLine = treelines.Size();
// Create the dynamic subtree
if (GenerateTree(&centroids[0], true))
{
if (!level.lines[i].backsector)
{
if (level.lines[i].sidedef[0] && (level.lines[i].sidedef[0]->Flags & WALLF_POLYOBJ))
polylines.Push(i);
line_elements.Push(i);
}
int dynamicroot = nodes.Size() - 1;
// Create a shared root node
FVector2 aabb_min, aabb_max;
const auto &left = nodes[staticroot];
const auto &right = nodes[dynamicroot];
aabb_min.X = MIN(left.aabb_left, right.aabb_left);
aabb_min.Y = MIN(left.aabb_top, right.aabb_top);
aabb_max.X = MAX(left.aabb_right, right.aabb_right);
aabb_max.Y = MAX(left.aabb_bottom, right.aabb_bottom);
nodes.Push({ aabb_min, aabb_max, staticroot, dynamicroot });
}
// GenerateTreeNode needs a buffer where it can store line indices temporarily when sorting lines into the left and right child AABB buckets
TArray<int> work_buffer;
work_buffer.Resize(line_elements.Size() * 2);
// Generate the AABB tree
GenerateTreeNode(&line_elements[0], (int)line_elements.Size(), &centroids[0], &work_buffer[0]);
// Add the lines referenced by the leaf nodes
lines.Resize(level.lines.Size());
for (unsigned int i = 0; i < level.lines.Size(); i++)
treelines.Resize(mapLines.Size());
for (unsigned int i = 0; i < mapLines.Size(); i++)
{
const auto &line = level.lines[i];
auto &treeline = lines[i];
const auto &line = Level->lines[mapLines[i]];
auto &treeline = treelines[i];
treeline.x = (float)line.v1->fX();
treeline.y = (float)line.v1->fY();
@ -71,13 +78,47 @@ LevelAABBTree::LevelAABBTree()
}
}
bool LevelAABBTree::GenerateTree(const FVector2 *centroids, bool dynamicsubtree)
{
// Create a list of level lines we want to add:
TArray<int> line_elements;
auto &maplines = Level->lines;
for (unsigned int i = 0; i < maplines.Size(); i++)
{
if (!maplines[i].backsector)
{
bool isPolyLine = maplines[i].sidedef[0] && (maplines[i].sidedef[0]->Flags & WALLF_POLYOBJ);
if (isPolyLine && dynamicsubtree)
{
line_elements.Push(mapLines.Size());
mapLines.Push(i);
}
else if (!isPolyLine && !dynamicsubtree)
{
line_elements.Push(mapLines.Size());
mapLines.Push(i);
}
}
}
if (line_elements.Size() == 0)
return false;
// GenerateTreeNode needs a buffer where it can store line indices temporarily when sorting lines into the left and right child AABB buckets
TArray<int> work_buffer;
work_buffer.Resize(line_elements.Size() * 2);
// Generate the AABB tree
GenerateTreeNode(&line_elements[0], (int)line_elements.Size(), centroids, &work_buffer[0]);
return true;
}
bool LevelAABBTree::Update()
{
bool modified = false;
for (unsigned int ii = 0; ii < polylines.Size(); ii++)
for (unsigned int i = dynamicStartLine; i < mapLines.Size(); i++)
{
int i = polylines[ii];
const auto &line = level.lines[i];
const auto &line = Level->lines[mapLines[i]];
AABBTreeLine treeline;
treeline.x = (float)line.v1->fX();
@ -85,15 +126,15 @@ bool LevelAABBTree::Update()
treeline.dx = (float)line.v2->fX() - treeline.x;
treeline.dy = (float)line.v2->fY() - treeline.y;
if (memcmp(&lines[i], &treeline, sizeof(AABBTreeLine)))
if (memcmp(&treelines[i], &treeline, sizeof(AABBTreeLine)))
{
TArray<int> path = FindNodePath(i, nodes.Size() - 1);
if (path.Size())
{
float x1 = (float)level.lines[i].v1->fX();
float y1 = (float)level.lines[i].v1->fY();
float x2 = (float)level.lines[i].v2->fX();
float y2 = (float)level.lines[i].v2->fY();
float x1 = (float)line.v1->fX();
float y1 = (float)line.v1->fY();
float x2 = (float)line.v2->fX();
float y2 = (float)line.v2->fY();
int nodeIndex = path[0];
nodes[nodeIndex].aabb_left = MIN(x1, x2);
@ -112,7 +153,7 @@ bool LevelAABBTree::Update()
cur.aabb_bottom = MAX(left.aabb_bottom, right.aabb_bottom);
}
lines[i] = treeline;
treelines[i] = treeline;
modified = true;
}
}
@ -124,8 +165,8 @@ TArray<int> LevelAABBTree::FindNodePath(unsigned int line, unsigned int node)
{
const AABBTreeNode &n = nodes[node];
if (n.aabb_left > lines[line].x || n.aabb_right < lines[line].x ||
n.aabb_top > lines[line].y || n.aabb_bottom < lines[line].y)
if (n.aabb_left > treelines[line].x || n.aabb_right < treelines[line].x ||
n.aabb_top > treelines[line].y || n.aabb_bottom < treelines[line].y)
{
return {};
}
@ -140,7 +181,7 @@ TArray<int> LevelAABBTree::FindNodePath(unsigned int line, unsigned int node)
if (path.Size())
path.Push(node);
}
else if (n.line_index == line)
else if (n.line_index == (int)line)
{
path.Push(node);
}
@ -160,7 +201,7 @@ double LevelAABBTree::RayTest(const DVector3 &ray_start, const DVector3 &ray_end
double hit_fraction = 1.0;
// Walk the tree nodes
int stack[16];
int stack[32];
int stack_pos = 1;
stack[0] = nodes.Size() - 1; // root node is the last node in the list
while (stack_pos > 0)
@ -178,7 +219,7 @@ double LevelAABBTree::RayTest(const DVector3 &ray_start, const DVector3 &ray_end
hit_fraction = MIN(IntersectRayLine(ray_start, ray_end, nodes[node_index].line_index, raydelta, rayd, raydist2), hit_fraction);
stack_pos--;
}
else if (stack_pos == 16)
else if (stack_pos == 32)
{
stack_pos--; // stack overflow - tree is too deep!
}
@ -234,7 +275,7 @@ double LevelAABBTree::IntersectRayLine(const DVector2 &ray_start, const DVector2
// This algorithm is homemade - I would not be surprised if there's a much faster method out there.
const double epsilon = 0.0000001;
const AABBTreeLine &line = lines[line_index];
const AABBTreeLine &line = treelines[line_index];
DVector2 raynormal = DVector2(raydelta.Y, -raydelta.X);
@ -264,15 +305,16 @@ int LevelAABBTree::GenerateTreeNode(int *lines, int num_lines, const FVector2 *c
// Find bounding box and median of the lines
FVector2 median = FVector2(0.0f, 0.0f);
FVector2 aabb_min, aabb_max;
aabb_min.X = (float)level.lines[lines[0]].v1->fX();
aabb_min.Y = (float)level.lines[lines[0]].v1->fY();
auto &maplines = Level->lines;
aabb_min.X = (float)maplines[mapLines[lines[0]]].v1->fX();
aabb_min.Y = (float)maplines[mapLines[lines[0]]].v1->fY();
aabb_max = aabb_min;
for (int i = 0; i < num_lines; i++)
{
float x1 = (float)level.lines[lines[i]].v1->fX();
float y1 = (float)level.lines[lines[i]].v1->fY();
float x2 = (float)level.lines[lines[i]].v2->fX();
float y2 = (float)level.lines[lines[i]].v2->fY();
float x1 = (float)maplines[mapLines[lines[i]]].v1->fX();
float y1 = (float)maplines[mapLines[lines[i]]].v1->fY();
float x2 = (float)maplines[mapLines[lines[i]]].v2->fX();
float y2 = (float)maplines[mapLines[lines[i]]].v2->fY();
aabb_min.X = MIN(aabb_min.X, x1);
aabb_min.X = MIN(aabb_min.X, x2);
@ -283,7 +325,7 @@ int LevelAABBTree::GenerateTreeNode(int *lines, int num_lines, const FVector2 *c
aabb_max.Y = MAX(aabb_max.Y, y1);
aabb_max.Y = MAX(aabb_max.Y, y2);
median += centroids[lines[i]];
median += centroids[mapLines[lines[i]]];
}
median /= (float)num_lines;
@ -319,7 +361,7 @@ int LevelAABBTree::GenerateTreeNode(int *lines, int num_lines, const FVector2 *c
{
int line_index = lines[i];
float side = FVector3(centroids[lines[i]], 1.0f) | plane;
float side = FVector3(centroids[mapLines[lines[i]]], 1.0f) | plane;
if (side >= 0.0f)
{
work_buffer[left_count] = line_index;

View file

@ -4,6 +4,8 @@
#include "tarray.h"
#include "vectors.h"
struct FLevelLocals;
namespace hwrenderer
{
@ -35,25 +37,33 @@ struct AABBTreeLine
float dx, dy;
};
// Axis aligned bounding box tree used for ray testing lines.
// Axis aligned bounding box tree used for ray testing treelines.
class LevelAABBTree
{
public:
// Constructs a tree for the current level
LevelAABBTree();
// Nodes in the AABB tree. Last node is the root node.
TArray<AABBTreeNode> nodes;
// Line segments for the leaf nodes in the tree.
TArray<AABBTreeLine> lines;
LevelAABBTree(FLevelLocals *lev);
// Shoot a ray from ray_start to ray_end and return the closest hit as a fractional value between 0 and 1. Returns 1 if no line was hit.
double RayTest(const DVector3 &ray_start, const DVector3 &ray_end);
bool Update();
const void *Nodes() const { return nodes.Data(); }
const void *Lines() const { return treelines.Data(); }
size_t NodesSize() const { return nodes.Size() * sizeof(AABBTreeNode); }
size_t LinesSize() const { return treelines.Size() * sizeof(AABBTreeLine); }
const void *DynamicNodes() const { return nodes.Data() + dynamicStartNode; }
const void *DynamicLines() const { return treelines.Data() + dynamicStartLine; }
size_t DynamicNodesSize() const { return (nodes.Size() - dynamicStartNode) * sizeof(AABBTreeNode); }
size_t DynamicLinesSize() const { return (treelines.Size() - dynamicStartLine) * sizeof(AABBTreeLine); }
size_t DynamicNodesOffset() const { return dynamicStartNode * sizeof(AABBTreeNode); }
size_t DynamicLinesOffset() const { return dynamicStartLine * sizeof(AABBTreeLine); }
private:
bool GenerateTree(const FVector2 *centroids, bool dynamicsubtree);
// Test if a ray overlaps an AABB node or not
bool OverlapRayAABB(const DVector2 &ray_start2d, const DVector2 &ray_end2d, const AABBTreeNode &node);
@ -61,11 +71,21 @@ private:
double IntersectRayLine(const DVector2 &ray_start, const DVector2 &ray_end, int line_index, const DVector2 &raydelta, double rayd, double raydist2);
// Generate a tree node and its children recursively
int GenerateTreeNode(int *lines, int num_lines, const FVector2 *centroids, int *work_buffer);
int GenerateTreeNode(int *treelines, int num_lines, const FVector2 *centroids, int *work_buffer);
TArray<int> FindNodePath(unsigned int line, unsigned int node);
TArray<int> polylines;
// Nodes in the AABB tree. Last node is the root node.
TArray<AABBTreeNode> nodes;
// Line segments for the leaf nodes in the tree.
TArray<AABBTreeLine> treelines;
int dynamicStartNode = 0;
int dynamicStartLine = 0;
TArray<int> mapLines;
FLevelLocals *Level;
};
} // namespace

View file

@ -42,14 +42,13 @@ thread_local FDynLightData lightdata;
CVAR (Bool, gl_light_sprites, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
CVAR (Bool, gl_light_particles, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
CVAR(Int, gl_attenuate, -1, 0); // This is mainly a debug option.
//==========================================================================
//
// Sets up the parameters to render one dynamic light onto one plane
//
//==========================================================================
bool FDynLightData::GetLight(int group, Plane & p, ADynamicLight * light, bool checkside)
bool FDynLightData::GetLight(int group, Plane & p, FDynamicLight * light, bool checkside)
{
DVector3 pos = light->PosRelative(group);
float radius = (light->GetRadius());
@ -72,7 +71,7 @@ bool FDynLightData::GetLight(int group, Plane & p, ADynamicLight * light, bool c
// Add one dynamic light to the light data list
//
//==========================================================================
void FDynLightData::AddLightToList(int group, ADynamicLight * light, bool forceAttenuate)
void FDynLightData::AddLightToList(int group, FDynamicLight * light, bool forceAttenuate)
{
int i = 0;
@ -106,13 +105,9 @@ void FDynLightData::AddLightToList(int group, ADynamicLight * light, bool forceA
}
float shadowIndex = light->mShadowmapIndex + 1.0f;
bool attenuate;
// Store attenuate flag in the sign bit of the float.
if (gl_attenuate == -1) attenuate = !!(light->lightflags & LF_ATTENUATE) || forceAttenuate;
else attenuate = !!gl_attenuate;
if (attenuate) shadowIndex = -shadowIndex;
if (light->IsAttenuated() || forceAttenuate) shadowIndex = -shadowIndex;
float lightType = 0.0f;
float spotInnerAngle = 0.0f;
@ -123,14 +118,15 @@ void FDynLightData::AddLightToList(int group, ADynamicLight * light, bool forceA
if (light->IsSpot())
{
lightType = 1.0f;
spotInnerAngle = (float)light->SpotInnerAngle.Cos();
spotOuterAngle = (float)light->SpotOuterAngle.Cos();
spotInnerAngle = (float)light->pSpotInnerAngle->Cos();
spotOuterAngle = (float)light->pSpotOuterAngle->Cos();
DAngle negPitch = -light->Angles.Pitch;
DAngle negPitch = -*light->pPitch;
DAngle Angle = light->target->Angles.Yaw;
double xzLen = negPitch.Cos();
spotDirX = float(-light->Angles.Yaw.Cos() * xzLen);
spotDirX = float(-Angle.Cos() * xzLen);
spotDirY = float(-negPitch.Sin());
spotDirZ = float(-light->Angles.Yaw.Sin() * xzLen);
spotDirZ = float(-Angle.Sin() * xzLen);
}
float *data = &arrays[i][arrays[i].Reserve(16)];

Some files were not shown because too many files have changed in this diff Show more