mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2025-03-15 22:50:45 +00:00
Merge branch 'master' of https://github.com/coelckers/gzdoom
# Conflicts: # src/CMakeLists.txt # src/basicinlines.h # src/m_fixed.h # src/r_3dfloors.h # src/r_bsp.cpp # src/r_bsp.h # src/r_draw.cpp # src/r_draw.h # src/r_main.cpp # src/r_main.h # src/r_plane.h # src/r_segs.h # src/r_swrenderer.cpp # src/r_things.cpp # src/r_things.h # src/win32/fb_d3d9.cpp # src/win32/fb_ddraw.cpp # wadsrc_lights/static/doomdefs.txt # wadsrc_lights/static/hticdefs.txt
This commit is contained in:
commit
e5e7e85b81
805 changed files with 83417 additions and 61653 deletions
|
@ -2,8 +2,8 @@
|
|||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
@ -317,3 +317,11 @@ Fixes some minor bugs since the last version, 1.0.3.
|
|||
~~~~~~~~~~~~~~~~~
|
||||
Security fix only. Fixes CERT-FI 20469 as it applies to bzip2.
|
||||
|
||||
|
||||
1.0.6 (6 Sept 10)
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Security fix for CVE-2010-0405. This was reported by Mikolaj
|
||||
Izdebski.
|
||||
|
||||
* Make the documentation build on Ubuntu 10.04
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
--------------------------------------------------------------------------
|
||||
|
||||
This program, "bzip2", the associated library "libbzip2", and all
|
||||
documentation, are copyright (C) 1996-2007 Julian R Seward. All
|
||||
documentation, are copyright (C) 1996-2010 Julian R Seward. All
|
||||
rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -37,6 +37,6 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Julian Seward, jseward@bzip.org
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
|
|
@ -6,8 +6,8 @@ This version is fully compatible with the previous public releases.
|
|||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in this file.
|
||||
|
||||
|
@ -181,6 +181,10 @@ WHAT'S NEW IN 1.0.5 ?
|
|||
|
||||
See the CHANGES file.
|
||||
|
||||
WHAT'S NEW IN 1.0.6 ?
|
||||
|
||||
See the CHANGES file.
|
||||
|
||||
|
||||
I hope you find bzip2 useful. Feel free to contact me at
|
||||
jseward@bzip.org
|
||||
|
@ -208,3 +212,4 @@ Cambridge, UK.
|
|||
15 February 2005 (bzip2, version 1.0.3)
|
||||
20 December 2006 (bzip2, version 1.0.4)
|
||||
10 December 2007 (bzip2, version 1.0.5)
|
||||
6 Sept 2010 (bzip2, version 1.0.6)
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
@ -36,7 +36,7 @@
|
|||
|
||||
/*-- General stuff. --*/
|
||||
|
||||
#define BZ_VERSION "1.0.5, 10-Dec-2007"
|
||||
#define BZ_VERSION "1.0.6, 6-Sept-2010"
|
||||
|
||||
typedef char Char;
|
||||
typedef unsigned char Bool;
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
@ -381,6 +381,13 @@ Int32 BZ2_decompress ( DState* s )
|
|||
es = -1;
|
||||
N = 1;
|
||||
do {
|
||||
/* Check that N doesn't get too big, so that es doesn't
|
||||
go negative. The maximum value that can be
|
||||
RUNA/RUNB encoded is equal to the block size (post
|
||||
the initial RLE), viz, 900k, so bounding N at 2
|
||||
million should guard against overflow without
|
||||
rejecting any legitimate inputs. */
|
||||
if (N >= 2*1024*1024) RETURN(BZ_DATA_ERROR);
|
||||
if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
|
||||
if (nextSym == BZ_RUNB) es = es + (1+1) * N;
|
||||
N = N * 2;
|
||||
|
@ -485,15 +492,28 @@ Int32 BZ2_decompress ( DState* s )
|
|||
RETURN(BZ_DATA_ERROR);
|
||||
|
||||
/*-- Set up cftab to facilitate generation of T^(-1) --*/
|
||||
/* Check: unzftab entries in range. */
|
||||
for (i = 0; i <= 255; i++) {
|
||||
if (s->unzftab[i] < 0 || s->unzftab[i] > nblock)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
}
|
||||
/* Actually generate cftab. */
|
||||
s->cftab[0] = 0;
|
||||
for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
|
||||
for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
|
||||
/* Check: cftab entries in range. */
|
||||
for (i = 0; i <= 256; i++) {
|
||||
if (s->cftab[i] < 0 || s->cftab[i] > nblock) {
|
||||
/* s->cftab[i] can legitimately be == nblock */
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
}
|
||||
}
|
||||
/* Check: cftab entries non-descending. */
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (s->cftab[i-1] > s->cftab[i]) {
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
s->state_out_len = 0;
|
||||
s->state_out_ch = 0;
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
|
|
@ -4,7 +4,7 @@ project(libgme)
|
|||
include (CheckCXXCompilerFlag)
|
||||
|
||||
# When version is changed, also change the one in gme/gme.h to match
|
||||
set(GME_VERSION 0.6.0 CACHE INTERNAL "libgme Version")
|
||||
set(GME_VERSION 0.6.1 CACHE INTERNAL "libgme Version")
|
||||
|
||||
# 2.6+ always assumes FATAL_ERROR, but 2.4 and below don't.
|
||||
# Of course, 2.4 might work, in which case you're welcome to drop
|
||||
|
@ -79,6 +79,9 @@ set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ZD_FASTMATH_FLAG}" )
|
|||
SET(USE_GME_NSF 1 BOOL "Enable NES NSF music emulation")
|
||||
#endif()
|
||||
|
||||
# [ZDoom] Set always to OFF.
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
|
||||
# Check for GCC "visibility" support.
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
check_cxx_compiler_flag (-fvisibility=hidden __LIBGME_TEST_VISIBILITY)
|
||||
|
@ -101,10 +104,17 @@ if (CMAKE_COMPILER_IS_GNUCXX)
|
|||
endif()
|
||||
endif()
|
||||
endif() # test visibility
|
||||
endif()
|
||||
|
||||
# Cache this result
|
||||
set( LIBGME_HAVE_GCC_VISIBILITY ${ENABLE_VISIBILITY} CACHE BOOL "GCC support for hidden visibility")
|
||||
# Cache this result
|
||||
set( LIBGME_HAVE_GCC_VISIBILITY ${ENABLE_VISIBILITY} CACHE BOOL "GCC support for hidden visibility")
|
||||
endif()
|
||||
|
||||
# Shared library defined here
|
||||
add_subdirectory(gme)
|
||||
|
||||
# EXCLUDE_FROM_ALL adds build rules but keeps it out of default build
|
||||
# [ZDoom] Not needed.
|
||||
if( FALSE )
|
||||
add_subdirectory(player EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(demo EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
|
|
@ -1,6 +1,18 @@
|
|||
Game_Music_Emu Change Log
|
||||
-------------------------
|
||||
|
||||
Game_Music_Emu 0.6.1
|
||||
--------------------
|
||||
|
||||
- Moved repository to Bitbucket since Google Code announced they would
|
||||
shutdown this year.
|
||||
|
||||
- Packaging improvements:
|
||||
- Honor $LIB_SUFFIX for installed pkg-config metadata.
|
||||
- Support setting BUILD_SHARED_LIBS to OFF to build libgme as a static
|
||||
library. (Pass -DBUILD_SHARED_LIBS=OFF when running cmake).
|
||||
Thanks to lachs0r.
|
||||
|
||||
Game_Music_Emu 0.6.0
|
||||
--------------------
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
Game_Music_Emu 0.6.0
|
||||
Game_Music_Emu 0.6.1
|
||||
--------------------
|
||||
Author : Shay Green <gblargg@gmail.com>
|
||||
Website: http://www.slack.net/~ant/libs/
|
||||
Forum : http://groups.google.com/group/blargg-sound-libs
|
||||
Source : https://code.google.com/p/game-music-emu/
|
||||
License: GNU Lesser General Public License (LGPL)
|
||||
Author : Shay Green <gblargg@gmail.com>
|
||||
Maintainer : Michael Pyne <mpyne@purinchu.net>
|
||||
Website : http://www.slack.net/~ant/libs/
|
||||
Forum : http://groups.google.com/group/blargg-sound-libs
|
||||
Source : https://bitbucket.org/mpyne/game-music-emu/
|
||||
License : GNU Lesser General Public License (LGPL), see LICENSE.txt
|
||||
|
||||
Contents
|
||||
--------
|
||||
|
|
|
@ -131,6 +131,12 @@ set (EXPORTED_HEADERS gme.h)
|
|||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gme_types.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/gme_types.h)
|
||||
|
||||
# [ZDoom] Not needed.
|
||||
if( FALSE )
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libgme.pc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libgme.pc @ONLY)
|
||||
endif()
|
||||
|
||||
# On some platforms we may need to change headers or whatnot based on whether
|
||||
# we're building the library or merely using the library. The following is
|
||||
# only defined when building the library to allow us to tell which is which.
|
||||
|
@ -147,7 +153,18 @@ add_library(gme ${libgme_SRCS})
|
|||
# to the API), the SOVERSION should be the same even when bumping up VERSION.
|
||||
# The way gme.h is designed, SOVERSION should very rarely be bumped, if ever.
|
||||
# Hopefully the API can stay compatible with old versions.
|
||||
#set_target_properties(gme
|
||||
# PROPERTIES VERSION ${GME_VERSION}
|
||||
# SOVERSION 0)
|
||||
# [ZDoom] Not needed.
|
||||
if( FALSE )
|
||||
set_target_properties(gme
|
||||
PROPERTIES VERSION ${GME_VERSION}
|
||||
SOVERSION 0)
|
||||
|
||||
install(TARGETS gme LIBRARY DESTINATION lib${LIB_SUFFIX}
|
||||
RUNTIME DESTINATION bin # DLL platforms
|
||||
ARCHIVE DESTINATION lib) # DLL platforms
|
||||
|
||||
install(FILES ${EXPORTED_HEADERS} DESTINATION include/gme)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libgme.pc DESTINATION lib${LIB_SUFFIX}/pkgconfig)
|
||||
endif()
|
||||
|
||||
target_link_libraries(gme)
|
||||
|
|
|
@ -129,6 +129,8 @@ private:
|
|||
};
|
||||
|
||||
#ifdef HAVE_ZLIB_H
|
||||
#include <zlib.h>
|
||||
|
||||
// Gzip compressed file reader
|
||||
class Gzip_File_Reader : public File_Reader {
|
||||
public:
|
||||
|
@ -143,7 +145,7 @@ public:
|
|||
long tell() const;
|
||||
blargg_err_t seek( long );
|
||||
private:
|
||||
void* file_;
|
||||
gzFile file_;
|
||||
long size_;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -178,6 +178,11 @@ blargg_long Music_Emu::msec_to_samples( blargg_long msec ) const
|
|||
return (sec * sample_rate() + msec * sample_rate() / 1000) * stereo;
|
||||
}
|
||||
|
||||
long Music_Emu::tell_samples() const
|
||||
{
|
||||
return out_time;
|
||||
}
|
||||
|
||||
long Music_Emu::tell() const
|
||||
{
|
||||
blargg_long rate = sample_rate() * stereo;
|
||||
|
@ -185,14 +190,18 @@ long Music_Emu::tell() const
|
|||
return sec * 1000 + (out_time - sec * rate) * 1000 / rate;
|
||||
}
|
||||
|
||||
blargg_err_t Music_Emu::seek( long msec )
|
||||
blargg_err_t Music_Emu::seek_samples( long time )
|
||||
{
|
||||
blargg_long time = msec_to_samples( msec );
|
||||
if ( time < out_time )
|
||||
RETURN_ERR( start_track( current_track_ ) );
|
||||
return skip( time - out_time );
|
||||
}
|
||||
|
||||
blargg_err_t Music_Emu::seek( long msec )
|
||||
{
|
||||
return seek_samples( msec_to_samples( msec ) );
|
||||
}
|
||||
|
||||
blargg_err_t Music_Emu::skip( long count )
|
||||
{
|
||||
require( current_track() >= 0 ); // start_track() must have been called already
|
||||
|
|
|
@ -41,9 +41,15 @@ public:
|
|||
// Number of milliseconds (1000 msec = 1 second) played since beginning of track
|
||||
long tell() const;
|
||||
|
||||
// Number of samples generated since beginning of track
|
||||
long tell_samples() const;
|
||||
|
||||
// Seek to new time in track. Seeking backwards or far forward can take a while.
|
||||
blargg_err_t seek( long msec );
|
||||
|
||||
// Equivalent to restarting track then skipping n samples
|
||||
blargg_err_t seek_samples( long n );
|
||||
|
||||
// Skip n samples
|
||||
blargg_err_t skip( long n );
|
||||
|
||||
|
|
|
@ -433,9 +433,7 @@ void Snes_Spc::cpu_write( int data, int addr, rel_time_t time )
|
|||
#endif
|
||||
|
||||
// Registers other than $F2 and $F4-$F7
|
||||
//if ( reg != 2 && reg != 4 && reg != 5 && reg != 6 && reg != 7 )
|
||||
// TODO: this is a bit on the fragile side
|
||||
if ( ((~0x2F00 << (bits_in_int - 16)) << reg) < 0 ) // 36%
|
||||
if ( reg != 2 && (reg < 4 || reg > 7) ) // 36%
|
||||
cpu_write_smp_reg( data, time, reg );
|
||||
}
|
||||
// High mem/address wrap-around
|
||||
|
|
|
@ -76,8 +76,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
|||
// TODO: remove non-wrapping versions?
|
||||
#define SPC_NO_SP_WRAPAROUND 0
|
||||
|
||||
#define SET_SP( v ) (sp = ram + 0x101 + (v))
|
||||
#define GET_SP() (int(sp - 0x101 - ram))
|
||||
#define SET_SP( v ) (sp = ram + 0x101 + ((uint8_t) v))
|
||||
#define GET_SP() (uint8_t (sp - 0x101 - ram))
|
||||
|
||||
#if SPC_NO_SP_WRAPAROUND
|
||||
#define PUSH16( v ) (sp -= 2, SET_LE16( sp, v ))
|
||||
|
@ -485,7 +485,7 @@ loop:
|
|||
|
||||
case 0xAF: // MOV (X)+,A
|
||||
WRITE_DP( 0, x, a + no_read_before_write );
|
||||
x++;
|
||||
x = (uint8_t) (x + 1);
|
||||
goto loop;
|
||||
|
||||
// 5. 8-BIT LOGIC OPERATION COMMANDS
|
||||
|
@ -808,7 +808,7 @@ loop:
|
|||
unsigned temp = y * a;
|
||||
a = (uint8_t) temp;
|
||||
nz = ((temp >> 1) | temp) & 0x7F;
|
||||
y = temp >> 8;
|
||||
y = (uint8_t) (temp >> 8);
|
||||
nz |= y;
|
||||
goto loop;
|
||||
}
|
||||
|
@ -838,6 +838,7 @@ loop:
|
|||
|
||||
nz = (uint8_t) a;
|
||||
a = (uint8_t) a;
|
||||
y = (uint8_t) y;
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
@ -1004,7 +1005,7 @@ loop:
|
|||
case 0x7F: // RET1
|
||||
temp = *sp;
|
||||
SET_PC( GET_LE16( sp + 1 ) );
|
||||
sp += 3;
|
||||
SET_SP(GET_SP() + 3);
|
||||
goto set_psw;
|
||||
case 0x8E: // POP PSW
|
||||
POP( temp );
|
||||
|
|
|
@ -337,7 +337,9 @@ BLARGG_EXPORT gme_err_t gme_play ( Music_Emu* me, int n, short* p )
|
|||
BLARGG_EXPORT void gme_set_fade ( Music_Emu* me, int start_msec ) { me->set_fade( start_msec ); }
|
||||
BLARGG_EXPORT int gme_track_ended ( Music_Emu const* me ) { return me->track_ended(); }
|
||||
BLARGG_EXPORT int gme_tell ( Music_Emu const* me ) { return me->tell(); }
|
||||
BLARGG_EXPORT int gme_tell_samples ( Music_Emu const* me ) { return me->tell_samples(); }
|
||||
BLARGG_EXPORT gme_err_t gme_seek ( Music_Emu* me, int msec ) { return me->seek( msec ); }
|
||||
BLARGG_EXPORT gme_err_t gme_seek_samples ( Music_Emu* me, int n ) { return me->seek_samples( n ); }
|
||||
BLARGG_EXPORT int gme_voice_count ( Music_Emu const* me ) { return me->voice_count(); }
|
||||
BLARGG_EXPORT void gme_ignore_silence ( Music_Emu* me, int disable ) { me->ignore_silence( disable != 0 ); }
|
||||
BLARGG_EXPORT void gme_set_tempo ( Music_Emu* me, double t ) { me->set_tempo( t ); }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Game music emulator library C interface (also usable from C++) */
|
||||
|
||||
/* Game_Music_Emu 0.6.0 */
|
||||
/* Game_Music_Emu 0.6.1 */
|
||||
#ifndef GME_H
|
||||
#define GME_H
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GME_VERSION 0x000600 /* 1 byte major, 1 byte minor, 1 byte patch-level */
|
||||
#define GME_VERSION 0x000601 /* 1 byte major, 1 byte minor, 1 byte patch-level */
|
||||
|
||||
/* Error string returned by library functions, or NULL if no error (success) */
|
||||
typedef const char* gme_err_t;
|
||||
|
@ -47,9 +47,15 @@ int gme_track_ended( Music_Emu const* );
|
|||
/* Number of milliseconds (1000 = one second) played since beginning of track */
|
||||
int gme_tell( Music_Emu const* );
|
||||
|
||||
/* Number of samples generated since beginning of track */
|
||||
int gme_tell_samples( Music_Emu const* );
|
||||
|
||||
/* Seek to new time in track. Seeking backwards or far forward can take a while. */
|
||||
gme_err_t gme_seek( Music_Emu*, int msec );
|
||||
|
||||
/* Equivalent to restarting track then skipping n samples */
|
||||
gme_err_t gme_seek_samples( Music_Emu*, int n );
|
||||
|
||||
|
||||
/******** Informational ********/
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Game_Music_Emu 0.6.0: Game Music Emulators
|
||||
Game_Music_Emu 0.6.1: Game Music Emulators
|
||||
------------------------------------------
|
||||
Game_Music_Emu is a collection of video game music file emulators that
|
||||
support the following formats and systems:
|
||||
|
@ -38,26 +38,42 @@ Website: http://www.slack.net/~ant/
|
|||
Forum : http://groups.google.com/group/blargg-sound-libs
|
||||
License: GNU Lesser General Public License (LGPL)
|
||||
|
||||
Current Maintainer: Michael Pyne <mpyne@purinchu.net>
|
||||
|
||||
Getting Started
|
||||
---------------
|
||||
Build a program consisting of demo/basics.c, demo/Wave_Writer.cpp, and
|
||||
all source files in gme/. If you have CMake 2.6 or later, execute
|
||||
all source files in gme/.
|
||||
|
||||
run cmake
|
||||
cd demo
|
||||
run make
|
||||
Or, if you have CMake 2.6 or later, execute at a command prompt (from the
|
||||
extracted source directory):
|
||||
|
||||
Be sure "test.nsf" is in the same directory as the program. Running it
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ../ # <-- Pass any needed CMake flags here
|
||||
make # To build the library
|
||||
cd demo
|
||||
make # To build the demo itself
|
||||
|
||||
Be sure "test.nsf" is in the same directory as the demo program. Running it
|
||||
should generate the recording "out.wav".
|
||||
|
||||
You can use "make install" to install the library. To choose where to install
|
||||
the library to, use the CMake argument "-DCMAKE_INSTALL_PREFIX=/usr/local"
|
||||
(and replace /usr/local with the base path you wish to use). Alternately, you
|
||||
can specify the base path to install to when you run "make install" by passing
|
||||
'DESTDIR=/usr/local' on the make install command line (again, replace
|
||||
/usr/local as appropriate).
|
||||
|
||||
To build a static library instead of shared (the default), pass
|
||||
-DBUILD_SHARED_LIBS=OFF to the cmake command when running cmake.
|
||||
|
||||
A slightly more extensive demo application is available in the player/
|
||||
directory. It requires SDL to build.
|
||||
|
||||
Read gme.txt for more information. Post to the discussion forum for
|
||||
assistance.
|
||||
|
||||
|
||||
Files
|
||||
-----
|
||||
gme.txt General notes about the library
|
||||
|
|
|
@ -252,9 +252,10 @@ Note: All <bool> fields default to false unless mentioned otherwise.
|
|||
// negative values are used as their absolute. Default = 1.
|
||||
|
||||
renderstyle = <string>; // Set per-actor render style, overriding the class default. Possible values can be "normal",
|
||||
// "none", "add" or "additive", "subtract" or "subtractive", "stencil", "translucentstencil",
|
||||
// "translucent", "fuzzy", "optfuzzy", "soultrans". Default is an empty string for no change.
|
||||
fillcolor = <integer>; // Fill color used by the "stencil" and "translucentstencil" rendestyles, as RRGGBB value, default = 0x000000.
|
||||
// "none", "add" or "additive", "subtract" or "subtractive", "stencil", "translucentstencil",
|
||||
// "addstencil", "shaded", "addshaded", "translucent", "fuzzy", "optfuzzy", "soultrans" and "shadow".
|
||||
// Default is an empty string for no change.
|
||||
fillcolor = <integer>; // Fill color used by the "stencil", "addstencil" and "translucentstencil" rendestyles, as RRGGBB value, default = 0x000000.
|
||||
alpha = <float>; // Translucency of this actor (if applicable to renderstyle), default is 1.0.
|
||||
score = <int>; // Score value of this actor, overriding the class default if not null. Default = 0.
|
||||
pitch = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal).
|
||||
|
|
|
@ -47,9 +47,9 @@ if( WIN32 )
|
|||
set( WIN_TYPE Win32 )
|
||||
set( XBITS x86 )
|
||||
endif()
|
||||
|
||||
|
||||
add_definitions( -D_WIN32 )
|
||||
|
||||
|
||||
find_path( D3D_INCLUDE_DIR d3d9.h
|
||||
PATHS ENV DXSDK_DIR
|
||||
PATH_SUFFIXES Include )
|
||||
|
@ -64,7 +64,7 @@ if( WIN32 )
|
|||
else()
|
||||
include_directories( ${D3D_INCLUDE_DIR} )
|
||||
endif()
|
||||
|
||||
|
||||
find_path( XINPUT_INCLUDE_DIR xinput.h
|
||||
PATHS ENV DXSDK_DIR
|
||||
PATH_SUFFIXES Include )
|
||||
|
@ -134,7 +134,6 @@ else()
|
|||
else()
|
||||
option( NO_GTK "Disable GTK+ dialogs (Not applicable to Windows)" )
|
||||
option( DYN_GTK "Load GTK+ at runtime instead of compile time" ON )
|
||||
option( VALGRIND "Add special Valgrind sequences to self-modifying code" )
|
||||
|
||||
# Use GTK+ for the IWAD picker, if available.
|
||||
if( NOT NO_GTK )
|
||||
|
@ -159,7 +158,7 @@ else()
|
|||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
if( NO_GTK )
|
||||
add_definitions( -DNO_GTK )
|
||||
elseif( DYN_GTK )
|
||||
|
@ -498,7 +497,7 @@ if( WIN32 )
|
|||
set( SYSTEM_SOURCES_DIR win32 )
|
||||
set( SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} )
|
||||
set( OTHER_SYSTEM_SOURCES ${PLAT_POSIX_SOURCES} ${PLAT_SDL_SOURCES} ${PLAT_OSX_SOURCES} ${PLAT_COCOA_SOURCES} ${PLAT_UNIX_SOURCES} )
|
||||
|
||||
|
||||
set( SYSTEM_SOURCES ${SYSTEM_SOURCES} win32/zdoom.rc )
|
||||
elseif( APPLE )
|
||||
if( OSX_COCOA_BACKEND )
|
||||
|
@ -540,16 +539,13 @@ if( HAVE_MMX )
|
|||
PROPERTIES COMPILE_FLAGS "-mmmx" )
|
||||
endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
|
||||
endif( HAVE_MMX )
|
||||
|
||||
add_definitions( -DNOASM )
|
||||
|
||||
add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.h
|
||||
COMMAND lemon -C${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/xlat/xlat_parser.y
|
||||
DEPENDS lemon ${CMAKE_CURRENT_SOURCE_DIR}/xlat/xlat_parser.y )
|
||||
|
||||
add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.c ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.h
|
||||
COMMAND lemon -C${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/zscript/zcc-parse.lemon
|
||||
DEPENDS lemon ${CMAKE_CURRENT_SOURCE_DIR}/zscript/zcc-parse.lemon )
|
||||
COMMAND lemon -C${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/scripting/zscript/zcc-parse.lemon
|
||||
DEPENDS lemon ${CMAKE_CURRENT_SOURCE_DIR}/scripting/zscript/zcc-parse.lemon )
|
||||
|
||||
add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h
|
||||
COMMAND re2c --no-generation-date -s -o ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h ${CMAKE_CURRENT_SOURCE_DIR}/sc_man_scanner.re
|
||||
|
@ -597,11 +593,8 @@ endif()
|
|||
file( GLOB HEADER_FILES
|
||||
${EXTRA_HEADER_DIRS}
|
||||
fragglescript/*.h
|
||||
g_doom/*.h
|
||||
g_heretic/*.h
|
||||
g_hexen/*.h
|
||||
g_raven/*.h
|
||||
g_shared/*.h
|
||||
g_inventory/*.h
|
||||
g_strife/*.h
|
||||
intermission/*.h
|
||||
menu/*.h
|
||||
|
@ -609,13 +602,17 @@ file( GLOB HEADER_FILES
|
|||
posix/cocoa/*.h
|
||||
posix/sdl/*.h
|
||||
r_data/*.h
|
||||
rapidjson/*.h
|
||||
resourcefiles/*.h
|
||||
sfmt/*.h
|
||||
sound/*.h
|
||||
textures/*.h
|
||||
thingdef/*.h
|
||||
scripting/*.h
|
||||
scripting/codegeneration/*.h
|
||||
scripting/decorate/*.h
|
||||
scripting/zscript/*.h
|
||||
scripting/vm/*.h
|
||||
xlat/*.h
|
||||
zscript/*.h
|
||||
gl/*.h
|
||||
gl/api/*.h
|
||||
gl/data/*.h
|
||||
|
@ -640,86 +637,11 @@ set( NOT_COMPILED_SOURCE_FILES
|
|||
${OTHER_SYSTEM_SOURCES}
|
||||
sc_man_scanner.h
|
||||
sc_man_scanner.re
|
||||
g_doom/a_arachnotron.cpp
|
||||
g_doom/a_archvile.cpp
|
||||
g_doom/a_bossbrain.cpp
|
||||
g_doom/a_bruiser.cpp
|
||||
g_doom/a_cacodemon.cpp
|
||||
g_doom/a_cyberdemon.cpp
|
||||
g_doom/a_demon.cpp
|
||||
g_doom/a_doomimp.cpp
|
||||
g_doom/a_doomweaps.cpp
|
||||
g_doom/a_fatso.cpp
|
||||
g_doom/a_keen.cpp
|
||||
g_doom/a_lostsoul.cpp
|
||||
g_doom/a_painelemental.cpp
|
||||
g_doom/a_possessed.cpp
|
||||
g_doom/a_revenant.cpp
|
||||
g_doom/a_scriptedmarine.cpp
|
||||
g_doom/a_spidermaster.cpp
|
||||
g_heretic/a_chicken.cpp
|
||||
g_heretic/a_dsparil.cpp
|
||||
g_heretic/a_hereticartifacts.cpp
|
||||
g_heretic/a_hereticimp.cpp
|
||||
g_heretic/a_hereticweaps.cpp
|
||||
g_heretic/a_ironlich.cpp
|
||||
g_heretic/a_knight.cpp
|
||||
g_heretic/a_wizard.cpp
|
||||
g_hexen/a_bats.cpp
|
||||
g_hexen/a_bishop.cpp
|
||||
g_hexen/a_blastradius.cpp
|
||||
g_hexen/a_boostarmor.cpp
|
||||
g_hexen/a_centaur.cpp
|
||||
g_hexen/a_clericflame.cpp
|
||||
g_hexen/a_clericholy.cpp
|
||||
g_hexen/a_clericmace.cpp
|
||||
g_hexen/a_clericstaff.cpp
|
||||
g_hexen/a_dragon.cpp
|
||||
g_hexen/a_fighteraxe.cpp
|
||||
g_hexen/a_fighterhammer.cpp
|
||||
g_hexen/a_fighterplayer.cpp
|
||||
g_hexen/a_fighterquietus.cpp
|
||||
g_hexen/a_firedemon.cpp
|
||||
g_hexen/a_flechette.cpp
|
||||
g_hexen/a_flies.cpp
|
||||
g_hexen/a_fog.cpp
|
||||
g_hexen/a_healingradius.cpp
|
||||
g_hexen/a_heresiarch.cpp
|
||||
g_hexen/a_hexenspecialdecs.cpp
|
||||
g_hexen/a_iceguy.cpp
|
||||
g_hexen/a_korax.cpp
|
||||
g_hexen/a_magecone.cpp
|
||||
g_hexen/a_magelightning.cpp
|
||||
g_hexen/a_magestaff.cpp
|
||||
g_hexen/a_pig.cpp
|
||||
g_hexen/a_serpent.cpp
|
||||
g_hexen/a_spike.cpp
|
||||
g_hexen/a_summon.cpp
|
||||
g_hexen/a_teleportother.cpp
|
||||
g_hexen/a_wraith.cpp
|
||||
g_strife/a_acolyte.cpp
|
||||
g_strife/a_alienspectres.cpp
|
||||
g_strife/a_coin.cpp
|
||||
g_strife/a_crusader.cpp
|
||||
g_strife/a_entityboss.cpp
|
||||
g_strife/a_inquisitor.cpp
|
||||
g_strife/a_loremaster.cpp
|
||||
g_strife/a_oracle.cpp
|
||||
g_strife/a_programmer.cpp
|
||||
g_strife/a_reaver.cpp
|
||||
g_strife/a_rebels.cpp
|
||||
g_strife/a_sentinel.cpp
|
||||
g_strife/a_spectral.cpp
|
||||
g_strife/a_stalker.cpp
|
||||
g_strife/a_strifeitems.cpp
|
||||
g_strife/a_strifeweapons.cpp
|
||||
g_strife/a_templar.cpp
|
||||
g_strife/a_thingstoblowup.cpp
|
||||
g_shared/sbarinfo_commands.cpp
|
||||
xlat/xlat_parser.y
|
||||
xlat_parser.c
|
||||
xlat_parser.h
|
||||
zscript/zcc-parse.lemon
|
||||
scripting/zscript/zcc-parse.lemon
|
||||
zcc-parse.c
|
||||
zcc-parse.h
|
||||
)
|
||||
|
@ -863,6 +785,7 @@ set( FASTMATH_SOURCES
|
|||
gl/shaders/gl_presentshader.cpp
|
||||
gl/shaders/gl_present3dRowshader.cpp
|
||||
gl/shaders/gl_bloomshader.cpp
|
||||
gl/shaders/gl_ambientshader.cpp
|
||||
gl/shaders/gl_blurshader.cpp
|
||||
gl/shaders/gl_colormapshader.cpp
|
||||
gl/shaders/gl_tonemapshader.cpp
|
||||
|
@ -1018,44 +941,32 @@ set (PCH_SOURCES
|
|||
w_wad.cpp
|
||||
wi_stuff.cpp
|
||||
zstrformat.cpp
|
||||
g_doom/a_doommisc.cpp
|
||||
g_heretic/a_hereticmisc.cpp
|
||||
g_hexen/a_hexenmisc.cpp
|
||||
g_raven/a_artitele.cpp
|
||||
g_raven/a_minotaur.cpp
|
||||
g_strife/a_strifestuff.cpp
|
||||
g_inventory/a_ammo.cpp
|
||||
g_inventory/a_armor.cpp
|
||||
g_inventory/a_artifacts.cpp
|
||||
g_inventory/a_health.cpp
|
||||
g_inventory/a_keys.cpp
|
||||
g_inventory/a_pickups.cpp
|
||||
g_inventory/a_puzzleitems.cpp
|
||||
g_inventory/a_weaponpiece.cpp
|
||||
g_inventory/a_weapons.cpp
|
||||
g_strife/strife_sbar.cpp
|
||||
g_shared/a_action.cpp
|
||||
g_shared/a_armor.cpp
|
||||
g_shared/a_artifacts.cpp
|
||||
g_shared/a_bridge.cpp
|
||||
g_shared/a_camera.cpp
|
||||
g_shared/a_debris.cpp
|
||||
g_shared/a_decals.cpp
|
||||
g_shared/a_fastprojectile.cpp
|
||||
g_shared/a_flashfader.cpp
|
||||
g_shared/a_fountain.cpp
|
||||
g_shared/a_hatetarget.cpp
|
||||
g_shared/a_keys.cpp
|
||||
g_shared/a_lightning.cpp
|
||||
g_shared/a_mapmarker.cpp
|
||||
g_shared/a_morph.cpp
|
||||
g_shared/a_movingcamera.cpp
|
||||
g_shared/a_pickups.cpp
|
||||
g_shared/a_puzzleitems.cpp
|
||||
g_shared/a_quake.cpp
|
||||
g_shared/a_randomspawner.cpp
|
||||
g_shared/a_secrettrigger.cpp
|
||||
g_shared/a_sectoraction.cpp
|
||||
g_shared/a_setcolor.cpp
|
||||
g_shared/a_skies.cpp
|
||||
g_shared/a_soundenvironment.cpp
|
||||
g_shared/a_soundsequence.cpp
|
||||
g_shared/a_spark.cpp
|
||||
g_shared/a_specialspot.cpp
|
||||
g_shared/a_waterzone.cpp
|
||||
g_shared/a_weaponpiece.cpp
|
||||
g_shared/a_weapons.cpp
|
||||
g_shared/hudmessages.cpp
|
||||
g_shared/sbarinfo.cpp
|
||||
g_shared/sbar_mugshot.cpp
|
||||
|
@ -1091,14 +1002,6 @@ set (PCH_SOURCES
|
|||
textures/texturemanager.cpp
|
||||
textures/tgatexture.cpp
|
||||
textures/warptexture.cpp
|
||||
thingdef/olddecorations.cpp
|
||||
thingdef/thingdef.cpp
|
||||
thingdef/thingdef_data.cpp
|
||||
thingdef/thingdef_exp.cpp
|
||||
thingdef/thingdef_expression.cpp
|
||||
thingdef/thingdef_parse.cpp
|
||||
thingdef/thingdef_properties.cpp
|
||||
thingdef/thingdef_states.cpp
|
||||
xlat/parse_xlat.cpp
|
||||
fragglescript/t_func.cpp
|
||||
fragglescript/t_load.cpp
|
||||
|
@ -1113,15 +1016,23 @@ set (PCH_SOURCES
|
|||
r_data/voxels.cpp
|
||||
r_data/renderstyle.cpp
|
||||
r_data/r_interpolate.cpp
|
||||
scripting/thingdef.cpp
|
||||
scripting/thingdef_data.cpp
|
||||
scripting/thingdef_properties.cpp
|
||||
scripting/codegeneration/codegen.cpp
|
||||
scripting/decorate/olddecorations.cpp
|
||||
scripting/decorate/thingdef_exp.cpp
|
||||
scripting/decorate/thingdef_parse.cpp
|
||||
scripting/decorate/thingdef_states.cpp
|
||||
scripting/vm/vmbuilder.cpp
|
||||
scripting/vm/vmdisasm.cpp
|
||||
scripting/vm/vmexec.cpp
|
||||
scripting/vm/vmframe.cpp
|
||||
scripting/zscript/ast.cpp
|
||||
scripting/zscript/zcc_compile.cpp
|
||||
scripting/zscript/zcc_expr.cpp
|
||||
scripting/zscript/zcc_parser.cpp
|
||||
sfmt/SFMT.cpp
|
||||
zscript/ast.cpp
|
||||
zscript/vmbuilder.cpp
|
||||
zscript/vmdisasm.cpp
|
||||
zscript/vmexec.cpp
|
||||
zscript/vmframe.cpp
|
||||
zscript/zcc_compile.cpp
|
||||
zscript/zcc_expr.cpp
|
||||
zscript/zcc_parser.cpp
|
||||
)
|
||||
enable_precompiled_headers( g_pch.h PCH_SOURCES )
|
||||
|
||||
|
@ -1146,6 +1057,8 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
|
|||
math/log10.c
|
||||
math/mtherr.c
|
||||
math/polevl.c
|
||||
math/pow.c
|
||||
math/powi.c
|
||||
math/sin.c
|
||||
math/sinh.c
|
||||
math/sqrt.c
|
||||
|
@ -1171,19 +1084,16 @@ endif()
|
|||
|
||||
target_link_libraries( zdoom ${ZDOOM_LIBS} gdtoa dumb lzma )
|
||||
include_directories( .
|
||||
g_doom
|
||||
g_heretic
|
||||
g_hexen
|
||||
g_raven
|
||||
g_strife
|
||||
g_shared
|
||||
g_inventory
|
||||
sound
|
||||
textures
|
||||
thingdef
|
||||
timidity
|
||||
wildmidi
|
||||
xlat
|
||||
zscript
|
||||
scripting
|
||||
scripting/vm
|
||||
../gdtoa
|
||||
../dumb/include
|
||||
${CMAKE_BINARY_DIR}/gdtoa
|
||||
|
@ -1262,17 +1172,14 @@ source_group("Audio Files\\Timidity\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRE
|
|||
source_group("Audio Files\\Timidity\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.cpp$")
|
||||
source_group("Audio Files\\WildMidi\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/wildmidi/.+\\.h$")
|
||||
source_group("Audio Files\\WildMidi\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/wildmidi/.+\\.cpp$")
|
||||
source_group("Decorate++" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thingdef/.+")
|
||||
source_group("External\\Math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/math/.+")
|
||||
source_group("External\\RapidJSON" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rapidjson/.+")
|
||||
source_group("Externak\\SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+")
|
||||
source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+")
|
||||
source_group("Games\\Doom Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_doom/.+")
|
||||
source_group("Games\\Heretic Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_heretic/.+")
|
||||
source_group("Games\\Hexen Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_hexen/.+")
|
||||
source_group("Games\\Raven Shared" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_raven/.+")
|
||||
source_group("Games\\Strife Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_strife/.+")
|
||||
source_group("Intermission" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/intermission/.+")
|
||||
source_group("Math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/math/.+")
|
||||
source_group("Inventory" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_inventory/.+")
|
||||
source_group("Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/menu/.+")
|
||||
source_group("RapidJSON" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rapidjson/.+")
|
||||
source_group("OpenGL Renderer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/.+")
|
||||
source_group("OpenGL Renderer\\Data" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/data/.+")
|
||||
source_group("OpenGL Renderer\\Dynamic Lights" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/dynlights/.+")
|
||||
|
@ -1294,15 +1201,18 @@ source_group("Render Data\\Resource Sources" REGULAR_EXPRESSION "^${CMAKE_CURREN
|
|||
source_group("Render Data\\Textures" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/textures/.+")
|
||||
source_group("Render Interface" FILES r_defs.h r_renderer.h r_sky.cpp r_sky.h r_state.h r_utility.cpp r_utility.h)
|
||||
source_group("Resource Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/resourcefiles/.+")
|
||||
source_group("POSIX Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/.+")
|
||||
source_group("Cocoa Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/cocoa/.+")
|
||||
source_group("OS X Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/osx/.+")
|
||||
source_group("Unix Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/unix/.+")
|
||||
source_group("SDL Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/sdl/.+")
|
||||
source_group("SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+")
|
||||
source_group("Platforms\\POSIX Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/.+")
|
||||
source_group("Platforms\\Cocoa Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/cocoa/.+")
|
||||
source_group("Platforms\\OS X Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/osx/.+")
|
||||
source_group("Platforms\\Unix Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/unix/.+")
|
||||
source_group("Platforms\\SDL Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/sdl/.+")
|
||||
source_group("Platforms\\Win32 Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/win32/.+")
|
||||
source_group("Scripting\\Decorate" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/scripting/decorate/.+")
|
||||
source_group("Scripting\\ZScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/scripting/zscript/.+" FILES ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.c ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.h)
|
||||
source_group("Scripting\\Code Generation" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/scripting/codegeneration/.+")
|
||||
source_group("Scripting\\VM" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/scripting/vm/.+")
|
||||
source_group("Scripting" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/scripting/.+")
|
||||
source_group("Shared Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_shared/.+")
|
||||
source_group("Versioning" FILES version.h win32/zdoom.rc)
|
||||
source_group("Win32 Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/win32/.+")
|
||||
source_group("Xlat" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/xlat/.+" FILES ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.h)
|
||||
source_group("ZScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/zscript/.+" FILES ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.c ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.h)
|
||||
source_group("Source Files" FILES ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h sc_man_scanner.re)
|
||||
|
|
|
@ -52,8 +52,8 @@
|
|||
// a single section during the final link. (.rdata is the standard section
|
||||
// for initialized read-only data.)
|
||||
|
||||
#pragma comment(linker, "/merge:.areg=.rdata /merge:.creg=.rdata /merge:.greg=.rdata")
|
||||
#pragma comment(linker, "/merge:.yreg=.rdata")
|
||||
#pragma comment(linker, "/merge:.areg=.rdata /merge:.creg=.rdata /merge:.freg=.rdata")
|
||||
#pragma comment(linker, "/merge:.greg=.rdata /merge:.yreg=.rdata")
|
||||
|
||||
#pragma section(".areg$a",read)
|
||||
__declspec(allocate(".areg$a")) void *const ARegHead = 0;
|
||||
|
@ -61,6 +61,9 @@ __declspec(allocate(".areg$a")) void *const ARegHead = 0;
|
|||
#pragma section(".creg$a",read)
|
||||
__declspec(allocate(".creg$a")) void *const CRegHead = 0;
|
||||
|
||||
#pragma section(".freg$a",read)
|
||||
__declspec(allocate(".freg$a")) void *const FRegHead = 0;
|
||||
|
||||
#pragma section(".greg$a",read)
|
||||
__declspec(allocate(".greg$a")) void *const GRegHead = 0;
|
||||
|
||||
|
@ -97,6 +100,7 @@ __declspec(allocate(".yreg$a")) void *const YRegHead = 0;
|
|||
|
||||
void *const ARegHead __attribute__((section(SECTION_AREG))) = 0;
|
||||
void *const CRegHead __attribute__((section(SECTION_CREG))) = 0;
|
||||
void *const FRegHead __attribute__((section(SECTION_FREG))) = 0;
|
||||
void *const GRegHead __attribute__((section(SECTION_GREG))) = 0;
|
||||
void *const YRegHead __attribute__((section(SECTION_YREG))) = 0;
|
||||
|
||||
|
|
78
src/actor.h
78
src/actor.h
|
@ -386,6 +386,8 @@ enum ActorFlag7
|
|||
MF7_USEKILLSCRIPTS = 0x00800000, // [JM] Use "KILL" Script on death if not forced by GameInfo.
|
||||
MF7_NOKILLSCRIPTS = 0x01000000, // [JM] No "KILL" Script on death whatsoever, even if forced by GameInfo.
|
||||
MF7_SPRITEANGLE = 0x02000000, // [MC] Utilize the SpriteAngle property and lock the rotation to the degrees specified.
|
||||
MF7_SMASHABLE = 0x04000000, // dies if hitting the floor.
|
||||
MF7_NOSHIELDREFLECT = 0x08000000, // will not be reflected by shields.
|
||||
};
|
||||
|
||||
// --- mobj.renderflags ---
|
||||
|
@ -584,11 +586,13 @@ public:
|
|||
AActor () throw();
|
||||
AActor (const AActor &other) throw();
|
||||
AActor &operator= (const AActor &other);
|
||||
void Destroy ();
|
||||
~AActor ();
|
||||
|
||||
void Serialize(FSerializer &arc);
|
||||
void PostSerialize();
|
||||
virtual void Destroy() override;
|
||||
virtual void Serialize(FSerializer &arc) override;
|
||||
virtual void PostSerialize() override;
|
||||
virtual void PostBeginPlay() override; // Called immediately before the actor's first tick
|
||||
virtual void Tick() override;
|
||||
|
||||
static AActor *StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t allowreplacement, bool SpawningMapThing = false);
|
||||
|
||||
|
@ -612,43 +616,50 @@ public:
|
|||
bool CheckNoDelay();
|
||||
|
||||
virtual void BeginPlay(); // Called immediately after the actor is created
|
||||
virtual void PostBeginPlay(); // Called immediately before the actor's first tick
|
||||
virtual void LevelSpawned(); // Called after BeginPlay if this actor was spawned by the world
|
||||
void CallBeginPlay();
|
||||
|
||||
void LevelSpawned(); // Called after BeginPlay if this actor was spawned by the world
|
||||
virtual void HandleSpawnFlags(); // Translates SpawnFlags into in-game flags.
|
||||
|
||||
virtual void MarkPrecacheSounds() const; // Marks sounds used by this actor for precaching.
|
||||
|
||||
virtual void Activate (AActor *activator);
|
||||
virtual void Deactivate (AActor *activator);
|
||||
void CallActivate(AActor *activator);
|
||||
|
||||
virtual void Tick ();
|
||||
virtual void Deactivate(AActor *activator);
|
||||
void CallDeactivate(AActor *activator);
|
||||
|
||||
// Called when actor dies
|
||||
virtual void Die (AActor *source, AActor *inflictor, int dmgflags = 0);
|
||||
void CallDie(AActor *source, AActor *inflictor, int dmgflags = 0);
|
||||
|
||||
// Perform some special damage action. Returns the amount of damage to do.
|
||||
// Returning -1 signals the damage routine to exit immediately
|
||||
virtual int DoSpecialDamage (AActor *target, int damage, FName damagetype);
|
||||
int CallDoSpecialDamage(AActor *target, int damage, FName damagetype);
|
||||
|
||||
// Like DoSpecialDamage, but called on the actor receiving the damage.
|
||||
virtual int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype);
|
||||
int CallTakeSpecialDamage(AActor *inflictor, AActor *source, int damage, FName damagetype);
|
||||
|
||||
// Actor had MF_SKULLFLY set and rammed into something
|
||||
// Returns false to stop moving and true to keep moving
|
||||
virtual bool Slam(AActor *victim);
|
||||
bool CallSlam(AActor *victim);
|
||||
|
||||
// Something just touched this actor.
|
||||
virtual void Touch(AActor *toucher);
|
||||
void CallTouch(AActor *toucher);
|
||||
|
||||
// Centaurs and ettins squeal when electrocuted, poisoned, or "holy"-ed
|
||||
// Made a metadata property so no longer virtual
|
||||
void Howl ();
|
||||
|
||||
// Actor just hit the floor
|
||||
virtual void HitFloor ();
|
||||
|
||||
// plays bouncing sound
|
||||
void PlayBounceSound(bool onfloor);
|
||||
|
||||
// Called when an actor with MF_MISSILE and MF2_FLOORBOUNCE hits the floor
|
||||
virtual bool FloorBounceMissile (secplane_t &plane);
|
||||
|
||||
// Called when an actor is to be reflected by a disc of repulsion.
|
||||
// Returns true to continue normal blast processing.
|
||||
virtual bool SpecialBlastHandling (AActor *source, double strength);
|
||||
bool FloorBounceMissile (secplane_t &plane);
|
||||
|
||||
// Called by RoughBlockCheck
|
||||
bool IsOkayToAttack (AActor *target);
|
||||
|
@ -656,27 +667,28 @@ public:
|
|||
// Plays the actor's ActiveSound if its voice isn't already making noise.
|
||||
void PlayActiveSound ();
|
||||
|
||||
// Actor had MF_SKULLFLY set and rammed into something
|
||||
// Returns false to stop moving and true to keep moving
|
||||
virtual bool Slam (AActor *victim);
|
||||
void RestoreSpecialPosition();
|
||||
|
||||
// Called by PIT_CheckThing() and needed for some Hexen things.
|
||||
// Returns -1 for normal behavior, 0 to return false, and 1 to return true.
|
||||
// I'm not sure I like it this way, but it will do for now.
|
||||
virtual int SpecialMissileHit (AActor *victim);
|
||||
// (virtual on the script side only)
|
||||
int SpecialMissileHit (AActor *victim);
|
||||
|
||||
// Returns true if it's okay to switch target to "other" after being attacked by it.
|
||||
virtual bool OkayToSwitchTarget (AActor *other);
|
||||
bool OkayToSwitchTarget (AActor *other);
|
||||
|
||||
// Something just touched this actor.
|
||||
virtual void Touch (AActor *toucher);
|
||||
// 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.
|
||||
|
||||
// Adds the item to this actor's inventory and sets its Owner.
|
||||
virtual void AddInventory (AInventory *item);
|
||||
|
||||
// Give an item to the actor and pick it up.
|
||||
// Returns true if the item pickup succeeded.
|
||||
virtual bool GiveInventory (PClassInventory *type, int amount, bool givecheat = false);
|
||||
bool GiveInventory (PClassInventory *type, int amount, bool givecheat = false);
|
||||
|
||||
// Removes the item from the inventory list.
|
||||
virtual void RemoveInventory (AInventory *item);
|
||||
|
@ -690,7 +702,7 @@ public:
|
|||
virtual bool UseInventory (AInventory *item);
|
||||
|
||||
// Tosses an item out of the inventory.
|
||||
virtual AInventory *DropInventory (AInventory *item);
|
||||
AInventory *DropInventory (AInventory *item);
|
||||
|
||||
// Removes all items from the inventory.
|
||||
void ClearInventory();
|
||||
|
@ -732,7 +744,7 @@ public:
|
|||
void ObtainInventory (AActor *other);
|
||||
|
||||
// Die. Now.
|
||||
virtual bool Massacre ();
|
||||
bool Massacre ();
|
||||
|
||||
// Transforms the actor into a finely-ground paste
|
||||
virtual bool Grind(bool items);
|
||||
|
@ -754,10 +766,10 @@ public:
|
|||
DVector3 GetPortalTransition(double byoffset, sector_t **pSec = NULL);
|
||||
|
||||
// What species am I?
|
||||
virtual FName GetSpecies();
|
||||
FName GetSpecies();
|
||||
|
||||
// set translation
|
||||
void SetTranslation(const char *trname);
|
||||
void SetTranslation(FName trname);
|
||||
|
||||
double GetBobOffset(double ticfrac = 0) const
|
||||
{
|
||||
|
@ -957,7 +969,7 @@ public:
|
|||
{
|
||||
SetOrigin(Pos() + vel, true);
|
||||
}
|
||||
virtual void SetOrigin(double x, double y, double z, bool moving);
|
||||
void SetOrigin(double x, double y, double z, bool moving);
|
||||
void SetOrigin(const DVector3 & npos, bool moving)
|
||||
{
|
||||
SetOrigin(npos.X, npos.Y, npos.Z, moving);
|
||||
|
@ -969,7 +981,7 @@ public:
|
|||
bool IsInsideVisibleAngles() const;
|
||||
|
||||
// Calculate amount of missile damage
|
||||
virtual int GetMissileDamage(int mask, int add);
|
||||
int GetMissileDamage(int mask, int add);
|
||||
|
||||
bool CanSeek(AActor *target) const;
|
||||
|
||||
|
@ -1367,7 +1379,7 @@ public:
|
|||
Vel.Y = speed * Angles.Yaw.Sin();
|
||||
}
|
||||
|
||||
void VelFromAngle(DAngle angle, double speed)
|
||||
void VelFromAngle(double speed, DAngle angle)
|
||||
{
|
||||
Vel.X = speed * angle.Cos();
|
||||
Vel.Y = speed * angle.Sin();
|
||||
|
@ -1415,6 +1427,7 @@ public:
|
|||
}
|
||||
|
||||
int ApplyDamageFactor(FName damagetype, int damage) const;
|
||||
int GetModifiedDamage(FName damagetype, int damage, bool passive);
|
||||
|
||||
|
||||
// begin of GZDoom specific additions
|
||||
|
@ -1449,6 +1462,10 @@ public:
|
|||
|
||||
return base;
|
||||
}
|
||||
void Reinit()
|
||||
{
|
||||
base = nullptr;
|
||||
}
|
||||
private:
|
||||
AActor *base;
|
||||
int id;
|
||||
|
@ -1532,6 +1549,7 @@ struct FTranslatedLineTarget
|
|||
{
|
||||
AActor *linetarget;
|
||||
DAngle angleFromSource;
|
||||
DAngle attackAngleFromSource;
|
||||
bool unlinked; // found by a trace that went through an unlinked portal.
|
||||
};
|
||||
|
||||
|
|
|
@ -474,6 +474,11 @@ static AMColorset AMMod;
|
|||
static AMColorset AMModOverlay;
|
||||
|
||||
|
||||
void AM_ClearColorsets()
|
||||
{
|
||||
AMModOverlay.defined = false;
|
||||
AMMod.defined = false;
|
||||
}
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -2964,8 +2969,8 @@ void AM_drawAuthorMarkers ()
|
|||
// [RH] Draw any actors derived from AMapMarker on the automap.
|
||||
// If args[0] is 0, then the actor's sprite is drawn at its own location.
|
||||
// Otherwise, its sprite is drawn at the location of any actors whose TIDs match args[0].
|
||||
TThinkerIterator<AMapMarker> it (STAT_MAPMARKER);
|
||||
AMapMarker *mark;
|
||||
TThinkerIterator<AActor> it ("MapMarker", STAT_MAPMARKER);
|
||||
AActor *mark;
|
||||
|
||||
while ((mark = it.Next()) != NULL)
|
||||
{
|
||||
|
|
|
@ -28,6 +28,7 @@ class FSerializer;
|
|||
|
||||
|
||||
void AM_StaticInit();
|
||||
void AM_ClearColorsets(); // reset data for a restart.
|
||||
|
||||
// Called by main loop.
|
||||
bool AM_Responder (event_t* ev, bool last);
|
||||
|
|
|
@ -49,6 +49,10 @@ extern REGINFO ARegTail;
|
|||
extern REGINFO CRegHead;
|
||||
extern REGINFO CRegTail;
|
||||
|
||||
// List of class fields
|
||||
extern REGINFO FRegHead;
|
||||
extern REGINFO FRegTail;
|
||||
|
||||
// List of properties
|
||||
extern REGINFO GRegHead;
|
||||
extern REGINFO GRegTail;
|
||||
|
|
|
@ -15,14 +15,16 @@
|
|||
#include "serializer.h"
|
||||
#include "d_player.h"
|
||||
|
||||
IMPLEMENT_POINTY_CLASS(DBot)
|
||||
DECLARE_POINTER(dest)
|
||||
DECLARE_POINTER(prev)
|
||||
DECLARE_POINTER(enemy)
|
||||
DECLARE_POINTER(missile)
|
||||
DECLARE_POINTER(mate)
|
||||
DECLARE_POINTER(last_mate)
|
||||
END_POINTERS
|
||||
IMPLEMENT_CLASS(DBot, false, true)
|
||||
|
||||
IMPLEMENT_POINTERS_START(DBot)
|
||||
IMPLEMENT_POINTER(dest)
|
||||
IMPLEMENT_POINTER(prev)
|
||||
IMPLEMENT_POINTER(enemy)
|
||||
IMPLEMENT_POINTER(missile)
|
||||
IMPLEMENT_POINTER(mate)
|
||||
IMPLEMENT_POINTER(last_mate)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
DBot::DBot ()
|
||||
: DThinker(STAT_BOT)
|
||||
|
|
|
@ -193,7 +193,7 @@ void DBot::Dofire (ticcmd_t *cmd)
|
|||
else
|
||||
{
|
||||
//*4 is for atmosphere, the chainsaws sounding and all..
|
||||
no_fire = (Dist > MELEERANGE*4);
|
||||
no_fire = (Dist > DEFMELEERANGE*4);
|
||||
}
|
||||
}
|
||||
else if (player->ReadyWeapon->WeaponFlags & WIF_BOT_BFG)
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "d_event.h"
|
||||
#include "d_player.h"
|
||||
#include "vectors.h"
|
||||
#include "a_ammo.h"
|
||||
#include "a_health.h"
|
||||
|
||||
static FRandom pr_botmove ("BotMove");
|
||||
|
||||
|
|
|
@ -1,199 +0,0 @@
|
|||
// This file is based on pragmas.h from Ken Silverman's original Build
|
||||
// source code release. The functions in here are so simple and so
|
||||
// basic that they can't be rewritten without being copycats of
|
||||
// themselves. As such, they are uncopyrightable.
|
||||
|
||||
#if _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && !defined(__forceinline)
|
||||
#define __forceinline __inline__ __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
static __forceinline SDWORD Scale (SDWORD a, SDWORD b, SDWORD c)
|
||||
{
|
||||
return (SDWORD)(((SQWORD)a*b)/c);
|
||||
}
|
||||
|
||||
static __forceinline SDWORD MulScale (SDWORD a, SDWORD b, SDWORD c)
|
||||
{
|
||||
return (SDWORD)(((SQWORD)a*b)>>c);
|
||||
}
|
||||
|
||||
static __forceinline SDWORD MulScale1 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 1); }
|
||||
static __forceinline SDWORD MulScale2 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 2); }
|
||||
static __forceinline SDWORD MulScale3 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 3); }
|
||||
static __forceinline SDWORD MulScale4 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 4); }
|
||||
static __forceinline SDWORD MulScale5 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 5); }
|
||||
static __forceinline SDWORD MulScale6 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 6); }
|
||||
static __forceinline SDWORD MulScale7 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 7); }
|
||||
static __forceinline SDWORD MulScale8 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 8); }
|
||||
static __forceinline SDWORD MulScale9 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 9); }
|
||||
static __forceinline SDWORD MulScale10 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 10); }
|
||||
static __forceinline SDWORD MulScale11 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 11); }
|
||||
static __forceinline SDWORD MulScale12 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 12); }
|
||||
static __forceinline SDWORD MulScale13 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 13); }
|
||||
static __forceinline SDWORD MulScale14 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 14); }
|
||||
static __forceinline SDWORD MulScale15 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 15); }
|
||||
static __forceinline SDWORD MulScale16 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 16); }
|
||||
static __forceinline SDWORD MulScale17 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 17); }
|
||||
static __forceinline SDWORD MulScale18 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 18); }
|
||||
static __forceinline SDWORD MulScale19 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 19); }
|
||||
static __forceinline SDWORD MulScale20 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 20); }
|
||||
static __forceinline SDWORD MulScale21 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 21); }
|
||||
static __forceinline SDWORD MulScale22 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 22); }
|
||||
static __forceinline SDWORD MulScale23 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 23); }
|
||||
static __forceinline SDWORD MulScale24 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 24); }
|
||||
static __forceinline SDWORD MulScale25 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 25); }
|
||||
static __forceinline SDWORD MulScale26 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 26); }
|
||||
static __forceinline SDWORD MulScale27 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 27); }
|
||||
static __forceinline SDWORD MulScale28 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 28); }
|
||||
static __forceinline SDWORD MulScale29 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 29); }
|
||||
static __forceinline SDWORD MulScale30 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 30); }
|
||||
static __forceinline SDWORD MulScale31 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 31); }
|
||||
static __forceinline SDWORD MulScale32 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 32); }
|
||||
|
||||
static __forceinline DWORD UMulScale16 (DWORD a, DWORD b) { return (DWORD)(((QWORD)a * b) >> 16); }
|
||||
|
||||
static __forceinline SDWORD DMulScale (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD s)
|
||||
{
|
||||
return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> s);
|
||||
}
|
||||
|
||||
static __forceinline SDWORD DMulScale1 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 1); }
|
||||
static __forceinline SDWORD DMulScale2 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 2); }
|
||||
static __forceinline SDWORD DMulScale3 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 3); }
|
||||
static __forceinline SDWORD DMulScale4 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 4); }
|
||||
static __forceinline SDWORD DMulScale5 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 5); }
|
||||
static __forceinline SDWORD DMulScale6 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 6); }
|
||||
static __forceinline SDWORD DMulScale7 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 7); }
|
||||
static __forceinline SDWORD DMulScale8 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 8); }
|
||||
static __forceinline SDWORD DMulScale9 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 9); }
|
||||
static __forceinline SDWORD DMulScale10 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 10); }
|
||||
static __forceinline SDWORD DMulScale11 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 11); }
|
||||
static __forceinline SDWORD DMulScale12 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 12); }
|
||||
static __forceinline SDWORD DMulScale13 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 13); }
|
||||
static __forceinline SDWORD DMulScale14 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 14); }
|
||||
static __forceinline SDWORD DMulScale15 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 15); }
|
||||
static __forceinline SDWORD DMulScale16 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 16); }
|
||||
static __forceinline SDWORD DMulScale17 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 17); }
|
||||
static __forceinline SDWORD DMulScale18 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 18); }
|
||||
static __forceinline SDWORD DMulScale19 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 19); }
|
||||
static __forceinline SDWORD DMulScale20 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 20); }
|
||||
static __forceinline SDWORD DMulScale21 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 21); }
|
||||
static __forceinline SDWORD DMulScale22 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 22); }
|
||||
static __forceinline SDWORD DMulScale23 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 23); }
|
||||
static __forceinline SDWORD DMulScale24 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 24); }
|
||||
static __forceinline SDWORD DMulScale25 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 25); }
|
||||
static __forceinline SDWORD DMulScale26 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 26); }
|
||||
static __forceinline SDWORD DMulScale27 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 27); }
|
||||
static __forceinline SDWORD DMulScale28 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 28); }
|
||||
static __forceinline SDWORD DMulScale29 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 29); }
|
||||
static __forceinline SDWORD DMulScale30 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 30); }
|
||||
static __forceinline SDWORD DMulScale31 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 31); }
|
||||
static __forceinline SDWORD DMulScale32 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 32); }
|
||||
|
||||
static __forceinline SDWORD TMulScale1 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 1); }
|
||||
static __forceinline SDWORD TMulScale2 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 2); }
|
||||
static __forceinline SDWORD TMulScale3 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 3); }
|
||||
static __forceinline SDWORD TMulScale4 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 4); }
|
||||
static __forceinline SDWORD TMulScale5 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 5); }
|
||||
static __forceinline SDWORD TMulScale6 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 6); }
|
||||
static __forceinline SDWORD TMulScale7 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 7); }
|
||||
static __forceinline SDWORD TMulScale8 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 8); }
|
||||
static __forceinline SDWORD TMulScale9 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 9); }
|
||||
static __forceinline SDWORD TMulScale10 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 10); }
|
||||
static __forceinline SDWORD TMulScale11 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 11); }
|
||||
static __forceinline SDWORD TMulScale12 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 12); }
|
||||
static __forceinline SDWORD TMulScale13 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 13); }
|
||||
static __forceinline SDWORD TMulScale14 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 14); }
|
||||
static __forceinline SDWORD TMulScale15 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 15); }
|
||||
static __forceinline SDWORD TMulScale16 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 16); }
|
||||
static __forceinline SDWORD TMulScale17 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 17); }
|
||||
static __forceinline SDWORD TMulScale18 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 18); }
|
||||
static __forceinline SDWORD TMulScale19 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 19); }
|
||||
static __forceinline SDWORD TMulScale20 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 20); }
|
||||
static __forceinline SDWORD TMulScale21 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 21); }
|
||||
static __forceinline SDWORD TMulScale22 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 22); }
|
||||
static __forceinline SDWORD TMulScale23 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 23); }
|
||||
static __forceinline SDWORD TMulScale24 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 24); }
|
||||
static __forceinline SDWORD TMulScale25 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 25); }
|
||||
static __forceinline SDWORD TMulScale26 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 26); }
|
||||
static __forceinline SDWORD TMulScale27 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 27); }
|
||||
static __forceinline SDWORD TMulScale28 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 28); }
|
||||
static __forceinline SDWORD TMulScale29 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 29); }
|
||||
static __forceinline SDWORD TMulScale30 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 30); }
|
||||
static __forceinline SDWORD TMulScale31 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 31); }
|
||||
static __forceinline SDWORD TMulScale32 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 32); }
|
||||
|
||||
static __forceinline SDWORD BoundMulScale (SDWORD a, SDWORD b, SDWORD c)
|
||||
{
|
||||
SQWORD x = ((SQWORD)a * b) >> c;
|
||||
return x > 0x7FFFFFFFll ? 0x7FFFFFFF :
|
||||
x < -0x80000000ll ? 0x80000000 :
|
||||
(SDWORD)x;
|
||||
}
|
||||
|
||||
static inline SDWORD DivScale (SDWORD a, SDWORD b, SDWORD c)
|
||||
{
|
||||
return (SDWORD)(((SQWORD)a << c) / b);
|
||||
}
|
||||
|
||||
static inline SDWORD DivScale1 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 1) / b); }
|
||||
static inline SDWORD DivScale2 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 2) / b); }
|
||||
static inline SDWORD DivScale3 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 3) / b); }
|
||||
static inline SDWORD DivScale4 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 4) / b); }
|
||||
static inline SDWORD DivScale5 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 5) / b); }
|
||||
static inline SDWORD DivScale6 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 6) / b); }
|
||||
static inline SDWORD DivScale7 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 7) / b); }
|
||||
static inline SDWORD DivScale8 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 8) / b); }
|
||||
static inline SDWORD DivScale9 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 9) / b); }
|
||||
static inline SDWORD DivScale10 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 10) / b); }
|
||||
static inline SDWORD DivScale11 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 11) / b); }
|
||||
static inline SDWORD DivScale12 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 12) / b); }
|
||||
static inline SDWORD DivScale13 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 13) / b); }
|
||||
static inline SDWORD DivScale14 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 14) / b); }
|
||||
static inline SDWORD DivScale15 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 15) / b); }
|
||||
static inline SDWORD DivScale16 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 16) / b); }
|
||||
static inline SDWORD DivScale17 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 17) / b); }
|
||||
static inline SDWORD DivScale18 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 18) / b); }
|
||||
static inline SDWORD DivScale19 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 19) / b); }
|
||||
static inline SDWORD DivScale20 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 20) / b); }
|
||||
static inline SDWORD DivScale21 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 21) / b); }
|
||||
static inline SDWORD DivScale22 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 22) / b); }
|
||||
static inline SDWORD DivScale23 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 23) / b); }
|
||||
static inline SDWORD DivScale24 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 24) / b); }
|
||||
static inline SDWORD DivScale25 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 25) / b); }
|
||||
static inline SDWORD DivScale26 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 26) / b); }
|
||||
static inline SDWORD DivScale27 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 27) / b); }
|
||||
static inline SDWORD DivScale28 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 28) / b); }
|
||||
static inline SDWORD DivScale29 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 29) / b); }
|
||||
static inline SDWORD DivScale30 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 30) / b); }
|
||||
static inline SDWORD DivScale31 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 31) / b); }
|
||||
static inline SDWORD DivScale32 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 32) / b); }
|
||||
|
||||
static __forceinline void clearbuf (void *buff, unsigned int count, SDWORD clear)
|
||||
{
|
||||
SDWORD *b2 = (SDWORD *)buff;
|
||||
for (unsigned int i = 0; i != count; ++i)
|
||||
{
|
||||
b2[i] = clear;
|
||||
}
|
||||
}
|
||||
|
||||
static __forceinline void clearbufshort (void *buff, unsigned int count, WORD clear)
|
||||
{
|
||||
SWORD *b2 = (SWORD *)buff;
|
||||
for (unsigned int i = 0; i != count; ++i)
|
||||
{
|
||||
b2[i] = clear;
|
||||
}
|
||||
}
|
||||
|
||||
static __forceinline SDWORD ksgn (SDWORD a)
|
||||
{
|
||||
if (a < 0) return -1;
|
||||
else if (a > 0) return 1;
|
||||
else return 0;
|
||||
}
|
|
@ -906,6 +906,16 @@ CCMD(info)
|
|||
"the NOBLOCKMAP flag or have height/radius of 0.\n");
|
||||
}
|
||||
|
||||
CCMD(myinfo)
|
||||
{
|
||||
if (CheckCheatmode () || players[consoleplayer].mo == NULL) return;
|
||||
Printf("Target=%s, Health=%d, Spawnhealth=%d\n",
|
||||
players[consoleplayer].mo->GetClass()->TypeName.GetChars(),
|
||||
players[consoleplayer].mo->health,
|
||||
players[consoleplayer].mo->SpawnHealth());
|
||||
PrintMiscActorInfo(players[consoleplayer].mo);
|
||||
}
|
||||
|
||||
typedef bool (*ActorTypeChecker) (AActor *);
|
||||
|
||||
static bool IsActorAMonster(AActor *mo)
|
||||
|
@ -1144,7 +1154,7 @@ CCMD(currentpos)
|
|||
}
|
||||
else
|
||||
{
|
||||
Printf("You are not in game!");
|
||||
Printf("You are not in game!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include "g_level.h"
|
||||
#include "d_event.h"
|
||||
#include "d_player.h"
|
||||
#include "gstrings.h"
|
||||
#include "c_consolebuffer.h"
|
||||
|
||||
#include "gi.h"
|
||||
|
@ -1522,8 +1523,6 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer)
|
|||
|
||||
buffer.Text.StripLeftRight();
|
||||
Printf(127, TEXTCOLOR_WHITE "]%s\n", buffer.Text.GetChars());
|
||||
AddCommandString(buffer.Text.LockBuffer());
|
||||
buffer.Text.UnlockBuffer();
|
||||
|
||||
if (buffer.Text.Len() == 0)
|
||||
{
|
||||
|
@ -1567,7 +1566,21 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer)
|
|||
}
|
||||
}
|
||||
HistPos = NULL;
|
||||
buffer.SetString("");
|
||||
{
|
||||
// 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(length + 1);
|
||||
memcpy(&command[0], buffer.Text.GetChars(), length);
|
||||
command[length] = '\0';
|
||||
|
||||
buffer.SetString("");
|
||||
|
||||
AddCommandString(&command[0]);
|
||||
}
|
||||
TabbedLast = false;
|
||||
TabbedList = false;
|
||||
break;
|
||||
|
@ -1729,6 +1742,20 @@ void C_MidPrintBold (FFont *font, const char *msg)
|
|||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DObject, C_MidPrint)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_STRING(font);
|
||||
PARAM_STRING(text);
|
||||
PARAM_BOOL_DEF(bold);
|
||||
|
||||
FFont *fnt = FFont::FindFont(font);
|
||||
const char *txt = text[0] == '$'? GStrings(&text[1]) : text.GetChars();
|
||||
if (!bold) C_MidPrint(fnt, txt);
|
||||
else C_MidPrintBold(fnt, txt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****** Tab completion code ******/
|
||||
|
||||
struct TabData
|
||||
|
|
|
@ -1093,7 +1093,7 @@ BitVal (bitval)
|
|||
|
||||
ECVarType FFlagCVar::GetRealType () const
|
||||
{
|
||||
return CVAR_Dummy;
|
||||
return CVAR_DummyBool;
|
||||
}
|
||||
|
||||
UCVarValue FFlagCVar::GetGenericRep (ECVarType type) const
|
||||
|
@ -1197,7 +1197,7 @@ BitVal (bitval)
|
|||
|
||||
ECVarType FMaskCVar::GetRealType () const
|
||||
{
|
||||
return CVAR_Dummy;
|
||||
return CVAR_DummyInt;
|
||||
}
|
||||
|
||||
UCVarValue FMaskCVar::GetGenericRep (ECVarType type) const
|
||||
|
|
|
@ -81,13 +81,17 @@ enum ECVarType
|
|||
CVAR_Float,
|
||||
CVAR_String,
|
||||
CVAR_Color, // stored as CVAR_Int
|
||||
CVAR_Dummy, // just redirects to another cvar
|
||||
CVAR_DummyBool, // just redirects to another cvar
|
||||
CVAR_DummyInt, // just redirects to another cvar
|
||||
CVAR_Dummy, // Unknown
|
||||
CVAR_GUID
|
||||
};
|
||||
|
||||
class FConfigFile;
|
||||
class AActor;
|
||||
|
||||
class FxCVar;
|
||||
|
||||
class FBaseCVar
|
||||
{
|
||||
public:
|
||||
|
@ -211,6 +215,7 @@ void C_DeinitConsole();
|
|||
|
||||
class FBoolCVar : public FBaseCVar
|
||||
{
|
||||
friend class FxCVar;
|
||||
public:
|
||||
FBoolCVar (const char *name, bool def, uint32 flags, void (*callback)(FBoolCVar &)=NULL);
|
||||
|
||||
|
@ -236,6 +241,7 @@ protected:
|
|||
|
||||
class FIntCVar : public FBaseCVar
|
||||
{
|
||||
friend class FxCVar;
|
||||
public:
|
||||
FIntCVar (const char *name, int def, uint32 flags, void (*callback)(FIntCVar &)=NULL);
|
||||
|
||||
|
@ -263,6 +269,7 @@ protected:
|
|||
|
||||
class FFloatCVar : public FBaseCVar
|
||||
{
|
||||
friend class FxCVar;
|
||||
public:
|
||||
FFloatCVar (const char *name, float def, uint32 flags, void (*callback)(FFloatCVar &)=NULL);
|
||||
|
||||
|
@ -289,6 +296,7 @@ protected:
|
|||
|
||||
class FStringCVar : public FBaseCVar
|
||||
{
|
||||
friend class FxCVar;
|
||||
public:
|
||||
FStringCVar (const char *name, const char *def, uint32 flags, void (*callback)(FStringCVar &)=NULL);
|
||||
~FStringCVar ();
|
||||
|
@ -315,6 +323,7 @@ protected:
|
|||
|
||||
class FColorCVar : public FIntCVar
|
||||
{
|
||||
friend class FxCVar;
|
||||
public:
|
||||
FColorCVar (const char *name, int def, uint32 flags, void (*callback)(FColorCVar &)=NULL);
|
||||
|
||||
|
@ -339,6 +348,7 @@ protected:
|
|||
|
||||
class FFlagCVar : public FBaseCVar
|
||||
{
|
||||
friend class FxCVar;
|
||||
public:
|
||||
FFlagCVar (const char *name, FIntCVar &realvar, uint32 bitval);
|
||||
|
||||
|
@ -367,6 +377,7 @@ protected:
|
|||
|
||||
class FMaskCVar : public FBaseCVar
|
||||
{
|
||||
friend class FxCVar;
|
||||
public:
|
||||
FMaskCVar (const char *name, FIntCVar &realvar, uint32 bitval);
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ static const char *KeyConfCommands[] =
|
|||
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CLASS (DWaitingCommand)
|
||||
IMPLEMENT_CLASS(DWaitingCommand, false, false)
|
||||
|
||||
void DWaitingCommand::Serialize(FSerializer &arc)
|
||||
{
|
||||
|
@ -225,7 +225,7 @@ void DWaitingCommand::Tick ()
|
|||
}
|
||||
}
|
||||
|
||||
IMPLEMENT_CLASS (DStoredCommand)
|
||||
IMPLEMENT_CLASS(DStoredCommand, false, false)
|
||||
|
||||
DStoredCommand::DStoredCommand ()
|
||||
{
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "cmdlib.h"
|
||||
#include "i_system.h"
|
||||
#include "v_text.h"
|
||||
#include "sc_man.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -324,7 +325,7 @@ FString ExtractFileBase (const char *path, bool include_extension)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int ParseHex (const char *hex)
|
||||
int ParseHex (const char *hex, FScriptPosition *sc)
|
||||
{
|
||||
const char *str;
|
||||
int num;
|
||||
|
@ -342,7 +343,8 @@ int ParseHex (const char *hex)
|
|||
else if (*str >= 'A' && *str <= 'F')
|
||||
num += 10 + *str-'A';
|
||||
else {
|
||||
Printf ("Bad hex number: %s\n",hex);
|
||||
if (!sc) Printf ("Bad hex number: %s\n",hex);
|
||||
else sc->Message(MSG_WARNING, "Bad hex number: %s", hex);
|
||||
return 0;
|
||||
}
|
||||
str++;
|
||||
|
@ -351,21 +353,6 @@ int ParseHex (const char *hex)
|
|||
return num;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ParseNum
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int ParseNum (const char *str)
|
||||
{
|
||||
if (str[0] == '$')
|
||||
return ParseHex (str+1);
|
||||
if (str[0] == '0' && str[1] == 'x')
|
||||
return ParseHex (str+2);
|
||||
return atol (str);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// IsNum
|
||||
|
@ -632,7 +619,10 @@ int strbin (char *str)
|
|||
if (*p >= '0' && *p <= '7')
|
||||
c += *p-'0';
|
||||
else
|
||||
{
|
||||
p--;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
*str++ = c;
|
||||
|
@ -732,7 +722,10 @@ FString strbin1 (const char *start)
|
|||
if (*p >= '0' && *p <= '7')
|
||||
c += *p-'0';
|
||||
else
|
||||
{
|
||||
p--;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
result << c;
|
||||
|
|
|
@ -33,8 +33,8 @@ void DefaultExtension (FString &path, const char *extension);
|
|||
FString ExtractFilePath (const char *path);
|
||||
FString ExtractFileBase (const char *path, bool keep_extension=false);
|
||||
|
||||
int ParseHex (const char *str);
|
||||
int ParseNum (const char *str);
|
||||
struct FScriptPosition;
|
||||
int ParseHex(const char *str, FScriptPosition *sc = nullptr);
|
||||
bool IsNum (const char *str); // [RH] added
|
||||
|
||||
char *copystring(const char *s);
|
||||
|
|
|
@ -80,6 +80,7 @@ enum
|
|||
CP_CLEARSPECIAL,
|
||||
CP_SETACTIVATION,
|
||||
CP_SECTORFLOOROFFSET,
|
||||
CP_SETSECTORSPECIAL,
|
||||
CP_SETWALLYSCALE,
|
||||
CP_SETTHINGZ,
|
||||
CP_SETTAG,
|
||||
|
@ -294,6 +295,15 @@ void ParseCompatibility()
|
|||
sc.MustGetFloat();
|
||||
CompatParams.Push(int(sc.Float*65536.));
|
||||
}
|
||||
else if (sc.Compare("setsectorspecial"))
|
||||
{
|
||||
if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
|
||||
CompatParams.Push(CP_SETSECTORSPECIAL);
|
||||
sc.MustGetNumber();
|
||||
CompatParams.Push(sc.Number);
|
||||
sc.MustGetNumber();
|
||||
CompatParams.Push(sc.Number);
|
||||
}
|
||||
else if (sc.Compare("setwallyscale"))
|
||||
{
|
||||
if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
|
||||
|
@ -529,6 +539,16 @@ void SetCompatibilityParams()
|
|||
i += 3;
|
||||
break;
|
||||
}
|
||||
case CP_SETSECTORSPECIAL:
|
||||
{
|
||||
const int index = CompatParams[i + 1];
|
||||
if (index < numsectors)
|
||||
{
|
||||
sectors[index].special = CompatParams[i + 2];
|
||||
}
|
||||
i += 3;
|
||||
break;
|
||||
}
|
||||
case CP_SETWALLYSCALE:
|
||||
{
|
||||
if (CompatParams[i+1] < numlines)
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "templates.h"
|
||||
#include "d_net.h"
|
||||
#include "d_event.h"
|
||||
#include "a_armor.h"
|
||||
|
||||
#define QUEUESIZE 128
|
||||
#define MESSAGESIZE 128
|
||||
|
|
|
@ -70,7 +70,13 @@
|
|||
#include "doomerrors.h"
|
||||
#include "p_effect.h"
|
||||
#include "serializer.h"
|
||||
#include "thingdef.h"
|
||||
#include "info.h"
|
||||
#include "v_text.h"
|
||||
#include "vmbuilder.h"
|
||||
#include "a_armor.h"
|
||||
#include "a_ammo.h"
|
||||
#include "a_health.h"
|
||||
|
||||
// [SO] Just the way Randy said to do it :)
|
||||
// [RH] Made this CVAR_SERVERINFO
|
||||
|
@ -163,36 +169,25 @@ static TArray<CodePointerAlias> MBFCodePointers;
|
|||
|
||||
struct AmmoPerAttack
|
||||
{
|
||||
VMNativeFunction **func;
|
||||
ENamedName func;
|
||||
int ammocount;
|
||||
VMFunction *ptr;
|
||||
};
|
||||
|
||||
DECLARE_ACTION(A_Punch)
|
||||
DECLARE_ACTION(A_FirePistol)
|
||||
DECLARE_ACTION(A_FireShotgun)
|
||||
DECLARE_ACTION(A_FireShotgun2)
|
||||
DECLARE_ACTION(A_FireCGun)
|
||||
DECLARE_ACTION(A_FireMissile)
|
||||
DECLARE_ACTION(A_Saw)
|
||||
DECLARE_ACTION(A_FirePlasma)
|
||||
DECLARE_ACTION(A_FireBFG)
|
||||
DECLARE_ACTION(A_FireOldBFG)
|
||||
DECLARE_ACTION(A_FireRailgun)
|
||||
|
||||
// Default ammo use of the various weapon attacks
|
||||
static AmmoPerAttack AmmoPerAttacks[] = {
|
||||
{ &A_Punch_VMPtr, 0},
|
||||
{ &A_FirePistol_VMPtr, 1},
|
||||
{ &A_FireShotgun_VMPtr, 1},
|
||||
{ &A_FireShotgun2_VMPtr, 2},
|
||||
{ &A_FireCGun_VMPtr, 1},
|
||||
{ &A_FireMissile_VMPtr, 1},
|
||||
{ &A_Saw_VMPtr, 0},
|
||||
{ &A_FirePlasma_VMPtr, 1},
|
||||
{ &A_FireBFG_VMPtr, -1}, // uses deh.BFGCells
|
||||
{ &A_FireOldBFG_VMPtr, 1},
|
||||
{ &A_FireRailgun_VMPtr, 1},
|
||||
{ NULL, 0}
|
||||
{ NAME_A_Punch, 0},
|
||||
{ NAME_A_FirePistol, 1},
|
||||
{ NAME_A_FireShotgun, 1},
|
||||
{ NAME_A_FireShotgun2, 2},
|
||||
{ NAME_A_FireCGun, 1},
|
||||
{ NAME_A_FireMissile, 1},
|
||||
{ NAME_A_Saw, 0},
|
||||
{ NAME_A_FirePlasma, 1},
|
||||
{ NAME_A_FireBFG, -1}, // uses deh.BFGCells
|
||||
{ NAME_A_FireOldBFG, 1},
|
||||
{ NAME_A_FireRailgun, 1},
|
||||
{ NAME_None, 0}
|
||||
};
|
||||
|
||||
|
||||
|
@ -220,6 +215,12 @@ DehInfo deh =
|
|||
40, // BFG cells per shot
|
||||
};
|
||||
|
||||
DEFINE_FIELD_X(DehInfo, DehInfo, MaxSoulsphere)
|
||||
DEFINE_FIELD_X(DehInfo, DehInfo, ExplosionStyle)
|
||||
DEFINE_FIELD_X(DehInfo, DehInfo, ExplosionAlpha)
|
||||
DEFINE_FIELD_X(DehInfo, DehInfo, NoAutofreeze)
|
||||
DEFINE_FIELD_X(DehInfo, DehInfo, BFGCells)
|
||||
|
||||
// Doom identified pickup items by their sprites. ZDoom prefers to use their
|
||||
// class type to identify them instead. To support the traditional Doom
|
||||
// behavior, for every thing touched by dehacked that has the MF_PICKUP flag,
|
||||
|
@ -227,9 +228,11 @@ DehInfo deh =
|
|||
// from the original actor's defaults. The original actor is then changed to
|
||||
// spawn the new class.
|
||||
|
||||
IMPLEMENT_POINTY_CLASS (ADehackedPickup)
|
||||
DECLARE_POINTER (RealPickup)
|
||||
END_POINTERS
|
||||
IMPLEMENT_CLASS(ADehackedPickup, false, true)
|
||||
|
||||
IMPLEMENT_POINTERS_START(ADehackedPickup)
|
||||
IMPLEMENT_POINTER(RealPickup)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
TArray<PClassActor *> TouchedActors;
|
||||
|
||||
|
@ -794,7 +797,7 @@ void SetDehParams(FState *state, int codepointer)
|
|||
|
||||
// Let's identify the codepointer we're dealing with.
|
||||
PFunction *sym;
|
||||
sym = dyn_cast<PFunction>(RUNTIME_CLASS(AInventory)->Symbols.FindSymbol(FName(MBFCodePointers[codepointer].name), true));
|
||||
sym = dyn_cast<PFunction>(RUNTIME_CLASS(AStateProvider)->Symbols.FindSymbol(FName(MBFCodePointers[codepointer].name), true));
|
||||
if (sym == NULL) return;
|
||||
|
||||
if (codepointer < 0 || (unsigned)codepointer >= countof(MBFCodePointerFactories))
|
||||
|
@ -804,22 +807,26 @@ void SetDehParams(FState *state, int codepointer)
|
|||
}
|
||||
else
|
||||
{
|
||||
VMFunctionBuilder buildit;
|
||||
int numargs = sym->GetImplicitArgs();
|
||||
VMFunctionBuilder buildit(numargs);
|
||||
// Allocate registers used to pass parameters in.
|
||||
// self, stateowner, state (all are pointers)
|
||||
buildit.Registers[REGT_POINTER].Get(NAP);
|
||||
buildit.Registers[REGT_POINTER].Get(numargs);
|
||||
// Emit code to pass the standard action function parameters.
|
||||
for (int i = 0; i < NAP; i++)
|
||||
for (int i = 0; i < numargs; i++)
|
||||
{
|
||||
buildit.Emit(OP_PARAM, 0, REGT_POINTER, i);
|
||||
}
|
||||
// Emit code for action parameters.
|
||||
int argcount = MBFCodePointerFactories[codepointer](buildit, value1, value2);
|
||||
buildit.Emit(OP_TAIL_K, buildit.GetConstantAddress(sym->Variants[0].Implementation, ATAG_OBJECT), NAP + argcount, 0);
|
||||
buildit.Emit(OP_TAIL_K, buildit.GetConstantAddress(sym->Variants[0].Implementation, ATAG_OBJECT), numargs + argcount, 0);
|
||||
// Attach it to the state.
|
||||
VMScriptFunction *sfunc = buildit.MakeFunction();
|
||||
sfunc->NumArgs = NAP;
|
||||
VMScriptFunction *sfunc = new VMScriptFunction;
|
||||
buildit.MakeFunction(sfunc);
|
||||
sfunc->NumArgs = numargs;
|
||||
sfunc->ImplicitArgs = numargs;
|
||||
state->SetAction(sfunc);
|
||||
sfunc->PrintableName.Format("Dehacked.%s.%d.%d", MBFCodePointers[codepointer].name.GetChars(), value1, value2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1466,15 +1473,16 @@ static int PatchFrame (int frameNum)
|
|||
|
||||
if (info != &dummy)
|
||||
{
|
||||
info->DefineFlags |= SDF_DEHACKED; // Signals the state has been modified by dehacked
|
||||
info->StateFlags |= STF_DEHACKED; // Signals the state has been modified by dehacked
|
||||
if ((unsigned)(frame & 0x7fff) > 63)
|
||||
{
|
||||
Printf ("Frame %d: Subnumber must be in range [0,63]\n", frameNum);
|
||||
Printf("Frame %d: Subnumber must be in range [0,63]\n", frameNum);
|
||||
}
|
||||
info->Tics = tics;
|
||||
info->Misc1 = misc1;
|
||||
info->Frame = frame & 0x3f;
|
||||
info->Fullbright = frame & 0x8000 ? true : false;
|
||||
if (frame & 0x8000) info->StateFlags |= STF_FULLBRIGHT;
|
||||
else info->StateFlags &= ~STF_FULLBRIGHT;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -2101,23 +2109,24 @@ static int PatchCodePtrs (int dummy)
|
|||
if (!symname.CompareNoCase(MBFCodePointers[i].alias))
|
||||
{
|
||||
symname = MBFCodePointers[i].name;
|
||||
Printf("%s --> %s\n", MBFCodePointers[i].alias, MBFCodePointers[i].name.GetChars());
|
||||
DPrintf(DMSG_SPAMMY, "%s --> %s\n", MBFCodePointers[i].alias, MBFCodePointers[i].name.GetChars());
|
||||
}
|
||||
}
|
||||
|
||||
// This skips the action table and goes directly to the internal symbol table
|
||||
// DEH compatible functions are easy to recognize.
|
||||
PFunction *sym = dyn_cast<PFunction>(RUNTIME_CLASS(AInventory)->Symbols.FindSymbol(symname, true));
|
||||
PFunction *sym = dyn_cast<PFunction>(RUNTIME_CLASS(AStateProvider)->Symbols.FindSymbol(symname, true));
|
||||
if (sym == NULL)
|
||||
{
|
||||
Printf("Frame %d: Unknown code pointer '%s'\n", frame, Line2);
|
||||
Printf(TEXTCOLOR_RED "Frame %d: Unknown code pointer '%s'\n", frame, Line2);
|
||||
}
|
||||
else
|
||||
{
|
||||
TArray<DWORD> &args = sym->Variants[0].ArgFlags;
|
||||
if ((sym->Flags & (VARF_Method | VARF_Action)) != (VARF_Method | VARF_Action) || (args.Size() > NAP && !(args[NAP] & VARF_Optional)))
|
||||
unsigned numargs = sym->GetImplicitArgs();
|
||||
if ((sym->Variants[0].Flags & VARF_Virtual || (args.Size() > numargs && !(args[numargs] & VARF_Optional))))
|
||||
{
|
||||
Printf("Frame %d: Incompatible code pointer '%s'\n", frame, Line2);
|
||||
Printf(TEXTCOLOR_RED "Frame %d: Incompatible code pointer '%s'\n", frame, Line2);
|
||||
sym = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -2715,11 +2724,11 @@ static bool LoadDehSupp ()
|
|||
}
|
||||
else
|
||||
{
|
||||
// all relevant code pointers are either defined in AInventory
|
||||
// all relevant code pointers are either defined in AStateProvider
|
||||
// or AActor so this will find all of them.
|
||||
FString name = "A_";
|
||||
name << sc.String;
|
||||
PFunction *sym = dyn_cast<PFunction>(RUNTIME_CLASS(AInventory)->Symbols.FindSymbol(name, true));
|
||||
PFunction *sym = dyn_cast<PFunction>(RUNTIME_CLASS(AStateProvider)->Symbols.FindSymbol(name, true));
|
||||
if (sym == NULL)
|
||||
{
|
||||
sc.ScriptError("Unknown code pointer '%s'", sc.String);
|
||||
|
@ -2727,7 +2736,8 @@ static bool LoadDehSupp ()
|
|||
else
|
||||
{
|
||||
TArray<DWORD> &args = sym->Variants[0].ArgFlags;
|
||||
if ((sym->Flags & (VARF_Method|VARF_Action)) != (VARF_Method | VARF_Action) || (args.Size() > NAP && !(args[NAP] & VARF_Optional)))
|
||||
unsigned numargs = sym->GetImplicitArgs();
|
||||
if ((sym->Variants[0].Flags & VARF_Virtual || (args.Size() > numargs && !(args[numargs] & VARF_Optional))))
|
||||
{
|
||||
sc.ScriptMessage("Incompatible code pointer '%s'", sc.String);
|
||||
}
|
||||
|
@ -3075,9 +3085,14 @@ void FinishDehPatch ()
|
|||
break; // State has already been checked so we reached a loop
|
||||
}
|
||||
StateVisited[state] = true;
|
||||
for(unsigned j = 0; AmmoPerAttacks[j].func != NULL; j++)
|
||||
for(unsigned j = 0; AmmoPerAttacks[j].func != NAME_None; j++)
|
||||
{
|
||||
if (state->ActionFunc == *AmmoPerAttacks[j].func)
|
||||
if (AmmoPerAttacks[j].ptr == nullptr)
|
||||
{
|
||||
auto p = dyn_cast<PFunction>(RUNTIME_CLASS(AStateProvider)->Symbols.FindSymbol(AmmoPerAttacks[j].func, true));
|
||||
if (p != nullptr) AmmoPerAttacks[j].ptr = p->Variants[0].Implementation;
|
||||
}
|
||||
if (state->ActionFunc == AmmoPerAttacks[j].ptr)
|
||||
{
|
||||
found = true;
|
||||
int use = AmmoPerAttacks[j].ammocount;
|
||||
|
@ -3131,7 +3146,7 @@ bool ADehackedPickup::TryPickup (AActor *&toucher)
|
|||
return false;
|
||||
}
|
||||
|
||||
const char *ADehackedPickup::PickupMessage ()
|
||||
FString ADehackedPickup::PickupMessage ()
|
||||
{
|
||||
if (RealPickup != nullptr)
|
||||
return RealPickup->PickupMessage ();
|
||||
|
@ -3141,7 +3156,7 @@ const char *ADehackedPickup::PickupMessage ()
|
|||
bool ADehackedPickup::ShouldStay ()
|
||||
{
|
||||
if (RealPickup != nullptr)
|
||||
return RealPickup->ShouldStay ();
|
||||
return RealPickup->CallShouldStay ();
|
||||
else return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,8 +41,8 @@ class ADehackedPickup : public AInventory
|
|||
DECLARE_CLASS (ADehackedPickup, AInventory)
|
||||
HAS_OBJECT_POINTERS
|
||||
public:
|
||||
void Destroy ();
|
||||
const char *PickupMessage ();
|
||||
void Destroy() override;
|
||||
FString PickupMessage ();
|
||||
bool ShouldRespawn ();
|
||||
bool ShouldStay ();
|
||||
bool TryPickup (AActor *&toucher);
|
||||
|
|
|
@ -193,10 +193,10 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize)
|
|||
{
|
||||
sc.MustGetStringName("=");
|
||||
sc.MustGetString();
|
||||
iwad->FgColor = V_GetColor(NULL, sc.String);
|
||||
iwad->FgColor = V_GetColor(NULL, sc);
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
iwad->BkColor = V_GetColor(NULL, sc.String);
|
||||
iwad->BkColor = V_GetColor(NULL, sc);
|
||||
}
|
||||
else if (sc.Compare("Load"))
|
||||
{
|
||||
|
|
102
src/d_main.cpp
102
src/d_main.cpp
|
@ -206,6 +206,11 @@ CUSTOM_CVAR (String, vid_cursor, "None", CVAR_ARCHIVE | CVAR_NOINITCALL)
|
|||
}
|
||||
}
|
||||
|
||||
// Controlled by startup dialog
|
||||
CVAR (Bool, disableautoload, false, CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, autoloadbrightmaps, false, CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, autoloadlights, false, CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG)
|
||||
|
||||
bool wantToRestart;
|
||||
bool DrawFSHUD; // [RH] Draw fullscreen HUD?
|
||||
TArray<FString> allwads;
|
||||
|
@ -1028,6 +1033,12 @@ void D_DoomLoop ()
|
|||
}
|
||||
D_ErrorCleanup ();
|
||||
}
|
||||
catch (CVMAbortException &error)
|
||||
{
|
||||
error.MaybePrintMessage();
|
||||
Printf("%s", error.stacktrace.GetChars());
|
||||
D_ErrorCleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1839,10 +1850,10 @@ static FString ParseGameInfo(TArray<FString> &pwads, const char *fn, const char
|
|||
else if (!nextKey.CompareNoCase("STARTUPCOLORS"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
DoomStartupInfo.FgColor = V_GetColor(NULL, sc.String);
|
||||
DoomStartupInfo.FgColor = V_GetColor(NULL, sc);
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
DoomStartupInfo.BkColor = V_GetColor(NULL, sc.String);
|
||||
DoomStartupInfo.BkColor = V_GetColor(NULL, sc);
|
||||
}
|
||||
else if (!nextKey.CompareNoCase("STARTUPTYPE"))
|
||||
{
|
||||
|
@ -2033,7 +2044,24 @@ static void AddAutoloadFiles(const char *autoname)
|
|||
{
|
||||
LumpFilterIWAD.Format("%s.", autoname); // The '.' is appened to simplify parsing the string
|
||||
|
||||
if (!(gameinfo.flags & GI_SHAREWARE) && !Args->CheckParm("-noautoload"))
|
||||
// [SP] Dialog reaction - load lights.pk3 and brightmaps.pk3 based on user choices
|
||||
if (!(gameinfo.flags & GI_SHAREWARE))
|
||||
{
|
||||
if (autoloadlights)
|
||||
{
|
||||
const char *lightswad = BaseFileSearch ("lights.pk3", NULL);
|
||||
if (lightswad)
|
||||
D_AddFile (allwads, lightswad);
|
||||
}
|
||||
if (autoloadbrightmaps)
|
||||
{
|
||||
const char *bmwad = BaseFileSearch ("brightmaps.pk3", NULL);
|
||||
if (bmwad)
|
||||
D_AddFile (allwads, bmwad);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(gameinfo.flags & GI_SHAREWARE) && !Args->CheckParm("-noautoload") && !disableautoload)
|
||||
{
|
||||
FString file;
|
||||
|
||||
|
@ -2593,44 +2621,48 @@ void D_DoomMain (void)
|
|||
G_DeferedPlayDemo (v);
|
||||
D_DoomLoop (); // never returns
|
||||
}
|
||||
|
||||
v = Args->CheckValue ("-timedemo");
|
||||
if (v)
|
||||
else
|
||||
{
|
||||
G_TimeDemo (v);
|
||||
D_DoomLoop (); // never returns
|
||||
}
|
||||
|
||||
if (gameaction != ga_loadgame && gameaction != ga_loadgamehidecon)
|
||||
{
|
||||
if (autostart || netgame)
|
||||
v = Args->CheckValue("-timedemo");
|
||||
if (v)
|
||||
{
|
||||
// Do not do any screenwipes when autostarting a game.
|
||||
if (!Args->CheckParm("-warpwipe"))
|
||||
{
|
||||
NoWipe = TICRATE;
|
||||
}
|
||||
CheckWarpTransMap (startmap, true);
|
||||
if (demorecording)
|
||||
G_BeginRecording (startmap);
|
||||
G_InitNew (startmap, false);
|
||||
if (StoredWarp.IsNotEmpty())
|
||||
{
|
||||
AddCommandString(StoredWarp.LockBuffer());
|
||||
StoredWarp = NULL;
|
||||
}
|
||||
G_TimeDemo(v);
|
||||
D_DoomLoop(); // never returns
|
||||
}
|
||||
else
|
||||
{
|
||||
D_StartTitle (); // start up intro loop
|
||||
if (gameaction != ga_loadgame && gameaction != ga_loadgamehidecon)
|
||||
{
|
||||
if (autostart || netgame)
|
||||
{
|
||||
// Do not do any screenwipes when autostarting a game.
|
||||
if (!Args->CheckParm("-warpwipe"))
|
||||
{
|
||||
NoWipe = TICRATE;
|
||||
}
|
||||
CheckWarpTransMap(startmap, true);
|
||||
if (demorecording)
|
||||
G_BeginRecording(startmap);
|
||||
G_InitNew(startmap, false);
|
||||
if (StoredWarp.IsNotEmpty())
|
||||
{
|
||||
AddCommandString(StoredWarp.LockBuffer());
|
||||
StoredWarp = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
D_StartTitle(); // start up intro loop
|
||||
}
|
||||
}
|
||||
else if (demorecording)
|
||||
{
|
||||
G_BeginRecording(NULL);
|
||||
}
|
||||
|
||||
atterm(D_QuitNetGame); // killough
|
||||
}
|
||||
}
|
||||
else if (demorecording)
|
||||
{
|
||||
G_BeginRecording (NULL);
|
||||
}
|
||||
|
||||
atterm (D_QuitNetGame); // killough
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2644,7 +2676,6 @@ void D_DoomMain (void)
|
|||
}
|
||||
|
||||
D_DoomLoop (); // this only returns if a 'restart' CCMD is given.
|
||||
|
||||
//
|
||||
// Clean up after a restart
|
||||
//
|
||||
|
@ -2655,6 +2686,7 @@ void D_DoomMain (void)
|
|||
|
||||
M_ClearMenus(); // close menu if open
|
||||
F_EndFinale(); // If an intermission is active, end it now
|
||||
AM_ClearColorsets();
|
||||
|
||||
// clean up game state
|
||||
ST_Clear();
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
#include "p_spec.h"
|
||||
#include "hardware.h"
|
||||
#include "r_utility.h"
|
||||
#include "a_keys.h"
|
||||
#include "intermission/intermission.h"
|
||||
|
||||
EXTERN_CVAR (Int, disableautosave)
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "doomstat.h"
|
||||
|
||||
#include "a_artifacts.h"
|
||||
#include "a_weapons.h"
|
||||
|
||||
// The player data structure depends on a number
|
||||
// of other structs: items (internal inventory),
|
||||
|
@ -81,7 +82,6 @@ public:
|
|||
FPlayerColorSet *GetColorSet(int setnum) { return ColorSets.CheckKey(setnum); }
|
||||
void SetPainFlash(FName type, PalEntry color);
|
||||
bool GetPainFlash(FName type, PalEntry *color) const;
|
||||
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
|
||||
|
||||
FString DisplayName; // Display name (used in menus, etc.)
|
||||
FString SoundClass; // Sound class
|
||||
|
@ -106,29 +106,36 @@ public:
|
|||
|
||||
virtual void Serialize(FSerializer &arc);
|
||||
|
||||
virtual void PostBeginPlay();
|
||||
virtual void Tick();
|
||||
virtual void AddInventory (AInventory *item);
|
||||
virtual void RemoveInventory (AInventory *item);
|
||||
virtual bool UseInventory (AInventory *item);
|
||||
virtual void MarkPrecacheSounds () const;
|
||||
virtual void PostBeginPlay() override;
|
||||
virtual void Tick() override;
|
||||
virtual void AddInventory (AInventory *item) override;
|
||||
virtual void RemoveInventory (AInventory *item) override;
|
||||
virtual bool UseInventory (AInventory *item) override;
|
||||
virtual void MarkPrecacheSounds () const override;
|
||||
virtual void BeginPlay () override;
|
||||
virtual void Die (AActor *source, AActor *inflictor, int dmgflags) override;
|
||||
virtual bool UpdateWaterLevel (bool splash) override;
|
||||
|
||||
virtual void PlayIdle ();
|
||||
virtual void PlayRunning ();
|
||||
virtual void ThrowPoisonBag ();
|
||||
virtual void TweakSpeeds (double &forwardmove, double &sidemove);
|
||||
virtual void MorphPlayerThink ();
|
||||
virtual void ActivateMorphWeapon ();
|
||||
bool ResetAirSupply (bool playgasp = true);
|
||||
int GetMaxHealth() const;
|
||||
void TweakSpeeds (double &forwardmove, double &sidemove);
|
||||
void MorphPlayerThink ();
|
||||
void ActivateMorphWeapon ();
|
||||
AWeapon *PickNewWeapon (PClassAmmo *ammotype);
|
||||
AWeapon *BestWeapon (PClassAmmo *ammotype);
|
||||
void CheckWeaponSwitch(PClassAmmo *ammotype);
|
||||
virtual void GiveDeathmatchInventory ();
|
||||
virtual void FilterCoopRespawnInventory (APlayerPawn *oldplayer);
|
||||
void GiveDeathmatchInventory ();
|
||||
void FilterCoopRespawnInventory (APlayerPawn *oldplayer);
|
||||
|
||||
void SetupWeaponSlots ();
|
||||
void GiveDefaultInventory ();
|
||||
|
||||
// These are virtual on the script side only.
|
||||
void PlayIdle();
|
||||
void PlayRunning();
|
||||
void PlayAttacking ();
|
||||
void PlayAttacking2 ();
|
||||
|
||||
const char *GetSoundClass () const;
|
||||
|
||||
enum EInvulState
|
||||
|
@ -139,8 +146,6 @@ public:
|
|||
INVUL_GetAlpha
|
||||
};
|
||||
|
||||
void BeginPlay ();
|
||||
void Die (AActor *source, AActor *inflictor, int dmgflags);
|
||||
|
||||
int crouchsprite;
|
||||
int MaxHealth;
|
||||
|
@ -172,10 +177,6 @@ public:
|
|||
// [SP] ViewBob Multiplier
|
||||
double ViewBob;
|
||||
|
||||
bool UpdateWaterLevel (bool splash);
|
||||
bool ResetAirSupply (bool playgasp = true);
|
||||
|
||||
int GetMaxHealth() const;
|
||||
};
|
||||
|
||||
class APlayerChunk : public APlayerPawn
|
||||
|
@ -254,11 +255,10 @@ enum
|
|||
WF_USER4OK = 1 << 11,
|
||||
};
|
||||
|
||||
#define WPIECE1 1
|
||||
#define WPIECE2 2
|
||||
#define WPIECE3 4
|
||||
|
||||
#define WP_NOCHANGE ((AWeapon*)~0)
|
||||
// The VM cannot deal with this as an invalid pointer because it performs a read barrier on every object pointer read.
|
||||
// This doesn't have to point to a valid weapon, though, because WP_NOCHANGE is never dereferenced, but it must point to a valid object
|
||||
// and the class descriptor just works fine for that.
|
||||
#define WP_NOCHANGE ((AWeapon*)RUNTIME_CLASS_CASTLESS(AWeapon))
|
||||
|
||||
|
||||
#define MAXPLAYERNAME 15
|
||||
|
|
|
@ -119,9 +119,11 @@ protected:
|
|||
DDecalThinker () : DThinker (STAT_DECALTHINKER) {}
|
||||
};
|
||||
|
||||
IMPLEMENT_POINTY_CLASS (DDecalThinker)
|
||||
DECLARE_POINTER (TheDecal)
|
||||
END_POINTERS
|
||||
IMPLEMENT_CLASS(DDecalThinker, false, true)
|
||||
|
||||
IMPLEMENT_POINTERS_START(DDecalThinker)
|
||||
IMPLEMENT_POINTER(TheDecal)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
void DDecalThinker::Serialize(FSerializer &arc)
|
||||
{
|
||||
|
@ -530,7 +532,7 @@ void FDecalLib::ParseDecal (FScanner &sc)
|
|||
sc.MustGetString ();
|
||||
if (!sc.Compare("BloodDefault"))
|
||||
{
|
||||
newdecal.ShadeColor = V_GetColor (NULL, sc.String);
|
||||
newdecal.ShadeColor = V_GetColor (NULL, sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -545,8 +547,8 @@ void FDecalLib::ParseDecal (FScanner &sc)
|
|||
case DECAL_COLORS:
|
||||
DWORD startcolor, endcolor;
|
||||
|
||||
sc.MustGetString (); startcolor = V_GetColor (NULL, sc.String);
|
||||
sc.MustGetString (); endcolor = V_GetColor (NULL, sc.String);
|
||||
sc.MustGetString (); startcolor = V_GetColor (NULL, sc);
|
||||
sc.MustGetString (); endcolor = V_GetColor (NULL, sc);
|
||||
newdecal.Translation = GenerateTranslation (startcolor, endcolor)->Index;
|
||||
break;
|
||||
|
||||
|
@ -817,7 +819,7 @@ void FDecalLib::ParseColorchanger (FScanner &sc)
|
|||
else if (sc.Compare ("Color"))
|
||||
{
|
||||
sc.MustGetString ();
|
||||
goal = V_GetColor (NULL, sc.String);
|
||||
goal = V_GetColor (NULL, sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1151,7 +1153,7 @@ FDecalAnimator::~FDecalAnimator ()
|
|||
{
|
||||
}
|
||||
|
||||
IMPLEMENT_CLASS (DDecalFader)
|
||||
IMPLEMENT_CLASS(DDecalFader, false, false)
|
||||
|
||||
void DDecalFader::Serialize(FSerializer &arc)
|
||||
{
|
||||
|
@ -1200,7 +1202,7 @@ DThinker *FDecalFaderAnim::CreateThinker (DBaseDecal *actor, side_t *wall) const
|
|||
return fader;
|
||||
}
|
||||
|
||||
IMPLEMENT_CLASS (DDecalStretcher)
|
||||
IMPLEMENT_CLASS(DDecalStretcher, false, false)
|
||||
|
||||
void DDecalStretcher::Serialize(FSerializer &arc)
|
||||
{
|
||||
|
@ -1230,6 +1232,7 @@ DThinker *FDecalStretcherAnim::CreateThinker (DBaseDecal *actor, side_t *wall) c
|
|||
}
|
||||
else
|
||||
{
|
||||
thinker->GoalX = 0;
|
||||
thinker->bStretchX = false;
|
||||
}
|
||||
if (GoalY >= 0)
|
||||
|
@ -1239,6 +1242,7 @@ DThinker *FDecalStretcherAnim::CreateThinker (DBaseDecal *actor, side_t *wall) c
|
|||
}
|
||||
else
|
||||
{
|
||||
thinker->GoalY = 0;
|
||||
thinker->bStretchY = false;
|
||||
}
|
||||
thinker->bStarted = false;
|
||||
|
@ -1288,7 +1292,7 @@ void DDecalStretcher::Tick ()
|
|||
}
|
||||
}
|
||||
|
||||
IMPLEMENT_CLASS (DDecalSlider)
|
||||
IMPLEMENT_CLASS(DDecalSlider, false, false)
|
||||
|
||||
void DDecalSlider::Serialize(FSerializer &arc)
|
||||
{
|
||||
|
@ -1368,8 +1372,7 @@ FDecalAnimator *FDecalLib::FindAnimator (const char *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
IMPLEMENT_CLASS (DDecalColorer)
|
||||
IMPLEMENT_CLASS(DDecalColorer, false, false)
|
||||
|
||||
void DDecalColorer::Serialize(FSerializer &arc)
|
||||
{
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "a_sharedglobal.h"
|
||||
#include "dsectoreffect.h"
|
||||
#include "serializer.h"
|
||||
#include "virtual.h"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -57,16 +58,21 @@
|
|||
|
||||
ClassReg DObject::RegistrationInfo =
|
||||
{
|
||||
NULL, // MyClass
|
||||
"DObject", // Name
|
||||
NULL, // ParentType
|
||||
NULL, // Pointers
|
||||
&DObject::InPlaceConstructor, // ConstructNative
|
||||
sizeof(DObject), // SizeOf
|
||||
CLASSREG_PClass, // MetaClassNum
|
||||
nullptr, // MyClass
|
||||
"DObject", // Name
|
||||
nullptr, // ParentType
|
||||
nullptr,
|
||||
nullptr, // Pointers
|
||||
&DObject::InPlaceConstructor, // ConstructNative
|
||||
nullptr,
|
||||
sizeof(DObject), // SizeOf
|
||||
CLASSREG_PClass, // MetaClassNum
|
||||
};
|
||||
_DECLARE_TI(DObject)
|
||||
|
||||
// This bit is needed in the playsim - but give it a less crappy name.
|
||||
DEFINE_FIELD_BIT(DObject,ObjectFlags, bDestroyed, OF_EuthanizeMe)
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -349,6 +355,13 @@ void DObject::Destroy ()
|
|||
ObjectFlags = (ObjectFlags & ~OF_Fixed) | OF_EuthanizeMe;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DObject, Destroy)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DObject);
|
||||
self->Destroy();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -410,7 +423,7 @@ size_t DObject::PointerSubstitution (DObject *old, DObject *notOld)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld)
|
||||
size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld, bool scandefaults)
|
||||
{
|
||||
DObject *probe;
|
||||
size_t changed = 0;
|
||||
|
@ -425,6 +438,20 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld)
|
|||
last = probe;
|
||||
}
|
||||
|
||||
if (scandefaults)
|
||||
{
|
||||
for (auto p : PClassActor::AllActorClasses)
|
||||
{
|
||||
auto def = GetDefaultByType(p);
|
||||
if (def != nullptr)
|
||||
{
|
||||
def->Class = p;
|
||||
def->DObject::PointerSubstitution(old, notOld);
|
||||
def->Class = nullptr; // reset pointer. Defaults should not have a valid class pointer.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Go through the bodyque.
|
||||
for (i = 0; i < BODYQUESIZE; ++i)
|
||||
{
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include "doomtype.h"
|
||||
#include "i_system.h"
|
||||
|
||||
class PClass;
|
||||
|
||||
|
@ -109,8 +110,10 @@ struct ClassReg
|
|||
PClass *MyClass;
|
||||
const char *Name;
|
||||
ClassReg *ParentType;
|
||||
ClassReg *_VMExport;
|
||||
const size_t *Pointers;
|
||||
void (*ConstructNative)(void *);
|
||||
void(*InitNatives)();
|
||||
unsigned int SizeOf:28;
|
||||
unsigned int MetaClassNum:4;
|
||||
|
||||
|
@ -124,8 +127,8 @@ enum EInPlace { EC_InPlace };
|
|||
public: \
|
||||
virtual PClass *StaticType() const; \
|
||||
static ClassReg RegistrationInfo, * const RegistrationInfoPtr; \
|
||||
private: \
|
||||
typedef parent Super; \
|
||||
private: \
|
||||
typedef cls ThisClass;
|
||||
|
||||
#define DECLARE_ABSTRACT_CLASS_WITH_META(cls,parent,meta) \
|
||||
|
@ -147,11 +150,6 @@ protected: \
|
|||
#define HAS_OBJECT_POINTERS \
|
||||
static const size_t PointerOffsets[];
|
||||
|
||||
// Taking the address of a field in an object at address 1 instead of
|
||||
// address 0 keeps GCC from complaining about possible misuse of offsetof.
|
||||
#define DECLARE_POINTER(field) (size_t)&((ThisClass*)1)->field - 1,
|
||||
#define END_POINTERS ~(size_t)0 };
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma section(".creg$u",read)
|
||||
# define _DECLARE_TI(cls) __declspec(allocate(".creg$u")) ClassReg * const cls::RegistrationInfoPtr = &cls::RegistrationInfo;
|
||||
|
@ -159,36 +157,41 @@ protected: \
|
|||
# define _DECLARE_TI(cls) ClassReg * const cls::RegistrationInfoPtr __attribute__((section(SECTION_CREG))) = &cls::RegistrationInfo;
|
||||
#endif
|
||||
|
||||
#define _IMP_PCLASS(cls,ptrs,create) \
|
||||
#define _IMP_PCLASS(cls, ptrs, create) \
|
||||
ClassReg cls::RegistrationInfo = {\
|
||||
NULL, \
|
||||
nullptr, \
|
||||
#cls, \
|
||||
&cls::Super::RegistrationInfo, \
|
||||
nullptr, \
|
||||
ptrs, \
|
||||
create, \
|
||||
nullptr, \
|
||||
sizeof(cls), \
|
||||
cls::MetaClassNum }; \
|
||||
_DECLARE_TI(cls) \
|
||||
PClass *cls::StaticType() const { return RegistrationInfo.MyClass; }
|
||||
|
||||
#define _IMP_CREATE_OBJ(cls) \
|
||||
void cls::InPlaceConstructor(void *mem) { new((EInPlace *)mem) cls; }
|
||||
#define IMPLEMENT_CLASS(cls, isabstract, ptrs) \
|
||||
_X_CONSTRUCTOR_##isabstract(cls) \
|
||||
_IMP_PCLASS(cls, _X_POINTERS_##ptrs(cls), _X_ABSTRACT_##isabstract(cls))
|
||||
|
||||
#define IMPLEMENT_POINTY_CLASS(cls) \
|
||||
_IMP_CREATE_OBJ(cls) \
|
||||
_IMP_PCLASS(cls,cls::PointerOffsets,cls::InPlaceConstructor) \
|
||||
const size_t cls::PointerOffsets[] = {
|
||||
// Taking the address of a field in an object at address 1 instead of
|
||||
// address 0 keeps GCC from complaining about possible misuse of offsetof.
|
||||
#define IMPLEMENT_POINTERS_START(cls) const size_t cls::PointerOffsets[] = {
|
||||
#define IMPLEMENT_POINTER(field) (size_t)&((ThisClass*)1)->field - 1,
|
||||
#define IMPLEMENT_POINTERS_END ~(size_t)0 };
|
||||
|
||||
#define IMPLEMENT_CLASS(cls) \
|
||||
_IMP_CREATE_OBJ(cls) \
|
||||
_IMP_PCLASS(cls,NULL,cls::InPlaceConstructor)
|
||||
|
||||
#define IMPLEMENT_ABSTRACT_CLASS(cls) \
|
||||
_IMP_PCLASS(cls,NULL,NULL)
|
||||
|
||||
#define IMPLEMENT_ABSTRACT_POINTY_CLASS(cls) \
|
||||
_IMP_PCLASS(cls,cls::PointerOffsets,NULL) \
|
||||
const size_t cls::PointerOffsets[] = {
|
||||
// Possible arguments for the IMPLEMENT_CLASS macro
|
||||
#define _X_POINTERS_true(cls) cls::PointerOffsets
|
||||
#define _X_POINTERS_false(cls) nullptr
|
||||
#define _X_FIELDS_true(cls) nullptr
|
||||
#define _X_FIELDS_false(cls) nullptr
|
||||
#define _X_CONSTRUCTOR_true(cls)
|
||||
#define _X_CONSTRUCTOR_false(cls) void cls::InPlaceConstructor(void *mem) { new((EInPlace *)mem) cls; }
|
||||
#define _X_ABSTRACT_true(cls) nullptr
|
||||
#define _X_ABSTRACT_false(cls) cls::InPlaceConstructor
|
||||
#define _X_VMEXPORT_true(cls) nullptr
|
||||
#define _X_VMEXPORT_false(cls) nullptr
|
||||
|
||||
enum EObjectFlags
|
||||
{
|
||||
|
@ -201,7 +204,6 @@ enum EObjectFlags
|
|||
OF_EuthanizeMe = 1 << 5, // Object wants to die
|
||||
OF_Cleanup = 1 << 6, // Object is now being deleted by the collector
|
||||
OF_YesReallyDelete = 1 << 7, // Object is being deleted outside the collector, and this is okay, so don't print a warning
|
||||
OF_Transient = 1 << 11, // Object should not be archived (references to it will be nulled on disk)
|
||||
|
||||
OF_WhiteBits = OF_White0 | OF_White1,
|
||||
OF_MarkBits = OF_WhiteBits | OF_Black,
|
||||
|
@ -210,6 +212,8 @@ enum EObjectFlags
|
|||
OF_JustSpawned = 1 << 8, // Thinker was spawned this tic
|
||||
OF_SerialSuccess = 1 << 9, // For debugging Serialize() calls
|
||||
OF_Sentinel = 1 << 10, // Object is serving as the sentinel in a ring list
|
||||
OF_Transient = 1 << 11, // Object should not be archived (references to it will be nulled on disk)
|
||||
OF_SuperCall = 1 << 12, // A super call from the VM is about to be performed
|
||||
};
|
||||
|
||||
template<class T> class TObjPtr;
|
||||
|
@ -472,13 +476,13 @@ public:
|
|||
// that don't call their base class.
|
||||
void CheckIfSerialized () const;
|
||||
|
||||
virtual void Destroy ();
|
||||
virtual void Destroy();
|
||||
|
||||
// If you need to replace one object with another and want to
|
||||
// change any pointers from the old object to the new object,
|
||||
// use this method.
|
||||
virtual size_t PointerSubstitution (DObject *old, DObject *notOld);
|
||||
static size_t StaticPointerSubstitution (DObject *old, DObject *notOld);
|
||||
static size_t StaticPointerSubstitution (DObject *old, DObject *notOld, bool scandefaults = false);
|
||||
|
||||
PClass *GetClass() const
|
||||
{
|
||||
|
@ -574,6 +578,8 @@ protected:
|
|||
}
|
||||
};
|
||||
|
||||
class AInventory;//
|
||||
|
||||
// When you write to a pointer to an Object, you must call this for
|
||||
// proper bookkeeping in case the Object holding this pointer has
|
||||
// already been processed by the GC.
|
||||
|
|
|
@ -124,7 +124,8 @@ public:
|
|||
int PolyNum;
|
||||
int SideNum;
|
||||
};
|
||||
IMPLEMENT_CLASS(DSectorMarker)
|
||||
|
||||
IMPLEMENT_CLASS(DSectorMarker, false, false)
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
|
|
1241
src/dobjtype.cpp
1241
src/dobjtype.cpp
File diff suppressed because it is too large
Load diff
285
src/dobjtype.h
285
src/dobjtype.h
|
@ -5,20 +5,36 @@
|
|||
#error You must #include "dobject.h" to get dobjtype.h
|
||||
#endif
|
||||
|
||||
#include "vm.h"
|
||||
|
||||
typedef std::pair<const class PType *, unsigned> FTypeAndOffset;
|
||||
|
||||
#include "vm.h"
|
||||
|
||||
// Variable/parameter/field flags -------------------------------------------
|
||||
|
||||
// Making all these different storage types use a common set of flags seems
|
||||
// like the simplest thing to do.
|
||||
|
||||
#define VARF_Optional (1<<0) // func param is optional
|
||||
#define VARF_Method (1<<1) // func has an implied self parameter
|
||||
#define VARF_Action (1<<2) // func has implied owner and state parameters
|
||||
#define VARF_Native (1<<3) // func is native code/don't auto serialize field
|
||||
#define VARF_ReadOnly (1<<4) // field is read only, do not write to it
|
||||
enum
|
||||
{
|
||||
VARF_Optional = (1<<0), // func param is optional
|
||||
VARF_Method = (1<<1), // func has an implied self parameter
|
||||
VARF_Action = (1<<2), // func has implied owner and state parameters
|
||||
VARF_Native = (1<<3), // func is native code, field is natively defined
|
||||
VARF_ReadOnly = (1<<4), // field is read only, do not write to it
|
||||
VARF_Private = (1<<5), // field is private to containing class
|
||||
VARF_Protected = (1<<6), // field is only accessible by containing class and children.
|
||||
VARF_Deprecated = (1<<7), // Deprecated fields should output warnings when used.
|
||||
VARF_Virtual = (1<<8), // function is virtual
|
||||
VARF_Final = (1<<9), // Function may not be overridden in subclasses
|
||||
VARF_In = (1<<10),
|
||||
VARF_Out = (1<<11),
|
||||
VARF_Implicit = (1<<12), // implicitly created parameters (i.e. do not compare types when checking function signatures)
|
||||
VARF_Static = (1<<13), // static class data (by necessity read only.)
|
||||
VARF_InternalAccess = (1<<14), // overrides VARF_ReadOnly for internal script code.
|
||||
VARF_Override = (1<<15), // overrides a virtual function from the parent class.
|
||||
VARF_Ref = (1<<16), // argument is passed by reference.
|
||||
VARF_Transient = (1<<17) // don't auto serialize field.
|
||||
};
|
||||
|
||||
// Symbol information -------------------------------------------------------
|
||||
|
||||
|
@ -57,7 +73,6 @@ struct StateCallData;
|
|||
class VMFrameStack;
|
||||
struct VMValue;
|
||||
struct VMReturn;
|
||||
typedef int (*actionf_p)(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/
|
||||
class VMFunction;
|
||||
|
||||
// A VM function ------------------------------------------------------------
|
||||
|
@ -86,18 +101,6 @@ public:
|
|||
PSymbolType() : PSymbol(NAME_None) {}
|
||||
};
|
||||
|
||||
// A symbol for a compiler tree node ----------------------------------------
|
||||
|
||||
class PSymbolTreeNode : public PSymbol
|
||||
{
|
||||
DECLARE_CLASS(PSymbolTreeNode, PSymbol);
|
||||
public:
|
||||
struct ZCC_NamedNode *Node;
|
||||
|
||||
PSymbolTreeNode(FName name, struct ZCC_NamedNode *node) : PSymbol(name), Node(node) {}
|
||||
PSymbolTreeNode() : PSymbol(NAME_None) {}
|
||||
};
|
||||
|
||||
// A symbol table -----------------------------------------------------------
|
||||
|
||||
struct PSymbolTable
|
||||
|
@ -111,6 +114,10 @@ struct PSymbolTable
|
|||
// Sets the table to use for searches if this one doesn't contain the
|
||||
// requested symbol.
|
||||
void SetParentTable (PSymbolTable *parent);
|
||||
PSymbolTable *GetParentTable() const
|
||||
{
|
||||
return ParentSymbolTable;
|
||||
}
|
||||
|
||||
// Finds a symbol in the table, optionally searching parent tables
|
||||
// as well.
|
||||
|
@ -120,6 +127,7 @@ struct PSymbolTable
|
|||
// specific symbol table the symbol was found in.
|
||||
PSymbol *FindSymbolInTable(FName symname, PSymbolTable *&symtable);
|
||||
|
||||
|
||||
// Places the symbol in the table and returns a pointer to it or NULL if
|
||||
// a symbol with the same name is already in the table. This symbol is
|
||||
// not copied and will be freed when the symbol table is destroyed.
|
||||
|
@ -132,15 +140,33 @@ struct PSymbolTable
|
|||
// Frees all symbols from this table.
|
||||
void ReleaseSymbols();
|
||||
|
||||
private:
|
||||
typedef TMap<FName, PSymbol *> MapType;
|
||||
|
||||
MapType::Iterator GetIterator()
|
||||
{
|
||||
return MapType::Iterator(Symbols);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
PSymbolTable *ParentSymbolTable;
|
||||
MapType Symbols;
|
||||
|
||||
friend class DObject;
|
||||
};
|
||||
|
||||
// A symbol for a compiler tree node ----------------------------------------
|
||||
|
||||
class PSymbolTreeNode : public PSymbol
|
||||
{
|
||||
DECLARE_CLASS(PSymbolTreeNode, PSymbol);
|
||||
public:
|
||||
struct ZCC_TreeNode *Node;
|
||||
|
||||
PSymbolTreeNode(FName name, struct ZCC_TreeNode *node) : PSymbol(name), Node(node) {}
|
||||
PSymbolTreeNode() : PSymbol(NAME_None) {}
|
||||
};
|
||||
|
||||
extern PSymbolTable GlobalSymbols;
|
||||
|
||||
// Basic information shared by all types ------------------------------------
|
||||
|
@ -179,6 +205,7 @@ class PType : public PTypeBase
|
|||
HAS_OBJECT_POINTERS;
|
||||
protected:
|
||||
enum { MetaClassNum = CLASSREG_PClassType };
|
||||
|
||||
public:
|
||||
typedef PClassType MetaClass;
|
||||
MetaClass *GetClass() const;
|
||||
|
@ -196,10 +223,13 @@ public:
|
|||
unsigned int Align; // this type's preferred alignment
|
||||
PType *HashNext; // next type in this type table
|
||||
PSymbolTable Symbols;
|
||||
bool MemberOnly = false; // type may only be used as a struct/class member but not as a local variable or function argument.
|
||||
FString mDescriptiveName;
|
||||
BYTE loadOp, storeOp, moveOp, RegType, RegCount;
|
||||
|
||||
PType();
|
||||
PType(unsigned int size, unsigned int align);
|
||||
PType(unsigned int size = 1, unsigned int align = 1);
|
||||
virtual ~PType();
|
||||
virtual bool isNumeric() { return false; }
|
||||
|
||||
bool AddConversion(PType *target, void (*convertconst)(ZCC_ExprConstant *, class FSharedStringArena &));
|
||||
|
||||
|
@ -224,6 +254,7 @@ public:
|
|||
// initialization when the object is created and destruction when the
|
||||
// object is destroyed.
|
||||
virtual void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL) const;
|
||||
virtual void SetPointer(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL) const;
|
||||
|
||||
// Initialize the value, if needed (e.g. strings)
|
||||
virtual void InitializeValue(void *addr, const void *def) const;
|
||||
|
@ -240,14 +271,33 @@ public:
|
|||
virtual double GetValueFloat(void *addr) const;
|
||||
|
||||
// Gets the opcode to store from a register to memory
|
||||
virtual int GetStoreOp() const;
|
||||
int GetStoreOp() const
|
||||
{
|
||||
return storeOp;
|
||||
}
|
||||
|
||||
// Gets the opcode to load from memory to a register
|
||||
virtual int GetLoadOp() const;
|
||||
int GetLoadOp() const
|
||||
{
|
||||
return loadOp;
|
||||
}
|
||||
|
||||
// Gets the opcode to move from register to another register
|
||||
int GetMoveOp() const
|
||||
{
|
||||
return moveOp;
|
||||
}
|
||||
|
||||
// Gets the register type for this type
|
||||
virtual int GetRegType() const;
|
||||
int GetRegType() const
|
||||
{
|
||||
return RegType;
|
||||
}
|
||||
|
||||
int GetRegCount() const
|
||||
{
|
||||
return RegCount;
|
||||
}
|
||||
// Returns true if this type matches the two identifiers. Referring to the
|
||||
// above table, any type is identified by at most two characteristics. Each
|
||||
// type that implements this function will cast these to the appropriate type.
|
||||
|
@ -259,6 +309,8 @@ public:
|
|||
// Get the type IDs used by IsMatch
|
||||
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||
|
||||
const char *DescriptiveName() const;
|
||||
|
||||
size_t PropagateMark();
|
||||
|
||||
static void StaticInit();
|
||||
|
@ -318,7 +370,7 @@ class PErrorType : public PType
|
|||
{
|
||||
DECLARE_CLASS(PErrorType, PType);
|
||||
public:
|
||||
PErrorType() : PType(0, 1) {}
|
||||
PErrorType(int which = 1) : PType(0, which) {}
|
||||
};
|
||||
|
||||
class PVoidType : public PType
|
||||
|
@ -351,8 +403,12 @@ public:
|
|||
PTypeBase *Outer; // object this type is contained within
|
||||
FName TypeName; // this type's name
|
||||
|
||||
PNamedType() : Outer(NULL) {}
|
||||
PNamedType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) {}
|
||||
PNamedType() : Outer(NULL) {
|
||||
mDescriptiveName = "NamedType";
|
||||
}
|
||||
PNamedType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) {
|
||||
mDescriptiveName = name.GetChars();
|
||||
}
|
||||
|
||||
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||
|
@ -365,7 +421,7 @@ class PInt : public PBasicType
|
|||
{
|
||||
DECLARE_CLASS(PInt, PBasicType);
|
||||
public:
|
||||
PInt(unsigned int size, bool unsign);
|
||||
PInt(unsigned int size, bool unsign, bool compatible = true);
|
||||
|
||||
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
|
||||
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
|
||||
|
@ -374,13 +430,13 @@ public:
|
|||
virtual void SetValue(void *addr, double val);
|
||||
virtual int GetValueInt(void *addr) const;
|
||||
virtual double GetValueFloat(void *addr) const;
|
||||
virtual int GetStoreOp() const;
|
||||
virtual int GetLoadOp() const;
|
||||
virtual int GetRegType() const;
|
||||
virtual bool isNumeric() override { return IntCompatible; }
|
||||
|
||||
bool Unsigned;
|
||||
bool IntCompatible;
|
||||
protected:
|
||||
PInt();
|
||||
void SetOps();
|
||||
};
|
||||
|
||||
class PBool : public PInt
|
||||
|
@ -403,11 +459,10 @@ public:
|
|||
virtual void SetValue(void *addr, double val);
|
||||
virtual int GetValueInt(void *addr) const;
|
||||
virtual double GetValueFloat(void *addr) const;
|
||||
virtual int GetStoreOp() const;
|
||||
virtual int GetLoadOp() const;
|
||||
virtual int GetRegType() const;
|
||||
virtual bool isNumeric() override { return true; }
|
||||
protected:
|
||||
PFloat();
|
||||
void SetOps();
|
||||
private:
|
||||
struct SymbolInitF
|
||||
{
|
||||
|
@ -432,8 +487,6 @@ class PString : public PBasicType
|
|||
public:
|
||||
PString();
|
||||
|
||||
virtual int GetRegType() const;
|
||||
|
||||
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
|
||||
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
|
||||
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL) const override;
|
||||
|
@ -463,6 +516,26 @@ public:
|
|||
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
|
||||
};
|
||||
|
||||
class PSpriteID : public PInt
|
||||
{
|
||||
DECLARE_CLASS(PSpriteID, PInt);
|
||||
public:
|
||||
PSpriteID();
|
||||
|
||||
void WriteValue(FSerializer &ar, const char *key, const void *addr) const override;
|
||||
bool ReadValue(FSerializer &ar, const char *key, void *addr) const override;
|
||||
};
|
||||
|
||||
class PTextureID : public PInt
|
||||
{
|
||||
DECLARE_CLASS(PTextureID, PInt);
|
||||
public:
|
||||
PTextureID();
|
||||
|
||||
void WriteValue(FSerializer &ar, const char *key, const void *addr) const override;
|
||||
bool ReadValue(FSerializer &ar, const char *key, void *addr) const override;
|
||||
};
|
||||
|
||||
class PColor : public PInt
|
||||
{
|
||||
DECLARE_CLASS(PColor, PInt);
|
||||
|
@ -470,45 +543,48 @@ public:
|
|||
PColor();
|
||||
};
|
||||
|
||||
// Pointers -----------------------------------------------------------------
|
||||
|
||||
class PStatePointer : public PBasicType
|
||||
class PStateLabel : public PInt
|
||||
{
|
||||
DECLARE_CLASS(PStatePointer, PBasicType);
|
||||
DECLARE_CLASS(PStateLabel, PInt);
|
||||
public:
|
||||
PStatePointer();
|
||||
|
||||
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
|
||||
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
|
||||
|
||||
virtual int GetStoreOp() const;
|
||||
virtual int GetLoadOp() const;
|
||||
virtual int GetRegType() const;
|
||||
PStateLabel();
|
||||
};
|
||||
|
||||
// Pointers -----------------------------------------------------------------
|
||||
|
||||
class PPointer : public PBasicType
|
||||
{
|
||||
DECLARE_CLASS(PPointer, PBasicType);
|
||||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
PPointer(PType *pointsat);
|
||||
PPointer();
|
||||
PPointer(PType *pointsat, bool isconst = false);
|
||||
|
||||
PType *PointedType;
|
||||
|
||||
virtual int GetStoreOp() const;
|
||||
virtual int GetLoadOp() const;
|
||||
virtual int GetRegType() const;
|
||||
bool IsConst;
|
||||
|
||||
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||
void SetPointer(void *base, unsigned offset, TArray<size_t> *special = NULL) const override;
|
||||
|
||||
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
|
||||
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
|
||||
|
||||
protected:
|
||||
PPointer();
|
||||
void SetOps();
|
||||
};
|
||||
|
||||
class PStatePointer : public PPointer
|
||||
{
|
||||
DECLARE_CLASS(PStatePointer, PPointer);
|
||||
public:
|
||||
PStatePointer();
|
||||
|
||||
void WriteValue(FSerializer &ar, const char *key, const void *addr) const override;
|
||||
bool ReadValue(FSerializer &ar, const char *key, void *addr) const override;
|
||||
};
|
||||
|
||||
|
||||
class PClassPointer : public PPointer
|
||||
{
|
||||
DECLARE_CLASS(PClassPointer, PPointer);
|
||||
|
@ -518,6 +594,9 @@ public:
|
|||
|
||||
class PClass *ClassRestriction;
|
||||
|
||||
// this is only here to block PPointer's implementation
|
||||
void SetPointer(void *base, unsigned offset, TArray<size_t> *special = NULL) const override {}
|
||||
|
||||
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||
protected:
|
||||
|
@ -532,13 +611,12 @@ class PField : public PSymbol
|
|||
DECLARE_CLASS(PField, PSymbol);
|
||||
HAS_OBJECT_POINTERS
|
||||
public:
|
||||
PField(FName name, PType *type) : PSymbol(name), Offset(0), Type(type), Flags(0) {}
|
||||
PField(FName name, PType *type, DWORD flags) : PSymbol(name), Offset(0), Type(type), Flags(flags) {}
|
||||
PField(FName name, PType *type, DWORD flags, unsigned offset) : PSymbol(name), Offset(offset), Type(type), Flags(flags) {}
|
||||
PField(FName name, PType *type, DWORD flags = 0, size_t offset = 0, int bitvalue = 0);
|
||||
|
||||
unsigned int Offset;
|
||||
size_t Offset;
|
||||
PType *Type;
|
||||
DWORD Flags;
|
||||
int BitValue;
|
||||
protected:
|
||||
PField();
|
||||
};
|
||||
|
@ -576,22 +654,12 @@ public:
|
|||
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
|
||||
|
||||
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const override;
|
||||
void SetPointer(void *base, unsigned offset, TArray<size_t> *special) const override;
|
||||
|
||||
protected:
|
||||
PArray();
|
||||
};
|
||||
|
||||
// A vector is an array with extra operations.
|
||||
class PVector : public PArray
|
||||
{
|
||||
DECLARE_CLASS(PVector, PArray);
|
||||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
PVector(unsigned int size);
|
||||
protected:
|
||||
PVector();
|
||||
};
|
||||
|
||||
class PDynArray : public PCompoundType
|
||||
{
|
||||
DECLARE_CLASS(PDynArray, PCompoundType);
|
||||
|
@ -630,14 +698,17 @@ public:
|
|||
PStruct(FName name, PTypeBase *outer);
|
||||
|
||||
TArray<PField *> Fields;
|
||||
bool HasNativeFields;
|
||||
|
||||
virtual PField *AddField(FName name, PType *type, DWORD flags=0);
|
||||
virtual PField *AddNativeField(FName name, PType *type, size_t address, DWORD flags = 0, int bitvalue = 0);
|
||||
|
||||
size_t PropagateMark();
|
||||
|
||||
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
|
||||
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
|
||||
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) const override;
|
||||
void SetPointer(void *base, unsigned offset, TArray<size_t> *specials) const override;
|
||||
|
||||
static void WriteFields(FSerializer &ar, const void *addr, const TArray<PField *> &fields);
|
||||
bool ReadFields(FSerializer &ar, void *addr) const;
|
||||
|
@ -645,6 +716,15 @@ protected:
|
|||
PStruct();
|
||||
};
|
||||
|
||||
// a native struct will always be abstract and cannot be instantiated. All variables are references.
|
||||
// In addition, native structs can have methods (but no virtual ones.)
|
||||
class PNativeStruct : public PStruct
|
||||
{
|
||||
DECLARE_CLASS(PNativeStruct, PStruct);
|
||||
public:
|
||||
PNativeStruct(FName name = NAME_None);
|
||||
};
|
||||
|
||||
class PPrototype : public PCompoundType
|
||||
{
|
||||
DECLARE_CLASS(PPrototype, PCompoundType);
|
||||
|
@ -668,19 +748,28 @@ class PFunction : public PSymbol
|
|||
public:
|
||||
struct Variant
|
||||
{
|
||||
//PPrototype *Proto;
|
||||
PPrototype *Proto;
|
||||
VMFunction *Implementation;
|
||||
TArray<DWORD> ArgFlags; // Should be the same length as Proto->ArgumentTypes
|
||||
TArray<FName> ArgNames; // we need the names to access them later when the function gets compiled.
|
||||
uint32_t Flags;
|
||||
int UseFlags;
|
||||
PStruct *SelfClass;
|
||||
};
|
||||
TArray<Variant> Variants;
|
||||
DWORD Flags;
|
||||
PStruct *OwningClass = nullptr;
|
||||
|
||||
unsigned AddVariant(PPrototype *proto, TArray<DWORD> &argflags, VMFunction *impl);
|
||||
unsigned AddVariant(PPrototype *proto, TArray<DWORD> &argflags, TArray<FName> &argnames, VMFunction *impl, int flags, int useflags);
|
||||
int GetImplicitArgs()
|
||||
{
|
||||
if (Variants[0].Flags & VARF_Action) return 3;
|
||||
else if (Variants[0].Flags & VARF_Method) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t PropagateMark();
|
||||
|
||||
PFunction(FName name) : PSymbol(name), Flags(0) {}
|
||||
PFunction() : PSymbol(NAME_None), Flags(0) {}
|
||||
PFunction(PStruct *owner = nullptr, FName name = NAME_None) : PSymbol(name), OwningClass(owner) {}
|
||||
};
|
||||
|
||||
// Meta-info for every class derived from DObject ---------------------------
|
||||
|
@ -691,16 +780,17 @@ enum
|
|||
};
|
||||
|
||||
class PClassClass;
|
||||
class PClass : public PStruct
|
||||
class PClass : public PNativeStruct
|
||||
{
|
||||
DECLARE_CLASS(PClass, PStruct);
|
||||
DECLARE_CLASS(PClass, PNativeStruct);
|
||||
HAS_OBJECT_POINTERS;
|
||||
protected:
|
||||
// We unravel _WITH_META here just as we did for PType.
|
||||
enum { MetaClassNum = CLASSREG_PClassClass };
|
||||
TArray<FTypeAndOffset> SpecialInits;
|
||||
virtual void Derive(PClass *newclass);
|
||||
void Derive(PClass *newclass, FName name);
|
||||
void InitializeSpecials(void *addr) const;
|
||||
void SetSuper();
|
||||
public:
|
||||
typedef PClassClass MetaClass;
|
||||
MetaClass *GetClass() const;
|
||||
|
@ -709,8 +799,10 @@ public:
|
|||
void WriteAllFields(FSerializer &ar, const void *addr) const;
|
||||
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
|
||||
bool ReadAllFields(FSerializer &ar, void *addr) const;
|
||||
void InitializeDefaults();
|
||||
int FindVirtualIndex(FName name, PPrototype *proto);
|
||||
virtual void DeriveData(PClass *newclass);
|
||||
|
||||
virtual void DeriveData(PClass *newclass) {}
|
||||
static void StaticInit();
|
||||
static void StaticShutdown();
|
||||
static void StaticBootstrap();
|
||||
|
@ -721,6 +813,9 @@ public:
|
|||
const size_t *FlatPointers; // object pointers defined by this class and all its superclasses; not initialized by default
|
||||
BYTE *Defaults;
|
||||
bool bRuntimeClass; // class was defined at run-time, not compile-time
|
||||
bool bExported; // This type has been declared in a script
|
||||
bool bDecorateClass; // may be subject to some idiosyncracies due to DECORATE backwards compatibility
|
||||
TArray<VMFunction*> Virtuals; // virtual function table
|
||||
|
||||
void (*ConstructNative)(void *);
|
||||
|
||||
|
@ -764,7 +859,8 @@ public:
|
|||
static PClassActor *FindActor(const FString &name) { return FindActor(FName(name, true)); }
|
||||
static PClassActor *FindActor(ENamedName name) { return FindActor(FName(name)); }
|
||||
static PClassActor *FindActor(FName name);
|
||||
PClass *FindClassTentative(FName name, bool fatal = true); // not static!
|
||||
static VMFunction *FindFunction(FName cls, FName func);
|
||||
PClass *FindClassTentative(FName name);
|
||||
|
||||
static TArray<PClass *> AllClasses;
|
||||
|
||||
|
@ -777,7 +873,7 @@ class PClassType : public PClass
|
|||
protected:
|
||||
public:
|
||||
PClassType();
|
||||
virtual void Derive(PClass *newclass);
|
||||
virtual void DeriveData(PClass *newclass);
|
||||
|
||||
PClass *TypeTableType; // The type to use for hashing into the type table
|
||||
};
|
||||
|
@ -799,17 +895,6 @@ inline PClass::MetaClass *PClass::GetClass() const
|
|||
return static_cast<MetaClass *>(DObject::GetClass());
|
||||
}
|
||||
|
||||
// A class that hasn't had its parent class defined yet ---------------------
|
||||
|
||||
class PClassWaitingForParent : public PClass
|
||||
{
|
||||
DECLARE_CLASS(PClassWaitingForParent, PClass);
|
||||
public:
|
||||
PClassWaitingForParent(FName myname, FName parentname);
|
||||
|
||||
FName ParentName;
|
||||
};
|
||||
|
||||
// Type tables --------------------------------------------------------------
|
||||
|
||||
struct FTypeTable
|
||||
|
@ -832,20 +917,20 @@ struct FTypeTable
|
|||
extern FTypeTable TypeTable;
|
||||
|
||||
// Returns a type from the TypeTable. Will create one if it isn't present.
|
||||
PVector *NewVector(unsigned int size);
|
||||
PMap *NewMap(PType *keytype, PType *valuetype);
|
||||
PArray *NewArray(PType *type, unsigned int count);
|
||||
PDynArray *NewDynArray(PType *type);
|
||||
PPointer *NewPointer(PType *type);
|
||||
PPointer *NewPointer(PType *type, bool isconst = false);
|
||||
PClassPointer *NewClassPointer(PClass *restrict);
|
||||
PClassWaitingForParent *NewUnknownClass(FName myname, FName parentname);
|
||||
PEnum *NewEnum(FName name, PTypeBase *outer);
|
||||
PStruct *NewStruct(FName name, PTypeBase *outer);
|
||||
PNativeStruct *NewNativeStruct(FName name, PTypeBase *outer);
|
||||
PPrototype *NewPrototype(const TArray<PType *> &rettypes, const TArray<PType *> &argtypes);
|
||||
|
||||
// Built-in types -----------------------------------------------------------
|
||||
|
||||
extern PErrorType *TypeError;
|
||||
extern PErrorType *TypeAuto;
|
||||
extern PVoidType *TypeVoid;
|
||||
extern PInt *TypeSInt8, *TypeUInt8;
|
||||
extern PInt *TypeSInt16, *TypeUInt16;
|
||||
|
@ -856,7 +941,15 @@ extern PString *TypeString;
|
|||
extern PName *TypeName;
|
||||
extern PSound *TypeSound;
|
||||
extern PColor *TypeColor;
|
||||
extern PTextureID *TypeTextureID;
|
||||
extern PSpriteID *TypeSpriteID;
|
||||
extern PStruct *TypeVector2;
|
||||
extern PStruct *TypeVector3;
|
||||
extern PStruct *TypeColorStruct;
|
||||
extern PStruct *TypeStringStruct;
|
||||
extern PStatePointer *TypeState;
|
||||
extern PStateLabel *TypeStateLabel;
|
||||
extern PPointer *TypeNullPtr;
|
||||
|
||||
// A constant value ---------------------------------------------------------
|
||||
|
||||
|
|
|
@ -56,6 +56,12 @@ public:
|
|||
strncpy (m_Message, message, MAX_ERRORTEXT-1);
|
||||
m_Message[MAX_ERRORTEXT-1] = '\0';
|
||||
}
|
||||
void AppendMessage(const char *message)
|
||||
{
|
||||
size_t len = strlen(m_Message);
|
||||
strncpy(m_Message + len, message, MAX_ERRORTEXT - 1 - len);
|
||||
m_Message[MAX_ERRORTEXT - 1] = '\0';
|
||||
}
|
||||
const char *GetMessage (void) const
|
||||
{
|
||||
if (m_Message[0] != '\0')
|
||||
|
@ -64,7 +70,7 @@ public:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
protected:
|
||||
char m_Message[MAX_ERRORTEXT];
|
||||
};
|
||||
|
||||
|
|
|
@ -49,57 +49,6 @@
|
|||
class PClassActor;
|
||||
typedef TMap<int, PClassActor *> FClassMap;
|
||||
|
||||
// Since this file is included by everything, it seems an appropriate place
|
||||
// to check the NOASM/USEASM macros.
|
||||
|
||||
// There are three assembly-related macros:
|
||||
//
|
||||
// NOASM - Assembly code is disabled
|
||||
// X86_ASM - Using ia32 assembly code
|
||||
// X64_ASM - Using amd64 assembly code
|
||||
//
|
||||
// Note that these relate only to using the pure assembly code. Inline
|
||||
// assembly may still be used without respect to these macros, as
|
||||
// deemed appropriate.
|
||||
|
||||
#ifndef NOASM
|
||||
// Select the appropriate type of assembly code to use.
|
||||
|
||||
#if defined(_M_IX86) || defined(__i386__)
|
||||
|
||||
#define X86_ASM
|
||||
#ifdef X64_ASM
|
||||
#undef X64_ASM
|
||||
#endif
|
||||
|
||||
#elif defined(_M_X64) || defined(__amd64__)
|
||||
|
||||
#define X64_ASM
|
||||
#ifdef X86_ASM
|
||||
#undef X86_ASM
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define NOASM
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef NOASM
|
||||
// Ensure no assembly macros are defined if NOASM is defined.
|
||||
|
||||
#ifdef X86_ASM
|
||||
#undef X86_ASM
|
||||
#endif
|
||||
|
||||
#ifdef X64_ASM
|
||||
#undef X64_ASM
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define NOVTABLE __declspec(novtable)
|
||||
|
@ -265,12 +214,14 @@ char ( &_ArraySizeHelper( T (&array)[N] ))[N];
|
|||
#ifdef __MACH__
|
||||
#define SECTION_AREG "__DATA,areg"
|
||||
#define SECTION_CREG "__DATA,creg"
|
||||
#define SECTION_FREG "__DATA,freg"
|
||||
#define SECTION_GREG "__DATA,greg"
|
||||
#define SECTION_MREG "__DATA,mreg"
|
||||
#define SECTION_YREG "__DATA,yreg"
|
||||
#else
|
||||
#define SECTION_AREG "areg"
|
||||
#define SECTION_CREG "creg"
|
||||
#define SECTION_FREG "freg"
|
||||
#define SECTION_GREG "greg"
|
||||
#define SECTION_MREG "mreg"
|
||||
#define SECTION_YREG "yreg"
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include "serializer.h"
|
||||
#include "doomstat.h"
|
||||
|
||||
IMPLEMENT_CLASS (DSectorEffect)
|
||||
IMPLEMENT_CLASS(DSectorEffect, false, false)
|
||||
|
||||
DSectorEffect::DSectorEffect ()
|
||||
: DThinker(STAT_SECTOREFFECT)
|
||||
|
@ -72,9 +72,11 @@ void DSectorEffect::Serialize(FSerializer &arc)
|
|||
arc("sector", m_Sector);
|
||||
}
|
||||
|
||||
IMPLEMENT_POINTY_CLASS (DMover)
|
||||
DECLARE_POINTER(interpolation)
|
||||
END_POINTERS
|
||||
IMPLEMENT_CLASS(DMover, false, true)
|
||||
|
||||
IMPLEMENT_POINTERS_START(DMover)
|
||||
IMPLEMENT_POINTER(interpolation)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
DMover::DMover ()
|
||||
{
|
||||
|
@ -107,9 +109,7 @@ void DMover::StopInterpolation(bool force)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
IMPLEMENT_CLASS (DMovingFloor)
|
||||
IMPLEMENT_CLASS(DMovingFloor, false, false)
|
||||
|
||||
DMovingFloor::DMovingFloor ()
|
||||
{
|
||||
|
@ -122,7 +122,7 @@ DMovingFloor::DMovingFloor (sector_t *sector)
|
|||
interpolation = sector->SetInterpolation(sector_t::FloorMove, true);
|
||||
}
|
||||
|
||||
IMPLEMENT_CLASS (DMovingCeiling)
|
||||
IMPLEMENT_CLASS(DMovingCeiling, false, false)
|
||||
|
||||
DMovingCeiling::DMovingCeiling ()
|
||||
{
|
||||
|
|
|
@ -12,7 +12,7 @@ public:
|
|||
|
||||
|
||||
void Serialize(FSerializer &arc);
|
||||
void Destroy();
|
||||
void Destroy() override;
|
||||
|
||||
sector_t *GetSector() const { return m_Sector; }
|
||||
|
||||
|
@ -35,7 +35,7 @@ protected:
|
|||
DMover ();
|
||||
|
||||
void Serialize(FSerializer &arc);
|
||||
void Destroy();
|
||||
void Destroy() override;
|
||||
};
|
||||
|
||||
class DMovingFloor : public DMover
|
||||
|
|
231
src/dthinker.cpp
231
src/dthinker.cpp
|
@ -40,6 +40,7 @@
|
|||
#include "doomerrors.h"
|
||||
#include "serializer.h"
|
||||
#include "d_player.h"
|
||||
#include "virtual.h"
|
||||
|
||||
|
||||
static cycle_t ThinkCycles;
|
||||
|
@ -47,7 +48,7 @@ extern cycle_t BotSupportCycles;
|
|||
extern cycle_t ActionCycles;
|
||||
extern int BotWTG;
|
||||
|
||||
IMPLEMENT_CLASS (DThinker)
|
||||
IMPLEMENT_CLASS(DThinker, false, false)
|
||||
|
||||
DThinker *NextToThink;
|
||||
|
||||
|
@ -55,6 +56,12 @@ FThinkerList DThinker::Thinkers[MAX_STATNUM+2];
|
|||
FThinkerList DThinker::FreshThinkers[MAX_STATNUM+1];
|
||||
bool DThinker::bSerialOverride = false;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FThinkerList::AddTail(DThinker *thinker)
|
||||
{
|
||||
assert(thinker->PrevThinker == NULL && thinker->NextThinker == NULL);
|
||||
|
@ -79,6 +86,12 @@ void FThinkerList::AddTail(DThinker *thinker)
|
|||
GC::WriteBarrier(Sentinel, thinker);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
DThinker *FThinkerList::GetHead() const
|
||||
{
|
||||
if (Sentinel == NULL || Sentinel->NextThinker == Sentinel)
|
||||
|
@ -89,6 +102,12 @@ DThinker *FThinkerList::GetHead() const
|
|||
return Sentinel->NextThinker;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
DThinker *FThinkerList::GetTail() const
|
||||
{
|
||||
if (Sentinel == NULL || Sentinel->PrevThinker == Sentinel)
|
||||
|
@ -98,11 +117,23 @@ DThinker *FThinkerList::GetTail() const
|
|||
return Sentinel->PrevThinker;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FThinkerList::IsEmpty() const
|
||||
{
|
||||
return Sentinel == NULL || Sentinel->NextThinker == NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DThinker::SaveList(FSerializer &arc, DThinker *node)
|
||||
{
|
||||
if (node != NULL)
|
||||
|
@ -233,6 +264,12 @@ void DThinker::Destroy ()
|
|||
Super::Destroy();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DThinker::Remove()
|
||||
{
|
||||
if (this == NextToThink)
|
||||
|
@ -253,14 +290,53 @@ void DThinker::Remove()
|
|||
PrevThinker = NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DThinker::PostBeginPlay ()
|
||||
{
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DThinker, PostBeginPlay)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DThinker);
|
||||
self->PostBeginPlay();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DThinker::CallPostBeginPlay()
|
||||
{
|
||||
IFVIRTUAL(DThinker, PostBeginPlay)
|
||||
{
|
||||
// Without the type cast this picks the 'void *' assignment...
|
||||
VMValue params[1] = { (DObject*)this };
|
||||
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
PostBeginPlay();
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DThinker::PostSerialize()
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
DThinker *DThinker::FirstThinker (int statnum)
|
||||
{
|
||||
DThinker *node;
|
||||
|
@ -281,6 +357,12 @@ DThinker *DThinker::FirstThinker (int statnum)
|
|||
return node;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DThinker::ChangeStatNum (int statnum)
|
||||
{
|
||||
FThinkerList *list;
|
||||
|
@ -304,7 +386,19 @@ void DThinker::ChangeStatNum (int statnum)
|
|||
list->AddTail(this);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DThinker, ChangeStatNum)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DThinker);
|
||||
PARAM_INT(stat);
|
||||
self->ChangeStatNum(stat);
|
||||
return 0;
|
||||
}
|
||||
//==========================================================================
|
||||
//
|
||||
// Mark the first thinker of each list
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DThinker::MarkRoots()
|
||||
{
|
||||
for (int i = 0; i <= MAX_STATNUM; ++i)
|
||||
|
@ -315,7 +409,12 @@ void DThinker::MarkRoots()
|
|||
GC::Mark(Thinkers[MAX_STATNUM+1].Sentinel);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Destroy every thinker
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DThinker::DestroyAllThinkers ()
|
||||
{
|
||||
int i;
|
||||
|
@ -332,6 +431,12 @@ void DThinker::DestroyAllThinkers ()
|
|||
GC::FullGC();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DThinker::DestroyThinkersInList (FThinkerList &list)
|
||||
{
|
||||
if (list.Sentinel != NULL)
|
||||
|
@ -346,6 +451,12 @@ void DThinker::DestroyThinkersInList (FThinkerList &list)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DThinker::RunThinkers ()
|
||||
{
|
||||
int i, count;
|
||||
|
@ -376,6 +487,12 @@ void DThinker::RunThinkers ()
|
|||
ThinkCycles.Unclock();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest)
|
||||
{
|
||||
int count = 0;
|
||||
|
@ -398,7 +515,7 @@ int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest)
|
|||
node->Remove();
|
||||
dest->AddTail(node);
|
||||
}
|
||||
node->PostBeginPlay();
|
||||
node->CallPostBeginPlay();
|
||||
}
|
||||
else if (dest != NULL)
|
||||
{
|
||||
|
@ -407,7 +524,7 @@ int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest)
|
|||
|
||||
if (!(node->ObjectFlags & OF_EuthanizeMe))
|
||||
{ // Only tick thinkers not scheduled for destruction
|
||||
node->Tick();
|
||||
node->CallTick();
|
||||
node->ObjectFlags &= ~OF_JustSpawned;
|
||||
GC::CheckGC();
|
||||
}
|
||||
|
@ -416,10 +533,40 @@ int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest)
|
|||
return count;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DThinker::Tick ()
|
||||
{
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DThinker, Tick)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DThinker);
|
||||
self->Tick();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DThinker::CallTick()
|
||||
{
|
||||
IFVIRTUAL(DThinker, Tick)
|
||||
{
|
||||
// Without the type cast this picks the 'void *' assignment...
|
||||
VMValue params[1] = { (DObject*)this };
|
||||
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
|
||||
}
|
||||
else Tick();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
size_t DThinker::PropagateMark()
|
||||
{
|
||||
// Do not choke on partially initialized objects (as happens when loading a savegame fails)
|
||||
|
@ -433,6 +580,12 @@ size_t DThinker::PropagateMark()
|
|||
return Super::PropagateMark();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FThinkerIterator::FThinkerIterator (const PClass *type, int statnum)
|
||||
{
|
||||
if ((unsigned)statnum > MAX_STATNUM)
|
||||
|
@ -450,6 +603,12 @@ FThinkerIterator::FThinkerIterator (const PClass *type, int statnum)
|
|||
m_SearchingFresh = false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FThinkerIterator::FThinkerIterator (const PClass *type, int statnum, DThinker *prev)
|
||||
{
|
||||
if ((unsigned)statnum > MAX_STATNUM)
|
||||
|
@ -474,13 +633,25 @@ FThinkerIterator::FThinkerIterator (const PClass *type, int statnum, DThinker *p
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FThinkerIterator::Reinit ()
|
||||
{
|
||||
m_CurrThinker = DThinker::Thinkers[m_Stat].GetHead();
|
||||
m_SearchingFresh = false;
|
||||
}
|
||||
|
||||
DThinker *FThinkerIterator::Next ()
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
DThinker *FThinkerIterator::Next (bool exact)
|
||||
{
|
||||
if (m_ParentType == NULL)
|
||||
{
|
||||
|
@ -496,7 +667,11 @@ DThinker *FThinkerIterator::Next ()
|
|||
{
|
||||
DThinker *thinker = m_CurrThinker;
|
||||
m_CurrThinker = thinker->NextThinker;
|
||||
if (thinker->IsKindOf(m_ParentType))
|
||||
if (exact)
|
||||
{
|
||||
if (thinker->IsA(m_ParentType)) return thinker;
|
||||
}
|
||||
else if (thinker->IsKindOf(m_ParentType))
|
||||
{
|
||||
return thinker;
|
||||
}
|
||||
|
@ -521,6 +696,52 @@ DThinker *FThinkerIterator::Next ()
|
|||
return NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// This is for scripting, which needs the iterator wrapped into an object with the needed functions exported.
|
||||
// Unfortunately we cannot have templated type conversions in scripts.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class DThinkerIterator : public DObject, public FThinkerIterator
|
||||
{
|
||||
DECLARE_CLASS(DThinkerIterator, DObject)
|
||||
|
||||
public:
|
||||
DThinkerIterator(PClass *cls = nullptr, int statnum = MAX_STATNUM + 1)
|
||||
: FThinkerIterator(cls, statnum)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DThinkerIterator, false, false);
|
||||
DEFINE_ACTION_FUNCTION(DThinkerIterator, Create)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_CLASS_DEF(type, DThinker);
|
||||
PARAM_INT_DEF(statnum);
|
||||
ACTION_RETURN_OBJECT(new DThinkerIterator(type, statnum));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DThinkerIterator, Next)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DThinkerIterator);
|
||||
ACTION_RETURN_OBJECT(self->Next());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DThinkerIterator, Reinit)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DThinkerIterator);
|
||||
self->Reinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
ADD_STAT (think)
|
||||
{
|
||||
FString out;
|
||||
|
|
|
@ -66,10 +66,12 @@ class DThinker : public DObject
|
|||
DECLARE_CLASS (DThinker, DObject)
|
||||
public:
|
||||
DThinker (int statnum = STAT_DEFAULT) throw();
|
||||
void Destroy ();
|
||||
void Destroy () override;
|
||||
virtual ~DThinker ();
|
||||
virtual void Tick ();
|
||||
void CallTick();
|
||||
virtual void PostBeginPlay (); // Called just before the first tick
|
||||
void CallPostBeginPlay();
|
||||
virtual void PostSerialize();
|
||||
size_t PropagateMark();
|
||||
|
||||
|
@ -121,7 +123,7 @@ private:
|
|||
public:
|
||||
FThinkerIterator (const PClass *type, int statnum=MAX_STATNUM+1);
|
||||
FThinkerIterator (const PClass *type, int statnum, DThinker *prev);
|
||||
DThinker *Next ();
|
||||
DThinker *Next (bool exact = false);
|
||||
void Reinit ();
|
||||
};
|
||||
|
||||
|
@ -146,9 +148,9 @@ public:
|
|||
TThinkerIterator (const char *subclass, int statnum=MAX_STATNUM+1) : FThinkerIterator(PClass::FindClass(subclass), statnum)
|
||||
{
|
||||
}
|
||||
T *Next ()
|
||||
T *Next (bool exact = false)
|
||||
{
|
||||
return static_cast<T *>(FThinkerIterator::Next ());
|
||||
return static_cast<T *>(FThinkerIterator::Next (exact));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -374,7 +374,7 @@ public:
|
|||
static FileWriter *Open(const char *filename);
|
||||
|
||||
virtual size_t Write(const void *buffer, size_t len);
|
||||
size_t Printf(const char *fmt, ...);
|
||||
size_t Printf(const char *fmt, ...) GCCPRINTF(2,3);
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@
|
|||
#include "p_setup.h"
|
||||
#include "p_spec.h"
|
||||
#include "r_utility.h"
|
||||
#include "a_ammo.h"
|
||||
#include "math/cmath.h"
|
||||
|
||||
static FRandom pr_script("FScript");
|
||||
|
@ -1785,9 +1786,7 @@ public:
|
|||
void Destroy() { Super::Destroy(); m_Sector->lightingdata=NULL; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
IMPLEMENT_CLASS (DLightLevel)
|
||||
IMPLEMENT_CLASS(DLightLevel, false, false)
|
||||
|
||||
void DLightLevel::Serialize(FSerializer &arc)
|
||||
{
|
||||
|
@ -2015,13 +2014,13 @@ void FParser::SF_CeilingTexture(void)
|
|||
|
||||
void FParser::SF_ChangeHubLevel(void)
|
||||
{
|
||||
I_Error("FS hub system permanently disabled\n");
|
||||
script_error("FS hub system permanently disabled\n");
|
||||
}
|
||||
|
||||
// for start map: start new game on a particular skill
|
||||
void FParser::SF_StartSkill(void)
|
||||
{
|
||||
I_Error("startskill is not supported by this implementation!\n");
|
||||
script_error("startskill is not supported by this implementation!\n");
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -2977,7 +2976,7 @@ void FParser::SF_ObjAwaken(void)
|
|||
|
||||
if(mo)
|
||||
{
|
||||
mo->Activate(Script->trigger);
|
||||
mo->CallActivate(Script->trigger);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3636,7 +3635,7 @@ void FParser::SF_Pow()
|
|||
{
|
||||
if (CheckArgs(2))
|
||||
{
|
||||
t_return.setDouble(pow(floatvalue(t_argv[0]), floatvalue(t_argv[1])));
|
||||
t_return.setDouble(g_pow(floatvalue(t_argv[0]), floatvalue(t_argv[1])));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ void FParser::NextToken()
|
|||
}
|
||||
if(!Section)
|
||||
{
|
||||
I_Error("section not found!\n");
|
||||
script_error("section not found!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -708,6 +708,18 @@ void FParser::EvaluateExpression(svalue_t &result, int start, int stop)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FS_Error(const char *error, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char errortext[MAX_ERRORTEXT];
|
||||
|
||||
va_start(argptr, error);
|
||||
myvsnprintf(errortext, MAX_ERRORTEXT, error, argptr);
|
||||
va_end(argptr);
|
||||
throw CFraggleScriptError(errortext);
|
||||
}
|
||||
|
||||
|
||||
void FParser::ErrorMessage(FString msg)
|
||||
{
|
||||
int linenum = 0;
|
||||
|
@ -721,7 +733,7 @@ void FParser::ErrorMessage(FString msg)
|
|||
}
|
||||
|
||||
//lineinfo.Format("Script %d, line %d: ", Script->scriptnum, linenum);
|
||||
I_Error("Script %d, line %d: %s", Script->scriptnum, linenum, msg.GetChars());
|
||||
FS_Error("Script %d, line %d: %s", Script->scriptnum, linenum, msg.GetChars());
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -71,9 +71,11 @@
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
IMPLEMENT_POINTY_CLASS(DFsSection)
|
||||
DECLARE_POINTER(next)
|
||||
END_POINTERS
|
||||
IMPLEMENT_CLASS(DFsSection, false, true)
|
||||
|
||||
IMPLEMENT_POINTERS_START(DFsSection)
|
||||
IMPLEMENT_POINTER(next)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -75,23 +75,23 @@ AActor *trigger_obj;
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
#define DECLARE_16_POINTERS(v, i) \
|
||||
DECLARE_POINTER(v[i]) \
|
||||
DECLARE_POINTER(v[i+1]) \
|
||||
DECLARE_POINTER(v[i+2]) \
|
||||
DECLARE_POINTER(v[i+3]) \
|
||||
DECLARE_POINTER(v[i+4]) \
|
||||
DECLARE_POINTER(v[i+5]) \
|
||||
DECLARE_POINTER(v[i+6]) \
|
||||
DECLARE_POINTER(v[i+7]) \
|
||||
DECLARE_POINTER(v[i+8]) \
|
||||
DECLARE_POINTER(v[i+9]) \
|
||||
DECLARE_POINTER(v[i+10]) \
|
||||
DECLARE_POINTER(v[i+11]) \
|
||||
DECLARE_POINTER(v[i+12]) \
|
||||
DECLARE_POINTER(v[i+13]) \
|
||||
DECLARE_POINTER(v[i+14]) \
|
||||
DECLARE_POINTER(v[i+15]) \
|
||||
#define IMPLEMENT_16_POINTERS(v, i) \
|
||||
IMPLEMENT_POINTER(v[i]) \
|
||||
IMPLEMENT_POINTER(v[i+1]) \
|
||||
IMPLEMENT_POINTER(v[i+2]) \
|
||||
IMPLEMENT_POINTER(v[i+3]) \
|
||||
IMPLEMENT_POINTER(v[i+4]) \
|
||||
IMPLEMENT_POINTER(v[i+5]) \
|
||||
IMPLEMENT_POINTER(v[i+6]) \
|
||||
IMPLEMENT_POINTER(v[i+7]) \
|
||||
IMPLEMENT_POINTER(v[i+8]) \
|
||||
IMPLEMENT_POINTER(v[i+9]) \
|
||||
IMPLEMENT_POINTER(v[i+10]) \
|
||||
IMPLEMENT_POINTER(v[i+11]) \
|
||||
IMPLEMENT_POINTER(v[i+12]) \
|
||||
IMPLEMENT_POINTER(v[i+13]) \
|
||||
IMPLEMENT_POINTER(v[i+14]) \
|
||||
IMPLEMENT_POINTER(v[i+15]) \
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -99,30 +99,32 @@ AActor *trigger_obj;
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
IMPLEMENT_POINTY_CLASS(DFsScript)
|
||||
DECLARE_POINTER(parent)
|
||||
DECLARE_POINTER(trigger)
|
||||
DECLARE_16_POINTERS(sections, 0)
|
||||
DECLARE_POINTER(sections[16])
|
||||
DECLARE_16_POINTERS(variables, 0)
|
||||
DECLARE_16_POINTERS(children, 0)
|
||||
DECLARE_16_POINTERS(children, 16)
|
||||
DECLARE_16_POINTERS(children, 32)
|
||||
DECLARE_16_POINTERS(children, 48)
|
||||
DECLARE_16_POINTERS(children, 64)
|
||||
DECLARE_16_POINTERS(children, 80)
|
||||
DECLARE_16_POINTERS(children, 96)
|
||||
DECLARE_16_POINTERS(children, 112)
|
||||
DECLARE_16_POINTERS(children, 128)
|
||||
DECLARE_16_POINTERS(children, 144)
|
||||
DECLARE_16_POINTERS(children, 160)
|
||||
DECLARE_16_POINTERS(children, 176)
|
||||
DECLARE_16_POINTERS(children, 192)
|
||||
DECLARE_16_POINTERS(children, 208)
|
||||
DECLARE_16_POINTERS(children, 224)
|
||||
DECLARE_16_POINTERS(children, 240)
|
||||
DECLARE_POINTER(children[256])
|
||||
END_POINTERS
|
||||
IMPLEMENT_CLASS(DFsScript, false, true)
|
||||
|
||||
IMPLEMENT_POINTERS_START(DFsScript)
|
||||
IMPLEMENT_POINTER(parent)
|
||||
IMPLEMENT_POINTER(trigger)
|
||||
IMPLEMENT_16_POINTERS(sections, 0)
|
||||
IMPLEMENT_POINTER(sections[16])
|
||||
IMPLEMENT_16_POINTERS(variables, 0)
|
||||
IMPLEMENT_16_POINTERS(children, 0)
|
||||
IMPLEMENT_16_POINTERS(children, 16)
|
||||
IMPLEMENT_16_POINTERS(children, 32)
|
||||
IMPLEMENT_16_POINTERS(children, 48)
|
||||
IMPLEMENT_16_POINTERS(children, 64)
|
||||
IMPLEMENT_16_POINTERS(children, 80)
|
||||
IMPLEMENT_16_POINTERS(children, 96)
|
||||
IMPLEMENT_16_POINTERS(children, 112)
|
||||
IMPLEMENT_16_POINTERS(children, 128)
|
||||
IMPLEMENT_16_POINTERS(children, 144)
|
||||
IMPLEMENT_16_POINTERS(children, 160)
|
||||
IMPLEMENT_16_POINTERS(children, 176)
|
||||
IMPLEMENT_16_POINTERS(children, 192)
|
||||
IMPLEMENT_16_POINTERS(children, 208)
|
||||
IMPLEMENT_16_POINTERS(children, 224)
|
||||
IMPLEMENT_16_POINTERS(children, 240)
|
||||
IMPLEMENT_POINTER(children[256])
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -249,7 +251,7 @@ void DFsScript::ParseScript(char *position)
|
|||
FParser parse(this);
|
||||
parse.Run(position, data, data + len);
|
||||
}
|
||||
catch (CRecoverableError &err)
|
||||
catch (CFraggleScriptError &err)
|
||||
{
|
||||
Printf ("%s\n", err.GetMessage());
|
||||
}
|
||||
|
@ -267,12 +269,14 @@ void DFsScript::ParseScript(char *position)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
IMPLEMENT_POINTY_CLASS(DRunningScript)
|
||||
DECLARE_POINTER(prev)
|
||||
DECLARE_POINTER(next)
|
||||
DECLARE_POINTER(trigger)
|
||||
DECLARE_16_POINTERS(variables, 0)
|
||||
END_POINTERS
|
||||
IMPLEMENT_CLASS(DRunningScript, false, true)
|
||||
|
||||
IMPLEMENT_POINTERS_START(DRunningScript)
|
||||
IMPLEMENT_POINTER(prev)
|
||||
IMPLEMENT_POINTER(next)
|
||||
IMPLEMENT_POINTER(trigger)
|
||||
IMPLEMENT_16_POINTERS(variables, 0)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -375,10 +379,13 @@ void DRunningScript::Serialize(FSerializer &arc)
|
|||
// The main thinker
|
||||
//
|
||||
//==========================================================================
|
||||
IMPLEMENT_POINTY_CLASS(DFraggleThinker)
|
||||
DECLARE_POINTER(RunningScripts)
|
||||
DECLARE_POINTER(LevelScript)
|
||||
END_POINTERS
|
||||
|
||||
IMPLEMENT_CLASS(DFraggleThinker, false, true)
|
||||
|
||||
IMPLEMENT_POINTERS_START(DFraggleThinker)
|
||||
IMPLEMENT_POINTER(RunningScripts)
|
||||
IMPLEMENT_POINTER(LevelScript)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
TObjPtr<DFraggleThinker> DFraggleThinker::ActiveThinker;
|
||||
|
||||
|
|
|
@ -41,12 +41,22 @@
|
|||
#include "p_lnspec.h"
|
||||
#include "m_fixed.h"
|
||||
#include "actor.h"
|
||||
#include "doomerrors.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// This pragma saves 8kb of wasted code.
|
||||
#pragma pointers_to_members( full_generality, single_inheritance )
|
||||
#endif
|
||||
|
||||
|
||||
class CFraggleScriptError : public CDoomError
|
||||
{
|
||||
public:
|
||||
CFraggleScriptError() : CDoomError() {}
|
||||
CFraggleScriptError(const char *message) : CDoomError(message) {}
|
||||
};
|
||||
|
||||
|
||||
class DRunningScript;
|
||||
|
||||
|
||||
|
@ -337,7 +347,7 @@ public:
|
|||
|
||||
DFsScript();
|
||||
~DFsScript();
|
||||
void Destroy();
|
||||
void Destroy() override;
|
||||
void Serialize(FSerializer &ar);
|
||||
|
||||
DFsVariable *NewVariable(const char *name, int vtype);
|
||||
|
@ -652,7 +662,7 @@ class DRunningScript : public DObject
|
|||
|
||||
public:
|
||||
DRunningScript(AActor *trigger=NULL, DFsScript *owner = NULL, int index = 0) ;
|
||||
void Destroy();
|
||||
void Destroy() override;
|
||||
void Serialize(FSerializer &arc);
|
||||
|
||||
TObjPtr<DFsScript> script;
|
||||
|
@ -687,7 +697,7 @@ public:
|
|||
bool nocheckposition;
|
||||
|
||||
DFraggleThinker();
|
||||
void Destroy();
|
||||
void Destroy() override;
|
||||
|
||||
|
||||
void Serialize(FSerializer & arc);
|
||||
|
@ -708,7 +718,7 @@ public:
|
|||
|
||||
#include "t_fs.h"
|
||||
|
||||
void script_error(const char *s, ...);
|
||||
void script_error(const char *s, ...) GCCPRINTF(1,2);
|
||||
void FS_EmulateCmd(char * string);
|
||||
|
||||
extern AActor *trigger_obj;
|
||||
|
|
|
@ -179,10 +179,12 @@ AActor* actorvalue(const svalue_t &svalue)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
IMPLEMENT_POINTY_CLASS(DFsVariable)
|
||||
DECLARE_POINTER (next)
|
||||
DECLARE_POINTER (actor)
|
||||
END_POINTERS
|
||||
IMPLEMENT_CLASS(DFsVariable, false, true)
|
||||
|
||||
IMPLEMENT_POINTERS_START(DFsVariable)
|
||||
IMPLEMENT_POINTER(next)
|
||||
IMPLEMENT_POINTER(actor)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_local.h"
|
||||
#include "p_enemy.h"
|
||||
#include "a_action.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BspiAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
A_FaceTarget (self);
|
||||
|
||||
// launch a missile
|
||||
P_SpawnMissile (self, self->target, PClass::FindActor("ArachnotronPlasma"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BabyMetal)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
S_Sound (self, CHAN_BODY, "baby/walk", 1, ATTN_IDLE);
|
||||
A_Chase (stack, self);
|
||||
return 0;
|
||||
}
|
|
@ -1,160 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_enemy.h"
|
||||
#include "gstrings.h"
|
||||
#include "a_action.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
//
|
||||
// PIT_VileCheck
|
||||
// Detect a corpse that could be raised.
|
||||
//
|
||||
void A_Fire(AActor *self, double height);
|
||||
|
||||
|
||||
//
|
||||
// A_VileStart
|
||||
//
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_VileStart)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
S_Sound (self, CHAN_VOICE, "vile/start", 1, ATTN_NORM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_Fire
|
||||
// Keep fire in front of player unless out of sight
|
||||
//
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_StartFire)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
S_Sound (self, CHAN_BODY, "vile/firestrt", 1, ATTN_NORM);
|
||||
A_Fire (self, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FireCrackle)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
S_Sound (self, CHAN_BODY, "vile/firecrkl", 1, ATTN_NORM);
|
||||
A_Fire (self, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Fire)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_FLOAT_OPT(height) { height = 0; }
|
||||
|
||||
A_Fire(self, height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void A_Fire(AActor *self, double height)
|
||||
{
|
||||
AActor *dest;
|
||||
|
||||
dest = self->tracer;
|
||||
if (dest == NULL || self->target == NULL)
|
||||
return;
|
||||
|
||||
// don't move it if the vile lost sight
|
||||
if (!P_CheckSight (self->target, dest, 0) )
|
||||
return;
|
||||
|
||||
DVector3 newpos = dest->Vec3Angle(24., dest->Angles.Yaw, height);
|
||||
self->SetOrigin(newpos, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// A_VileTarget
|
||||
// Spawn the hellfire
|
||||
//
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileTarget)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_CLASS_OPT(fire, AActor) { fire = PClass::FindActor("ArchvileFire"); }
|
||||
|
||||
AActor *fog;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
A_FaceTarget (self);
|
||||
|
||||
fog = Spawn (fire, self->target->Pos(), ALLOW_REPLACE);
|
||||
|
||||
self->tracer = fog;
|
||||
fog->target = self;
|
||||
fog->tracer = self->target;
|
||||
A_Fire(fog, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// A_VileAttack
|
||||
//
|
||||
|
||||
// A_VileAttack flags
|
||||
#define VAF_DMGTYPEAPPLYTODIRECT 1
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_SOUND_OPT (snd) { snd = "vile/stop"; }
|
||||
PARAM_INT_OPT (dmg) { dmg = 20; }
|
||||
PARAM_INT_OPT (blastdmg) { blastdmg = 70; }
|
||||
PARAM_INT_OPT (blastrad) { blastrad = 70; }
|
||||
PARAM_FLOAT_OPT (thrust) { thrust = 1; }
|
||||
PARAM_NAME_OPT (dmgtype) { dmgtype = NAME_Fire; }
|
||||
PARAM_INT_OPT (flags) { flags = 0; }
|
||||
|
||||
AActor *fire, *target;
|
||||
|
||||
if (NULL == (target = self->target))
|
||||
return 0;
|
||||
|
||||
A_FaceTarget (self);
|
||||
|
||||
if (!P_CheckSight (self, target, 0) )
|
||||
return 0;
|
||||
|
||||
S_Sound (self, CHAN_WEAPON, snd, 1, ATTN_NORM);
|
||||
|
||||
int newdam;
|
||||
|
||||
if (flags & VAF_DMGTYPEAPPLYTODIRECT)
|
||||
newdam = P_DamageMobj (target, self, self, dmg, dmgtype);
|
||||
|
||||
else
|
||||
newdam = P_DamageMobj (target, self, self, dmg, NAME_None);
|
||||
|
||||
P_TraceBleed (newdam > 0 ? newdam : dmg, target);
|
||||
|
||||
fire = self->tracer;
|
||||
|
||||
if (fire != NULL)
|
||||
{
|
||||
// move the fire between the vile and the player
|
||||
DVector3 pos = target->Vec3Angle(-24., self->Angles.Yaw, 0);
|
||||
fire->SetOrigin (pos, true);
|
||||
|
||||
P_RadiusAttack (fire, self, blastdmg, blastrad, dmgtype, 0);
|
||||
}
|
||||
if (!(target->flags7 & MF7_DONTTHRUST))
|
||||
{
|
||||
target->Vel.Z = thrust * 1000 / MAX(1, target->Mass);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,325 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "m_random.h"
|
||||
#include "p_local.h"
|
||||
#include "p_enemy.h"
|
||||
#include "s_sound.h"
|
||||
#include "statnums.h"
|
||||
#include "a_specialspot.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "g_level.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_brainscream ("BrainScream");
|
||||
static FRandom pr_brainexplode ("BrainExplode");
|
||||
static FRandom pr_spawnfly ("SpawnFly");
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BrainAwake)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
// killough 3/26/98: only generates sound now
|
||||
S_Sound (self, CHAN_VOICE, "brain/sight", 1, ATTN_NONE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BrainPain)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
S_Sound (self, CHAN_VOICE, "brain/pain", 1, ATTN_NONE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void BrainishExplosion (const DVector3 &pos)
|
||||
{
|
||||
AActor *boom = Spawn("Rocket", pos, NO_REPLACE);
|
||||
if (boom != NULL)
|
||||
{
|
||||
boom->DeathSound = "misc/brainexplode";
|
||||
boom->Vel.Z = pr_brainscream() /128.;
|
||||
|
||||
PClassActor *cls = PClass::FindActor("BossBrain");
|
||||
if (cls != NULL)
|
||||
{
|
||||
FState *state = cls->FindState(NAME_Brainexplode);
|
||||
if (state != NULL)
|
||||
boom->SetState (state);
|
||||
}
|
||||
boom->effects = 0;
|
||||
boom->SetDamage(0); // disables collision detection which is not wanted here
|
||||
boom->tics -= pr_brainscream() & 7;
|
||||
if (boom->tics < 1)
|
||||
boom->tics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BrainScream)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
for (double x = -196; x < +320; x += 8)
|
||||
{
|
||||
// (1 / 512.) is actually what the original value of 128 did, even though it probably meant 128 map units.
|
||||
BrainishExplosion(self->Vec2OffsetZ(x, -320, (1 / 512.) + pr_brainexplode() * 2));
|
||||
}
|
||||
S_Sound (self, CHAN_VOICE, "brain/death", 1, ATTN_NONE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BrainExplode)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
double x = pr_brainexplode.Random2() / 32.;
|
||||
DVector3 pos = self->Vec2OffsetZ(x, 0, 1 / 512. + pr_brainexplode() * 2);
|
||||
BrainishExplosion(pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BrainDie)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
// [RH] If noexit, then don't end the level.
|
||||
if ((deathmatch || alwaysapplydmflags) && (dmflags & DF_NO_EXIT))
|
||||
return 0;
|
||||
|
||||
// New dmflag: Kill all boss spawned monsters before ending the level.
|
||||
if (dmflags2 & DF2_KILLBOSSMONST)
|
||||
{
|
||||
int count; // Repeat until we have no more boss-spawned monsters.
|
||||
do // (e.g. Pain Elementals can spawn more to kill upon death.)
|
||||
{
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
count = 0;
|
||||
while ((mo = it.Next()))
|
||||
{
|
||||
if (mo->health > 0 && mo->flags4 & MF4_BOSSSPAWNED)
|
||||
{
|
||||
P_DamageMobj(mo, self, self, mo->health, NAME_None,
|
||||
DMG_NO_ARMOR|DMG_FORCED|DMG_THRUSTLESS|DMG_NO_FACTOR);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
} while (count != 0);
|
||||
}
|
||||
|
||||
G_ExitLevel (0, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BrainSpit)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; }
|
||||
|
||||
DSpotState *state = DSpotState::GetSpotState();
|
||||
AActor *targ;
|
||||
AActor *spit;
|
||||
bool isdefault = false;
|
||||
|
||||
// shoot a cube at current target
|
||||
targ = state->GetNextInList(PClass::FindActor("BossTarget"), G_SkillProperty(SKILLP_EasyBossBrain));
|
||||
|
||||
if (targ != NULL)
|
||||
{
|
||||
if (spawntype == NULL)
|
||||
{
|
||||
spawntype = PClass::FindActor("SpawnShot");
|
||||
isdefault = true;
|
||||
}
|
||||
|
||||
// spawn brain missile
|
||||
spit = P_SpawnMissile (self, targ, spawntype);
|
||||
|
||||
if (spit != NULL)
|
||||
{
|
||||
// Boss cubes should move freely to their destination so it's
|
||||
// probably best to disable all collision detection for them.
|
||||
if (spit->flags & MF_NOCLIP) spit->flags5 |= MF5_NOINTERACTION;
|
||||
|
||||
spit->target = targ;
|
||||
spit->master = self;
|
||||
// [RH] Do this correctly for any trajectory. Doom would divide by 0
|
||||
// if the target had the same y coordinate as the spitter.
|
||||
if (spit->Vel.X == 0 && spit->Vel.Y == 0)
|
||||
{
|
||||
spit->special2 = 0;
|
||||
}
|
||||
else if (fabs(spit->Vel.Y) > fabs(spit->Vel.X))
|
||||
{
|
||||
spit->special2 = int((targ->Y() - self->Y()) / spit->Vel.Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
spit->special2 = int((targ->X() - self->X()) / spit->Vel.X);
|
||||
}
|
||||
// [GZ] Calculates when the projectile will have reached destination
|
||||
spit->special2 += level.maptime;
|
||||
spit->flags6 |= MF6_BOSSCUBE;
|
||||
}
|
||||
|
||||
if (!isdefault)
|
||||
{
|
||||
S_Sound(self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// compatibility fallback
|
||||
S_Sound (self, CHAN_WEAPON, "brain/spit", 1, ATTN_NONE);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SpawnFly(AActor *self, PClassActor *spawntype, FSoundID sound)
|
||||
{
|
||||
AActor *newmobj;
|
||||
AActor *fog;
|
||||
AActor *eye = self->master; // The eye is the spawnshot's master, not the target!
|
||||
AActor *targ = self->target; // Unlike other projectiles, the target is the intended destination.
|
||||
int r;
|
||||
|
||||
// [GZ] Should be more viable than a countdown...
|
||||
if (self->special2 != 0)
|
||||
{
|
||||
if (self->special2 > level.maptime)
|
||||
return; // still flying
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self->reactiontime == 0 || --self->reactiontime != 0)
|
||||
return; // still flying
|
||||
}
|
||||
|
||||
if (spawntype != NULL)
|
||||
{
|
||||
fog = Spawn (spawntype, targ->Pos(), ALLOW_REPLACE);
|
||||
if (fog != NULL) S_Sound (fog, CHAN_BODY, sound, 1, ATTN_NORM);
|
||||
}
|
||||
|
||||
FName SpawnName;
|
||||
|
||||
DDropItem *di; // di will be our drop item list iterator
|
||||
DDropItem *drop; // while drop stays as the reference point.
|
||||
int n = 0;
|
||||
|
||||
// First see if this cube has its own actor list
|
||||
drop = self->GetDropItems();
|
||||
|
||||
// If not, then default back to its master's list
|
||||
if (drop == NULL && eye != NULL)
|
||||
drop = eye->GetDropItems();
|
||||
|
||||
if (drop != NULL)
|
||||
{
|
||||
for (di = drop; di != NULL; di = di->Next)
|
||||
{
|
||||
if (di->Name != NAME_None)
|
||||
{
|
||||
if (di->Amount < 0)
|
||||
{
|
||||
di->Amount = 1; // default value is -1, we need a positive value.
|
||||
}
|
||||
n += di->Amount; // this is how we can weight the list.
|
||||
}
|
||||
}
|
||||
di = drop;
|
||||
n = pr_spawnfly(n);
|
||||
while (n >= 0)
|
||||
{
|
||||
if (di->Name != NAME_None)
|
||||
{
|
||||
n -= di->Amount; // logically, none of the -1 values have survived by now.
|
||||
}
|
||||
if ((di->Next != NULL) && (n >= 0))
|
||||
{
|
||||
di = di->Next;
|
||||
}
|
||||
else
|
||||
{
|
||||
n = -1;
|
||||
}
|
||||
}
|
||||
SpawnName = di->Name;
|
||||
}
|
||||
if (SpawnName == NAME_None)
|
||||
{
|
||||
// Randomly select monster to spawn.
|
||||
r = pr_spawnfly ();
|
||||
|
||||
// Probability distribution (kind of :),
|
||||
// decreasing likelihood.
|
||||
if (r < 50) SpawnName = "DoomImp";
|
||||
else if (r < 90) SpawnName = "Demon";
|
||||
else if (r < 120) SpawnName = "Spectre";
|
||||
else if (r < 130) SpawnName = "PainElemental";
|
||||
else if (r < 160) SpawnName = "Cacodemon";
|
||||
else if (r < 162) SpawnName = "Archvile";
|
||||
else if (r < 172) SpawnName = "Revenant";
|
||||
else if (r < 192) SpawnName = "Arachnotron";
|
||||
else if (r < 222) SpawnName = "Fatso";
|
||||
else if (r < 246) SpawnName = "HellKnight";
|
||||
else SpawnName = "BaronOfHell";
|
||||
}
|
||||
spawntype = PClass::FindActor(SpawnName);
|
||||
if (spawntype != NULL)
|
||||
{
|
||||
newmobj = Spawn (spawntype, targ->Pos(), ALLOW_REPLACE);
|
||||
if (newmobj != NULL)
|
||||
{
|
||||
// Make the new monster hate what the boss eye hates
|
||||
if (eye != NULL)
|
||||
{
|
||||
newmobj->CopyFriendliness (eye, false);
|
||||
}
|
||||
// Make it act as if it was around when the player first made noise
|
||||
// (if the player has made noise).
|
||||
newmobj->LastHeard = newmobj->Sector->SoundTarget;
|
||||
|
||||
if (newmobj->SeeState != NULL && P_LookForPlayers (newmobj, true, NULL))
|
||||
{
|
||||
newmobj->SetState (newmobj->SeeState);
|
||||
}
|
||||
if (!(newmobj->ObjectFlags & OF_EuthanizeMe))
|
||||
{
|
||||
// telefrag anything in this spot
|
||||
P_TeleportMove (newmobj, newmobj->Pos(), true);
|
||||
}
|
||||
newmobj->flags4 |= MF4_BOSSSPAWNED;
|
||||
}
|
||||
}
|
||||
|
||||
// remove self (i.e., cube).
|
||||
self->Destroy ();
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnFly)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_CLASS_OPT (spawntype, AActor) { spawntype = NULL; }
|
||||
|
||||
FSoundID sound;
|
||||
|
||||
if (spawntype != NULL)
|
||||
{
|
||||
sound = GetDefaultByType(spawntype)->SeeSound;
|
||||
}
|
||||
else
|
||||
{
|
||||
spawntype = PClass::FindActor("SpawnFire");
|
||||
sound = "brain/spawn";
|
||||
}
|
||||
SpawnFly(self, spawntype, sound);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// travelling cube sound
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SpawnSound)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
S_Sound (self, CHAN_BODY, "brain/cube", 1, ATTN_IDLE);
|
||||
SpawnFly(self, PClass::FindActor("SpawnFire"), "brain/spawn");
|
||||
return 0;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
static FRandom pr_bruisattack ("BruisAttack");
|
||||
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BruisAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
if (self->CheckMeleeRange ())
|
||||
{
|
||||
int damage = (pr_bruisattack()%8+1)*10;
|
||||
S_Sound (self, CHAN_WEAPON, "baron/melee", 1, ATTN_NORM);
|
||||
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// launch a missile
|
||||
P_SpawnMissile (self, self->target, PClass::FindActor("BaronBall"));
|
||||
return 0;
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "m_random.h"
|
||||
#include "p_local.h"
|
||||
#include "p_enemy.h"
|
||||
#include "gstrings.h"
|
||||
#include "a_action.h"
|
||||
#include "s_sound.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_headattack ("HeadAttack");
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_HeadAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
A_FaceTarget (self);
|
||||
if (self->CheckMeleeRange ())
|
||||
{
|
||||
int damage = (pr_headattack()%6+1)*10;
|
||||
S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM);
|
||||
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// launch a missile
|
||||
P_SpawnMissile (self, self->target, PClass::FindActor("CacodemonBall"));
|
||||
return 0;
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_enemy.h"
|
||||
#include "a_action.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_CyberAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
A_FaceTarget (self);
|
||||
P_SpawnMissile (self, self->target, PClass::FindActor("Rocket"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Hoof)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
S_Sound (self, CHAN_BODY, "cyber/hoof", 1, ATTN_IDLE);
|
||||
A_Chase (stack, self);
|
||||
return 0;
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "m_random.h"
|
||||
#include "p_local.h"
|
||||
#include "p_enemy.h"
|
||||
#include "gstrings.h"
|
||||
#include "a_action.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_sargattack ("SargAttack");
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SargAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
A_FaceTarget (self);
|
||||
if (self->CheckMeleeRange ())
|
||||
{
|
||||
int damage = ((pr_sargattack()%10)+1)*4;
|
||||
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
#ifndef __A_DOOMGLOBAL_H__
|
||||
#define __A_DOOMGLOBAL_H__
|
||||
|
||||
#include "info.h"
|
||||
|
||||
class AScriptedMarine : public AActor
|
||||
{
|
||||
DECLARE_CLASS (AScriptedMarine, AActor)
|
||||
public:
|
||||
enum EMarineWeapon
|
||||
{
|
||||
WEAPON_Dummy,
|
||||
WEAPON_Fist,
|
||||
WEAPON_BerserkFist,
|
||||
WEAPON_Chainsaw,
|
||||
WEAPON_Pistol,
|
||||
WEAPON_Shotgun,
|
||||
WEAPON_SuperShotgun,
|
||||
WEAPON_Chaingun,
|
||||
WEAPON_RocketLauncher,
|
||||
WEAPON_PlasmaRifle,
|
||||
WEAPON_Railgun,
|
||||
WEAPON_BFG
|
||||
};
|
||||
|
||||
void Activate (AActor *activator);
|
||||
void Deactivate (AActor *activator);
|
||||
void BeginPlay ();
|
||||
void Tick ();
|
||||
void SetWeapon (EMarineWeapon);
|
||||
void SetSprite (PClassActor *source);
|
||||
|
||||
void Serialize(FSerializer &arc);
|
||||
|
||||
int CurrentWeapon;
|
||||
|
||||
protected:
|
||||
bool GetWeaponStates(int weap, FState *&melee, FState *&missile);
|
||||
|
||||
int SpriteOverride;
|
||||
};
|
||||
|
||||
#endif //__A_DOOMGLOBAL_H__
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_local.h"
|
||||
#include "p_enemy.h"
|
||||
#include "gstrings.h"
|
||||
#include "a_action.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_troopattack ("TroopAttack");
|
||||
|
||||
//
|
||||
// A_TroopAttack
|
||||
//
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_TroopAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
A_FaceTarget (self);
|
||||
if (self->CheckMeleeRange ())
|
||||
{
|
||||
int damage = (pr_troopattack()%8+1)*3;
|
||||
S_Sound (self, CHAN_WEAPON, "imp/melee", 1, ATTN_NORM);
|
||||
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// launch a missile
|
||||
P_SpawnMissile (self, self->target, PClass::FindActor("DoomImpBall"));
|
||||
return 0;
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "p_local.h"
|
||||
#include "p_spec.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "m_random.h"
|
||||
#include "gi.h"
|
||||
#include "doomstat.h"
|
||||
#include "gstrings.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
#include "g_level.h"
|
||||
#include "p_enemy.h"
|
||||
#include "a_doomglobal.h"
|
||||
#include "a_specialspot.h"
|
||||
#include "templates.h"
|
||||
#include "m_bbox.h"
|
||||
#include "portal.h"
|
||||
#include "d_player.h"
|
||||
#include "p_maputl.h"
|
||||
#include "serializer.h"
|
||||
#include "g_shared/a_pickups.h"
|
||||
|
||||
// Include all the other Doom stuff here to reduce compile time
|
||||
#include "a_arachnotron.cpp"
|
||||
#include "a_archvile.cpp"
|
||||
#include "a_bossbrain.cpp"
|
||||
#include "a_bruiser.cpp"
|
||||
#include "a_cacodemon.cpp"
|
||||
#include "a_cyberdemon.cpp"
|
||||
#include "a_demon.cpp"
|
||||
#include "a_doomimp.cpp"
|
||||
#include "a_doomweaps.cpp"
|
||||
#include "a_fatso.cpp"
|
||||
#include "a_keen.cpp"
|
||||
#include "a_lostsoul.cpp"
|
||||
#include "a_painelemental.cpp"
|
||||
#include "a_possessed.cpp"
|
||||
#include "a_revenant.cpp"
|
||||
#include "a_spidermaster.cpp"
|
||||
#include "a_scriptedmarine.cpp"
|
||||
|
||||
// The barrel of green goop ------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BarrelDestroy)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (dmflags2 & DF2_BARRELS_RESPAWN)
|
||||
{
|
||||
self->Height = self->GetDefault()->Height;
|
||||
self->renderflags |= RF_INVISIBLE;
|
||||
self->flags &= ~MF_SOLID;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->Destroy ();
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,782 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "s_sound.h"
|
||||
#include "m_random.h"
|
||||
#include "a_pickups.h"
|
||||
#include "d_player.h"
|
||||
#include "p_pspr.h"
|
||||
#include "p_local.h"
|
||||
#include "gstrings.h"
|
||||
#include "p_effect.h"
|
||||
#include "gi.h"
|
||||
#include "templates.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
#include "doomstat.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_punch ("Punch");
|
||||
static FRandom pr_saw ("Saw");
|
||||
static FRandom pr_fireshotgun2 ("FireSG2");
|
||||
static FRandom pr_fireplasma ("FirePlasma");
|
||||
static FRandom pr_firerail ("FireRail");
|
||||
static FRandom pr_bfgspray ("BFGSpray");
|
||||
static FRandom pr_oldbfg ("OldBFG");
|
||||
|
||||
//
|
||||
// A_Punch
|
||||
//
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Punch)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
DAngle angle;
|
||||
int damage;
|
||||
DAngle pitch;
|
||||
FTranslatedLineTarget t;
|
||||
|
||||
if (self->player != NULL)
|
||||
{
|
||||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != NULL && !(weapon->WeaponFlags & WIF_DEHAMMO) && ACTION_CALL_FROM_PSPRITE())
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
damage = (pr_punch()%10+1)<<1;
|
||||
|
||||
if (self->FindInventory<APowerStrength>())
|
||||
damage *= 10;
|
||||
|
||||
angle = self->Angles.Yaw + pr_punch.Random2() * (5.625 / 256);
|
||||
pitch = P_AimLineAttack (self, angle, MELEERANGE);
|
||||
|
||||
P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, LAF_ISMELEEATTACK, &t);
|
||||
|
||||
// turn to face target
|
||||
if (t.linetarget)
|
||||
{
|
||||
S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM);
|
||||
self->Angles.Yaw = t.angleFromSource;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// A_FirePistol
|
||||
//
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FirePistol)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
bool accurate;
|
||||
|
||||
if (self->player != nullptr)
|
||||
{
|
||||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != nullptr && ACTION_CALL_FROM_PSPRITE())
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
|
||||
return 0;
|
||||
|
||||
P_SetPsprite(self->player, PSP_FLASH, weapon->FindState(NAME_Flash), true);
|
||||
}
|
||||
self->player->mo->PlayAttacking2 ();
|
||||
|
||||
accurate = !self->player->refire;
|
||||
}
|
||||
else
|
||||
{
|
||||
accurate = true;
|
||||
}
|
||||
|
||||
S_Sound (self, CHAN_WEAPON, "weapons/pistol", 1, ATTN_NORM);
|
||||
|
||||
P_GunShot (self, accurate, PClass::FindActor(NAME_BulletPuff), P_BulletSlope (self));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// A_Saw
|
||||
//
|
||||
enum SAW_Flags
|
||||
{
|
||||
SF_NORANDOM = 1,
|
||||
SF_RANDOMLIGHTMISS = 2,
|
||||
SF_RANDOMLIGHTHIT = 4,
|
||||
SF_NOUSEAMMOMISS = 8,
|
||||
SF_NOUSEAMMO = 16,
|
||||
SF_NOPULLIN = 32,
|
||||
SF_NOTURN = 64,
|
||||
SF_STEALARMOR = 128,
|
||||
};
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_SOUND_OPT (fullsound) { fullsound = "weapons/sawfull"; }
|
||||
PARAM_SOUND_OPT (hitsound) { hitsound = "weapons/sawhit"; }
|
||||
PARAM_INT_OPT (damage) { damage = 2; }
|
||||
PARAM_CLASS_OPT (pufftype, AActor) { pufftype = NULL; }
|
||||
PARAM_INT_OPT (flags) { flags = 0; }
|
||||
PARAM_FLOAT_OPT (range) { range = 0; }
|
||||
PARAM_ANGLE_OPT (spread_xy) { spread_xy = 2.8125; }
|
||||
PARAM_ANGLE_OPT (spread_z) { spread_z = 0.; }
|
||||
PARAM_FLOAT_OPT (lifesteal) { lifesteal = 0; }
|
||||
PARAM_INT_OPT (lifestealmax) { lifestealmax = 0; }
|
||||
PARAM_CLASS_OPT (armorbonustype, ABasicArmorBonus) { armorbonustype = NULL; }
|
||||
|
||||
DAngle angle;
|
||||
DAngle slope;
|
||||
player_t *player;
|
||||
FTranslatedLineTarget t;
|
||||
int actualdamage;
|
||||
|
||||
if (NULL == (player = self->player))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pufftype == NULL)
|
||||
{
|
||||
pufftype = PClass::FindActor(NAME_BulletPuff);
|
||||
}
|
||||
if (damage == 0)
|
||||
{
|
||||
damage = 2;
|
||||
}
|
||||
if (!(flags & SF_NORANDOM))
|
||||
{
|
||||
damage *= (pr_saw()%10+1);
|
||||
}
|
||||
if (range == 0)
|
||||
{
|
||||
range = SAWRANGE;
|
||||
}
|
||||
|
||||
angle = self->Angles.Yaw + spread_xy * (pr_saw.Random2() / 255.);
|
||||
slope = P_AimLineAttack (self, angle, range, &t) + spread_z * (pr_saw.Random2() / 255.);
|
||||
|
||||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if ((weapon != NULL) && !(flags & SF_NOUSEAMMO) && !(!t.linetarget && (flags & SF_NOUSEAMMOMISS)) && !(weapon->WeaponFlags & WIF_DEHAMMO) && ACTION_CALL_FROM_PSPRITE())
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
||||
return 0;
|
||||
}
|
||||
|
||||
P_LineAttack (self, angle, range, slope, damage, NAME_Melee, pufftype, false, &t, &actualdamage);
|
||||
|
||||
if (!t.linetarget)
|
||||
{
|
||||
if ((flags & SF_RANDOMLIGHTMISS) && (pr_saw() > 64))
|
||||
{
|
||||
player->extralight = !player->extralight;
|
||||
}
|
||||
S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (flags & SF_RANDOMLIGHTHIT)
|
||||
{
|
||||
int randVal = pr_saw();
|
||||
if (randVal < 64)
|
||||
{
|
||||
player->extralight = 0;
|
||||
}
|
||||
else if (randVal < 160)
|
||||
{
|
||||
player->extralight = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
player->extralight = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (lifesteal && !(t.linetarget->flags5 & MF5_DONTDRAIN))
|
||||
{
|
||||
if (flags & SF_STEALARMOR)
|
||||
{
|
||||
if (armorbonustype == NULL)
|
||||
{
|
||||
armorbonustype = dyn_cast<ABasicArmorBonus::MetaClass>(PClass::FindClass("ArmorBonus"));
|
||||
}
|
||||
if (armorbonustype != NULL)
|
||||
{
|
||||
assert(armorbonustype->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus)));
|
||||
ABasicArmorBonus *armorbonus = static_cast<ABasicArmorBonus *>(Spawn(armorbonustype));
|
||||
armorbonus->SaveAmount = int(armorbonus->SaveAmount * actualdamage * lifesteal);
|
||||
armorbonus->MaxSaveAmount = lifestealmax <= 0 ? armorbonus->MaxSaveAmount : lifestealmax;
|
||||
armorbonus->flags |= MF_DROPPED;
|
||||
armorbonus->ClearCounters();
|
||||
|
||||
if (!armorbonus->CallTryPickup (self))
|
||||
{
|
||||
armorbonus->Destroy ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
P_GiveBody (self, int(actualdamage * lifesteal), lifestealmax);
|
||||
}
|
||||
}
|
||||
|
||||
S_Sound (self, CHAN_WEAPON, hitsound, 1, ATTN_NORM);
|
||||
|
||||
// turn to face target
|
||||
if (!(flags & SF_NOTURN))
|
||||
{
|
||||
DAngle anglediff = deltaangle(self->Angles.Yaw, t.angleFromSource);
|
||||
|
||||
if (anglediff < 0.0)
|
||||
{
|
||||
if (anglediff < -4.5)
|
||||
self->Angles.Yaw = angle + 90.0 / 21;
|
||||
else
|
||||
self->Angles.Yaw -= 4.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (anglediff > 4.5)
|
||||
self->Angles.Yaw = angle - 90.0 / 21;
|
||||
else
|
||||
self->Angles.Yaw += 4.5;
|
||||
}
|
||||
}
|
||||
if (!(flags & SF_NOPULLIN))
|
||||
self->flags |= MF_JUSTATTACKED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// A_FireShotgun
|
||||
//
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
int i;
|
||||
player_t *player;
|
||||
|
||||
if (nullptr == (player = self->player))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
S_Sound (self, CHAN_WEAPON, "weapons/shotgf", 1, ATTN_NORM);
|
||||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != nullptr && ACTION_CALL_FROM_PSPRITE())
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
|
||||
return 0;
|
||||
P_SetPsprite(player, PSP_FLASH, weapon->FindState(NAME_Flash), true);
|
||||
}
|
||||
player->mo->PlayAttacking2 ();
|
||||
|
||||
DAngle pitch = P_BulletSlope (self);
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
P_GunShot (self, false, PClass::FindActor(NAME_BulletPuff), pitch);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// A_FireShotgun2
|
||||
//
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun2)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
int i;
|
||||
DAngle angle;
|
||||
int damage;
|
||||
player_t *player;
|
||||
|
||||
if (nullptr == (player = self->player))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
S_Sound (self, CHAN_WEAPON, "weapons/sshotf", 1, ATTN_NORM);
|
||||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != nullptr && ACTION_CALL_FROM_PSPRITE())
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 2))
|
||||
return 0;
|
||||
P_SetPsprite(player, PSP_FLASH, weapon->FindState(NAME_Flash), true);
|
||||
}
|
||||
player->mo->PlayAttacking2 ();
|
||||
|
||||
|
||||
DAngle pitch = P_BulletSlope (self);
|
||||
|
||||
for (i=0 ; i<20 ; i++)
|
||||
{
|
||||
damage = 5*(pr_fireshotgun2()%3+1);
|
||||
angle = self->Angles.Yaw + pr_fireshotgun2.Random2() * (11.25 / 256);
|
||||
|
||||
// Doom adjusts the bullet slope by shifting a random number [-255,255]
|
||||
// left 5 places. At 2048 units away, this means the vertical position
|
||||
// of the shot can deviate as much as 255 units from nominal. So using
|
||||
// some simple trigonometry, that means the vertical angle of the shot
|
||||
// can deviate by as many as ~7.097 degrees or ~84676099 BAMs.
|
||||
|
||||
P_LineAttack (self,
|
||||
angle,
|
||||
PLAYERMISSILERANGE,
|
||||
pitch + pr_fireshotgun2.Random2() * (7.097 / 256), damage,
|
||||
NAME_Hitscan, NAME_BulletPuff);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_OpenShotgun2)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
S_Sound (self, CHAN_WEAPON, "weapons/sshoto", 1, ATTN_NORM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_LoadShotgun2)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
S_Sound (self, CHAN_WEAPON, "weapons/sshotl", 1, ATTN_NORM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_CloseShotgun2)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
S_Sound (self, CHAN_WEAPON, "weapons/sshotc", 1, ATTN_NORM);
|
||||
A_ReFire (self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
//
|
||||
// Setting a random flash like some of Doom's weapons can easily crash when the
|
||||
// definition is overridden incorrectly so let's check that the state actually exists.
|
||||
// Be aware though that this will not catch all DEHACKED related problems. But it will
|
||||
// find all DECORATE related ones.
|
||||
//
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int index)
|
||||
{
|
||||
|
||||
PClassActor *cls = weapon->GetClass();
|
||||
while (cls != RUNTIME_CLASS(AWeapon))
|
||||
{
|
||||
if (flashstate >= cls->OwnedStates && flashstate < cls->OwnedStates + cls->NumOwnedStates)
|
||||
{
|
||||
// The flash state belongs to this class.
|
||||
// Now let's check if the actually wanted state does also
|
||||
if (flashstate + index < cls->OwnedStates + cls->NumOwnedStates)
|
||||
{
|
||||
// we're ok so set the state
|
||||
P_SetPsprite(player, PSP_FLASH, flashstate + index, true);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// oh, no! The state is beyond the end of the state table so use the original flash state.
|
||||
P_SetPsprite(player, PSP_FLASH, flashstate, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// try again with parent class
|
||||
cls = static_cast<PClassActor *>(cls->ParentClass);
|
||||
}
|
||||
// if we get here the state doesn't seem to belong to any class in the inheritance chain
|
||||
// This can happen with Dehacked if the flash states are remapped.
|
||||
// The only way to check this would be to go through all Dehacked modifiable actors, convert
|
||||
// their states into a single flat array and find the correct one.
|
||||
// Rather than that, just check to make sure it belongs to something.
|
||||
if (FState::StaticFindStateOwner(flashstate + index) == NULL)
|
||||
{ // Invalid state. With no index offset, it should at least be valid.
|
||||
index = 0;
|
||||
}
|
||||
P_SetPsprite(player, PSP_FLASH, flashstate + index, true);
|
||||
}
|
||||
|
||||
//
|
||||
// A_FireCGun
|
||||
//
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FireCGun)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
player_t *player;
|
||||
|
||||
if (self == nullptr || nullptr == (player = self->player))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
AWeapon *weapon = player->ReadyWeapon;
|
||||
if (weapon != nullptr && ACTION_CALL_FROM_PSPRITE())
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
|
||||
return 0;
|
||||
|
||||
S_Sound (self, CHAN_WEAPON, "weapons/chngun", 1, ATTN_NORM);
|
||||
|
||||
FState *flash = weapon->FindState(NAME_Flash);
|
||||
if (flash != nullptr)
|
||||
{
|
||||
// [RH] Fix for Sparky's messed-up Dehacked patch! Blargh!
|
||||
FState * atk = weapon->FindState(NAME_Fire);
|
||||
|
||||
int theflash = clamp (int(player->GetPSprite(PSP_WEAPON)->GetState() - atk), 0, 1);
|
||||
|
||||
if (flash[theflash].sprite != flash->sprite)
|
||||
{
|
||||
theflash = 0;
|
||||
}
|
||||
|
||||
P_SetSafeFlash (weapon, player, flash, theflash);
|
||||
}
|
||||
|
||||
}
|
||||
player->mo->PlayAttacking2 ();
|
||||
|
||||
P_GunShot (self, !player->refire, PClass::FindActor(NAME_BulletPuff), P_BulletSlope (self));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// A_FireMissile
|
||||
//
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FireMissile)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
player_t *player;
|
||||
|
||||
if (NULL == (player = self->player))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != NULL && ACTION_CALL_FROM_PSPRITE())
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
|
||||
return 0;
|
||||
}
|
||||
P_SpawnPlayerMissile (self, PClass::FindActor("Rocket"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// A_FireSTGrenade: not exactly backported from ST, but should work the same
|
||||
//
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireSTGrenade)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_CLASS_OPT(grenade, AActor) { grenade = PClass::FindActor("Grenade"); }
|
||||
|
||||
player_t *player;
|
||||
|
||||
if (grenade == NULL)
|
||||
return 0;
|
||||
|
||||
if (NULL == (player = self->player))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != NULL && ACTION_CALL_FROM_PSPRITE())
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Temporarily raise the pitch to send the grenade slightly upwards
|
||||
DAngle SavedPlayerPitch = self->Angles.Pitch;
|
||||
self->Angles.Pitch -= 6.328125; //(1152 << F RACBITS);
|
||||
P_SpawnPlayerMissile(self, grenade);
|
||||
self->Angles.Pitch = SavedPlayerPitch;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// A_FirePlasma
|
||||
//
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FirePlasma)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
player_t *player;
|
||||
|
||||
if (NULL == (player = self->player))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != NULL && ACTION_CALL_FROM_PSPRITE())
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
|
||||
return 0;
|
||||
|
||||
FState *flash = weapon->FindState(NAME_Flash);
|
||||
if (flash != NULL)
|
||||
{
|
||||
P_SetSafeFlash(weapon, player, flash, (pr_fireplasma()&1));
|
||||
}
|
||||
}
|
||||
|
||||
P_SpawnPlayerMissile (self, PClass::FindActor("PlasmaBall"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// [RH] A_FireRailgun
|
||||
//
|
||||
static void FireRailgun(AActor *self, int offset_xy, bool fromweapon)
|
||||
{
|
||||
int damage;
|
||||
player_t *player;
|
||||
|
||||
if (NULL == (player = self->player))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != NULL && fromweapon)
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
|
||||
return;
|
||||
|
||||
FState *flash = weapon->FindState(NAME_Flash);
|
||||
if (flash != NULL)
|
||||
{
|
||||
P_SetSafeFlash(weapon, player, flash, (pr_firerail()&1));
|
||||
}
|
||||
}
|
||||
|
||||
damage = deathmatch ? 100 : 150;
|
||||
|
||||
FRailParams p;
|
||||
p.source = self;
|
||||
p.damage = damage;
|
||||
p.offset_xy = offset_xy;
|
||||
P_RailAttack (&p);
|
||||
}
|
||||
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FireRailgun)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
FireRailgun(self, 0, ACTION_CALL_FROM_PSPRITE());
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FireRailgunRight)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
FireRailgun(self, 10, ACTION_CALL_FROM_PSPRITE());
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FireRailgunLeft)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
FireRailgun(self, -10, ACTION_CALL_FROM_PSPRITE());
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_RailWait)
|
||||
{
|
||||
// Okay, this was stupid. Just use a NULL function instead of this.
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// A_FireBFG
|
||||
//
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FireBFG)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
player_t *player;
|
||||
|
||||
if (NULL == (player = self->player))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != NULL && ACTION_CALL_FROM_PSPRITE())
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, deh.BFGCells))
|
||||
return 0;
|
||||
}
|
||||
|
||||
P_SpawnPlayerMissile (self, 0, 0, 0, PClass::FindActor("BFGBall"), self->Angles.Yaw, NULL, NULL, !!(dmflags2 & DF2_NO_FREEAIMBFG));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_BFGSpray
|
||||
// Spawn a BFG explosion on every monster in view
|
||||
//
|
||||
enum BFG_Flags
|
||||
{
|
||||
BFGF_HURTSOURCE = 1,
|
||||
BFGF_MISSILEORIGIN = 2,
|
||||
};
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_CLASS_OPT (spraytype, AActor) { spraytype = NULL; }
|
||||
PARAM_INT_OPT (numrays) { numrays = 0; }
|
||||
PARAM_INT_OPT (damagecnt) { damagecnt = 0; }
|
||||
PARAM_ANGLE_OPT (angle) { angle = 0.; }
|
||||
PARAM_FLOAT_OPT (distance) { distance = 0; }
|
||||
PARAM_ANGLE_OPT (vrange) { vrange = 0.; }
|
||||
PARAM_INT_OPT (defdamage) { defdamage = 0; }
|
||||
PARAM_INT_OPT (flags) { flags = 0; }
|
||||
|
||||
int i;
|
||||
int j;
|
||||
int damage;
|
||||
DAngle an;
|
||||
FTranslatedLineTarget t;
|
||||
AActor *originator;
|
||||
|
||||
if (spraytype == NULL) spraytype = PClass::FindActor("BFGExtra");
|
||||
if (numrays <= 0) numrays = 40;
|
||||
if (damagecnt <= 0) damagecnt = 15;
|
||||
if (angle == 0) angle = 90.;
|
||||
if (distance <= 0) distance = 16 * 64;
|
||||
if (vrange == 0) vrange = 32.;
|
||||
|
||||
// [RH] Don't crash if no target
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
// [XA] Set the originator of the rays to the projectile (self) if
|
||||
// the new flag is set, else set it to the player (self->target)
|
||||
originator = (flags & BFGF_MISSILEORIGIN) ? self : (AActor *)(self->target);
|
||||
|
||||
// offset angles from its attack angle
|
||||
for (i = 0; i < numrays; i++)
|
||||
{
|
||||
an = self->Angles.Yaw - angle / 2 + angle / numrays*i;
|
||||
|
||||
P_AimLineAttack(originator, an, distance, &t, vrange);
|
||||
|
||||
if (t.linetarget != NULL)
|
||||
{
|
||||
AActor *spray = Spawn(spraytype, t.linetarget->PosPlusZ(t.linetarget->Height / 4), ALLOW_REPLACE);
|
||||
|
||||
int dmgFlags = 0;
|
||||
FName dmgType = NAME_BFGSplash;
|
||||
|
||||
if (spray != NULL)
|
||||
{
|
||||
if ((spray->flags6 & MF6_MTHRUSPECIES && self->target->GetSpecies() == t.linetarget->GetSpecies()) ||
|
||||
(!(flags & BFGF_HURTSOURCE) && self->target == t.linetarget)) // [XA] Don't hit oneself unless we say so.
|
||||
{
|
||||
spray->Destroy(); // [MC] Remove it because technically, the spray isn't trying to "hit" them.
|
||||
continue;
|
||||
}
|
||||
if (spray->flags5 & MF5_PUFFGETSOWNER) spray->target = self->target;
|
||||
if (spray->flags3 & MF3_FOILINVUL) dmgFlags |= DMG_FOILINVUL;
|
||||
if (spray->flags7 & MF7_FOILBUDDHA) dmgFlags |= DMG_FOILBUDDHA;
|
||||
dmgType = spray->DamageType;
|
||||
}
|
||||
|
||||
if (defdamage == 0)
|
||||
{
|
||||
damage = 0;
|
||||
for (j = 0; j < damagecnt; ++j)
|
||||
damage += (pr_bfgspray() & 7) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if this is used, damagecnt will be ignored
|
||||
damage = defdamage;
|
||||
}
|
||||
|
||||
int newdam = P_DamageMobj(t.linetarget, originator, self->target, damage, dmgType, dmgFlags|DMG_USEANGLE, t.angleFromSource.Degrees);
|
||||
P_TraceBleed(newdam > 0 ? newdam : damage, &t, self);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// A_BFGsound
|
||||
//
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BFGsound)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
S_Sound (self, CHAN_WEAPON, "weapons/bfgf", 1, ATTN_NORM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// A_FireOldBFG
|
||||
//
|
||||
// This function emulates Doom's Pre-Beta BFG
|
||||
// By Lee Killough 6/6/98, 7/11/98, 7/19/98, 8/20/98
|
||||
//
|
||||
// This code may not be used in other mods without appropriate credit given.
|
||||
// Code leeches will be telefragged.
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FireOldBFG)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PClassActor *plasma[] = { PClass::FindActor("PlasmaBall1"), PClass::FindActor("PlasmaBall2") };
|
||||
AActor * mo = NULL;
|
||||
|
||||
player_t *player;
|
||||
bool doesautoaim = false;
|
||||
|
||||
if (NULL == (player = self->player))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (!ACTION_CALL_FROM_PSPRITE()) weapon = NULL;
|
||||
if (weapon != NULL)
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
|
||||
return 0;
|
||||
|
||||
doesautoaim = !(weapon->WeaponFlags & WIF_NOAUTOAIM);
|
||||
weapon->WeaponFlags |= WIF_NOAUTOAIM; // No autoaiming that gun
|
||||
}
|
||||
self->player->extralight = 2;
|
||||
|
||||
// Save values temporarily
|
||||
DAngle SavedPlayerAngle = self->Angles.Yaw;
|
||||
DAngle SavedPlayerPitch = self->Angles.Pitch;
|
||||
for (int i = 0; i < 2; i++) // Spawn two plasma balls in sequence
|
||||
{
|
||||
self->Angles.Yaw += ((pr_oldbfg()&127) - 64) * (90./768);
|
||||
self->Angles.Pitch += ((pr_oldbfg()&127) - 64) * (90./640);
|
||||
mo = P_SpawnPlayerMissile (self, plasma[i]);
|
||||
// Restore saved values
|
||||
self->Angles.Yaw = SavedPlayerAngle;
|
||||
self->Angles.Pitch = SavedPlayerPitch;
|
||||
}
|
||||
if (doesautoaim && weapon != NULL)
|
||||
{ // Restore autoaim setting
|
||||
weapon->WeaponFlags &= ~WIF_NOAUTOAIM;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,177 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_local.h"
|
||||
#include "p_enemy.h"
|
||||
#include "gstrings.h"
|
||||
#include "a_action.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
//
|
||||
// Mancubus attack,
|
||||
// firing three missiles in three different directions?
|
||||
// Doesn't look like it.
|
||||
//
|
||||
#define FATSPREAD (90./8)
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FatRaise)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
A_FaceTarget (self);
|
||||
S_Sound (self, CHAN_WEAPON, "fatso/raiseguns", 1, ATTN_NORM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack1)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; }
|
||||
|
||||
AActor *missile;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
if (spawntype == NULL) spawntype = PClass::FindActor("FatShot");
|
||||
|
||||
A_FaceTarget (self);
|
||||
// Change direction to ...
|
||||
self->Angles.Yaw += FATSPREAD;
|
||||
P_SpawnMissile (self, self->target, spawntype);
|
||||
|
||||
missile = P_SpawnMissile (self, self->target, spawntype);
|
||||
if (missile != NULL)
|
||||
{
|
||||
missile->Angles.Yaw += FATSPREAD;
|
||||
missile->VelFromAngle();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack2)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; }
|
||||
|
||||
AActor *missile;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
if (spawntype == NULL) spawntype = PClass::FindActor("FatShot");
|
||||
|
||||
A_FaceTarget (self);
|
||||
// Now here choose opposite deviation.
|
||||
self->Angles.Yaw -= FATSPREAD;
|
||||
P_SpawnMissile (self, self->target, spawntype);
|
||||
|
||||
missile = P_SpawnMissile (self, self->target, spawntype);
|
||||
if (missile != NULL)
|
||||
{
|
||||
missile->Angles.Yaw -= FATSPREAD*2;
|
||||
missile->VelFromAngle();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack3)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; }
|
||||
|
||||
AActor *missile;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
if (spawntype == NULL) spawntype = PClass::FindActor("FatShot");
|
||||
|
||||
A_FaceTarget (self);
|
||||
|
||||
missile = P_SpawnMissile (self, self->target, spawntype);
|
||||
if (missile != NULL)
|
||||
{
|
||||
missile->Angles.Yaw -= FATSPREAD/2;
|
||||
missile->VelFromAngle();
|
||||
}
|
||||
|
||||
missile = P_SpawnMissile (self, self->target, spawntype);
|
||||
if (missile != NULL)
|
||||
{
|
||||
missile->Angles.Yaw += FATSPREAD/2;
|
||||
missile->VelFromAngle();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// killough 9/98: a mushroom explosion effect, sorta :)
|
||||
// Original idea: Linguica
|
||||
//
|
||||
|
||||
enum
|
||||
{
|
||||
MSF_Standard = 0,
|
||||
MSF_Classic = 1,
|
||||
MSF_DontHurt = 2,
|
||||
};
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_CLASS_OPT (spawntype, AActor) { spawntype = NULL; }
|
||||
PARAM_INT_OPT (n) { n = 0; }
|
||||
PARAM_INT_OPT (flags) { flags = 0; }
|
||||
PARAM_FLOAT_OPT (vrange) { vrange = 4; }
|
||||
PARAM_FLOAT_OPT (hrange) { hrange = 0.5; }
|
||||
|
||||
int i, j;
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
n = self->GetMissileDamage(0, 1);
|
||||
}
|
||||
if (spawntype == NULL)
|
||||
{
|
||||
spawntype = PClass::FindActor("FatShot");
|
||||
}
|
||||
|
||||
P_RadiusAttack (self, self->target, 128, 128, self->DamageType, (flags & MSF_DontHurt) ? 0 : RADF_HURTSOURCE);
|
||||
P_CheckSplash(self, 128.);
|
||||
|
||||
// Now launch mushroom cloud
|
||||
AActor *target = Spawn("Mapspot", self->Pos(), NO_REPLACE); // We need something to aim at.
|
||||
AActor *master = (flags & MSF_DontHurt) ? (AActor*)(self->target) : self;
|
||||
target->Height = self->Height;
|
||||
for (i = -n; i <= n; i += 8)
|
||||
{
|
||||
for (j = -n; j <= n; j += 8)
|
||||
{
|
||||
AActor *mo;
|
||||
target->SetXYZ(
|
||||
self->X() + i, // Aim in many directions from source
|
||||
self->Y() + j,
|
||||
self->Z() + (P_AproxDistance(i,j) * vrange)); // Aim up fairly high
|
||||
if ((flags & MSF_Classic) || // Flag explicitely set, or no flags and compat options
|
||||
(flags == 0 && (self->state->DefineFlags & SDF_DEHACKED) && (i_compatflags & COMPATF_MUSHROOM)))
|
||||
{ // Use old function for MBF compatibility
|
||||
mo = P_OldSpawnMissile (self, master, target, spawntype);
|
||||
}
|
||||
else // Use normal function
|
||||
{
|
||||
mo = P_SpawnMissile(self, target, spawntype, master);
|
||||
}
|
||||
if (mo != NULL)
|
||||
{ // Slow it down a bit
|
||||
mo->Vel *= hrange;
|
||||
mo->flags &= ~MF_NOGRAVITY; // Make debris fall under gravity
|
||||
}
|
||||
}
|
||||
}
|
||||
target->Destroy();
|
||||
return 0;
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "p_local.h"
|
||||
#include "p_spec.h"
|
||||
#include "p_enemy.h"
|
||||
#include "a_action.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
//
|
||||
// A_KeenDie
|
||||
// DOOM II special, map 32.
|
||||
// Uses special tag 666 by default.
|
||||
//
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KeenDie)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_INT_OPT(doortag) { doortag = 666; }
|
||||
|
||||
A_Unblock(self, false);
|
||||
|
||||
// scan the remaining thinkers to see if all Keens are dead
|
||||
AActor *other;
|
||||
TThinkerIterator<AActor> iterator;
|
||||
const PClass *matchClass = self->GetClass ();
|
||||
|
||||
while ( (other = iterator.Next ()) )
|
||||
{
|
||||
if (other != self && other->health > 0 && other->IsA (matchClass))
|
||||
{
|
||||
// other Keen not dead
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
EV_DoDoor (DDoor::doorOpen, NULL, NULL, doortag, 2., 0, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
#include "templates.h"
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_local.h"
|
||||
#include "p_enemy.h"
|
||||
#include "gi.h"
|
||||
#include "gstrings.h"
|
||||
#include "a_action.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
FRandom pr_oldsoul ("BetaLostSoul");
|
||||
|
||||
//
|
||||
// SkullAttack
|
||||
// Fly at the player like a missile.
|
||||
//
|
||||
|
||||
void A_SkullAttack(AActor *self, double speed)
|
||||
{
|
||||
AActor *dest;
|
||||
if (!self->target)
|
||||
return;
|
||||
|
||||
dest = self->target;
|
||||
self->flags |= MF_SKULLFLY;
|
||||
|
||||
S_Sound (self, CHAN_VOICE, self->AttackSound, 1, ATTN_NORM);
|
||||
A_FaceTarget (self);
|
||||
self->VelFromAngle(speed);
|
||||
self->Vel.Z = (dest->Center() - self->Z()) / self->DistanceBySpeed(dest, speed);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_FLOAT_OPT(speed) { speed = SKULLSPEED; }
|
||||
|
||||
if (speed <= 0)
|
||||
speed = SKULLSPEED;
|
||||
A_SkullAttack(self, speed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BetaSkullAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
int damage;
|
||||
if (!self || !self->target || self->target->GetSpecies() == self->GetSpecies())
|
||||
return 0;
|
||||
S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM);
|
||||
A_FaceTarget(self);
|
||||
damage = (pr_oldsoul()%8+1)*self->GetMissileDamage(0,1);
|
||||
P_DamageMobj(self->target, self, self, damage, NAME_None);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CVAR transsouls
|
||||
//
|
||||
// How translucent things drawn with STYLE_SoulTrans are. Normally, only
|
||||
// Lost Souls have this render style, but a dehacked patch could give other
|
||||
// things this style. Values less than 0.25 will automatically be set to
|
||||
// 0.25 to ensure some degree of visibility. Likewise, values above 1.0 will
|
||||
// be set to 1.0, because anything higher doesn't make sense.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
CUSTOM_CVAR (Float, transsouls, 0.75f, CVAR_ARCHIVE)
|
||||
{
|
||||
if (self < 0.25f)
|
||||
{
|
||||
self = 0.25f;
|
||||
}
|
||||
else if (self > 1.f)
|
||||
{
|
||||
self = 1.f;
|
||||
}
|
||||
}
|
|
@ -1,194 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "p_enemy.h"
|
||||
#include "p_local.h"
|
||||
#include "a_action.h"
|
||||
#include "templates.h"
|
||||
#include "m_bbox.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
#include "doomstat.h"
|
||||
*/
|
||||
|
||||
enum PA_Flags
|
||||
{
|
||||
PAF_NOSKULLATTACK = 1,
|
||||
PAF_AIMFACING = 2,
|
||||
PAF_NOTARGET = 4,
|
||||
};
|
||||
|
||||
//
|
||||
// A_PainShootSkull
|
||||
// Spawn a lost soul and launch it at the target
|
||||
//
|
||||
void A_PainShootSkull (AActor *self, DAngle Angle, PClassActor *spawntype, int flags = 0, int limit = -1)
|
||||
{
|
||||
AActor *other;
|
||||
double prestep;
|
||||
|
||||
if (spawntype == NULL) spawntype = PClass::FindActor("LostSoul");
|
||||
assert(spawntype != NULL);
|
||||
if (self->DamageType == NAME_Massacre) return;
|
||||
|
||||
// [RH] check to make sure it's not too close to the ceiling
|
||||
if (self->Top() + 8 > self->ceilingz)
|
||||
{
|
||||
if (self->flags & MF_FLOAT)
|
||||
{
|
||||
self->Vel.Z -= 2;
|
||||
self->flags |= MF_INFLOAT;
|
||||
self->flags4 |= MF4_VFRICTION;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// [RH] make this optional
|
||||
if (limit == -1 && (i_compatflags & COMPATF_LIMITPAIN))
|
||||
limit = 21;
|
||||
|
||||
if (limit)
|
||||
{
|
||||
// count total number of skulls currently on the level
|
||||
// if there are already 21 skulls on the level, don't spit another one
|
||||
int count = limit;
|
||||
FThinkerIterator iterator (spawntype);
|
||||
DThinker *othink;
|
||||
|
||||
while ( (othink = iterator.Next ()) )
|
||||
{
|
||||
if (--count == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// okay, there's room for another one
|
||||
prestep = 4 + (self->radius + GetDefaultByType(spawntype)->radius) * 1.5;
|
||||
|
||||
// NOTE: The following code contains some advance work for line-to-line portals which is currenty inactive.
|
||||
|
||||
DVector2 dist = Angle.ToVector(prestep);
|
||||
DVector3 pos = self->Vec3Offset(dist.X, dist.Y, 8., true);
|
||||
DVector3 src = self->Pos();
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
// Check whether the Lost Soul is being fired through a 1-sided // phares
|
||||
// wall or an impassible line, or a "monsters can't cross" line.// |
|
||||
// If it is, then we don't allow the spawn. // V
|
||||
|
||||
FBoundingBox box(MIN(src.X, pos.X), MIN(src.Y, pos.Y), MAX(src.X, pos.X), MAX(src.Y, pos.Y));
|
||||
FBlockLinesIterator it(box);
|
||||
line_t *ld;
|
||||
bool inportal = false;
|
||||
|
||||
while ((ld = it.Next()))
|
||||
{
|
||||
if (ld->isLinePortal() && i == 0)
|
||||
{
|
||||
if (P_PointOnLineSidePrecise(src, ld) == 0 &&
|
||||
P_PointOnLineSidePrecise(pos, ld) == 1)
|
||||
{
|
||||
// crossed a portal line from front to back, we need to repeat the check on the other side as well.
|
||||
inportal = true;
|
||||
}
|
||||
}
|
||||
else if (!(ld->flags & ML_TWOSIDED) ||
|
||||
(ld->flags & (ML_BLOCKING | ML_BLOCKMONSTERS | ML_BLOCKEVERYTHING)))
|
||||
{
|
||||
if (box.inRange(ld))
|
||||
{
|
||||
if (P_PointOnLineSidePrecise(src, ld) != P_PointOnLineSidePrecise(pos, ld))
|
||||
return; // line blocks trajectory // ^
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!inportal) break;
|
||||
|
||||
// recalculate position and redo the check on the other side of the portal
|
||||
pos = self->Vec3Offset(dist.X, dist.Y, 8.);
|
||||
src.X = pos.X - dist.X;
|
||||
src.Y = pos.Y - dist.Y;
|
||||
|
||||
}
|
||||
|
||||
other = Spawn (spawntype, pos, ALLOW_REPLACE);
|
||||
|
||||
// Check to see if the new Lost Soul's z value is above the
|
||||
// ceiling of its new sector, or below the floor. If so, kill it.
|
||||
|
||||
if (other->Top() > other->Sector->HighestCeilingAt(other) ||
|
||||
other->Z() < other->Sector->LowestFloorAt(other))
|
||||
{
|
||||
// kill it immediately
|
||||
P_DamageMobj (other, self, self, TELEFRAG_DAMAGE, NAME_None);// ^
|
||||
return; // |
|
||||
} // phares
|
||||
|
||||
// Check for movements.
|
||||
|
||||
if (!P_CheckPosition (other, other->Pos()))
|
||||
{
|
||||
// kill it immediately
|
||||
P_DamageMobj (other, self, self, TELEFRAG_DAMAGE, NAME_None);
|
||||
return;
|
||||
}
|
||||
|
||||
// [RH] Lost souls hate the same things as their pain elementals
|
||||
other->CopyFriendliness (self, !(flags & PAF_NOTARGET));
|
||||
|
||||
if (!(flags & PAF_NOSKULLATTACK))
|
||||
A_SkullAttack(other, SKULLSPEED);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_PainAttack
|
||||
// Spawn a lost soul and launch it at the target
|
||||
//
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
PARAM_CLASS_OPT (spawntype, AActor) { spawntype = NULL; }
|
||||
PARAM_ANGLE_OPT (angle) { angle = 0.; }
|
||||
PARAM_INT_OPT (flags) { flags = 0; }
|
||||
PARAM_INT_OPT (limit) { limit = -1; }
|
||||
|
||||
if (!(flags & PAF_AIMFACING))
|
||||
A_FaceTarget (self);
|
||||
A_PainShootSkull (self, self->Angles.Yaw + angle, spawntype, flags, limit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DualPainAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; }
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
A_FaceTarget (self);
|
||||
A_PainShootSkull (self, self->Angles.Yaw + 45., spawntype);
|
||||
A_PainShootSkull (self, self->Angles.Yaw - 45., spawntype);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainDie)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; }
|
||||
|
||||
if (self->target != NULL && self->IsFriend(self->target))
|
||||
{ // And I thought you were my friend!
|
||||
self->flags &= ~MF_FRIENDLY;
|
||||
}
|
||||
A_Unblock(self, true);
|
||||
A_PainShootSkull (self, self->Angles.Yaw + 90, spawntype);
|
||||
A_PainShootSkull (self, self->Angles.Yaw + 180, spawntype);
|
||||
A_PainShootSkull (self, self->Angles.Yaw + 270, spawntype);
|
||||
return 0;
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_local.h"
|
||||
#include "p_enemy.h"
|
||||
#include "gstrings.h"
|
||||
#include "a_action.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_posattack ("PosAttack");
|
||||
static FRandom pr_sposattack ("SPosAttack");
|
||||
static FRandom pr_cposattack ("CPosAttack");
|
||||
static FRandom pr_cposrefire ("CPosRefire");
|
||||
|
||||
//
|
||||
// A_PosAttack
|
||||
//
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_PosAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
int damage;
|
||||
DAngle angle;
|
||||
DAngle slope;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
A_FaceTarget (self);
|
||||
angle = self->Angles.Yaw;
|
||||
slope = P_AimLineAttack (self, angle, MISSILERANGE);
|
||||
|
||||
S_Sound (self, CHAN_WEAPON, "grunt/attack", 1, ATTN_NORM);
|
||||
angle += pr_posattack.Random2() * (22.5 / 256);
|
||||
damage = ((pr_posattack()%5)+1)*3;
|
||||
P_LineAttack (self, angle, MISSILERANGE, slope, damage, NAME_Hitscan, NAME_BulletPuff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void A_SPosAttack2 (AActor *self)
|
||||
{
|
||||
int i;
|
||||
DAngle bangle;
|
||||
DAngle slope;
|
||||
|
||||
A_FaceTarget (self);
|
||||
bangle = self->Angles.Yaw;
|
||||
slope = P_AimLineAttack (self, bangle, MISSILERANGE);
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
DAngle angle = bangle + pr_sposattack.Random2() * (22.5 / 256);
|
||||
int damage = ((pr_sposattack()%5)+1)*3;
|
||||
P_LineAttack(self, angle, MISSILERANGE, slope, damage, NAME_Hitscan, NAME_BulletPuff);
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SPosAttackUseAtkSound)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM);
|
||||
A_SPosAttack2 (self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This version of the function, which uses a hard-coded sound, is
|
||||
// meant for Dehacked only.
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SPosAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
S_Sound (self, CHAN_WEAPON, "shotguy/attack", 1, ATTN_NORM);
|
||||
A_SPosAttack2 (self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_CPosAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
DAngle angle;
|
||||
DAngle bangle;
|
||||
int damage;
|
||||
DAngle slope;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
// [RH] Andy Baker's stealth monsters
|
||||
if (self->flags & MF_STEALTH)
|
||||
{
|
||||
self->visdir = 1;
|
||||
}
|
||||
|
||||
S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM);
|
||||
A_FaceTarget (self);
|
||||
bangle = self->Angles.Yaw;
|
||||
slope = P_AimLineAttack (self, bangle, MISSILERANGE);
|
||||
|
||||
angle = bangle + pr_cposattack.Random2() * (22.5 / 256);
|
||||
damage = ((pr_cposattack()%5)+1)*3;
|
||||
P_LineAttack (self, angle, MISSILERANGE, slope, damage, NAME_Hitscan, NAME_BulletPuff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_CPosRefire)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
// keep firing unless target got out of sight
|
||||
A_FaceTarget (self);
|
||||
|
||||
if (pr_cposrefire() < 40)
|
||||
return 0;
|
||||
|
||||
if (!self->target
|
||||
|| P_HitFriend (self)
|
||||
|| self->target->health <= 0
|
||||
|| !P_CheckSight (self, self->target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES))
|
||||
{
|
||||
self->SetState (self->SeeState);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,152 +0,0 @@
|
|||
/*
|
||||
#include "templates.h"
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_local.h"
|
||||
#include "p_enemy.h"
|
||||
#include "gstrings.h"
|
||||
#include "a_action.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
#include "g_level.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_tracer ("Tracer");
|
||||
static FRandom pr_skelfist ("SkelFist");
|
||||
|
||||
//
|
||||
// A_SkelMissile
|
||||
//
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SkelMissile)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
AActor *missile;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
A_FaceTarget (self);
|
||||
self->AddZ(16.);
|
||||
missile = P_SpawnMissile(self, self->target, PClass::FindActor("RevenantTracer"));
|
||||
self->AddZ(-16.);
|
||||
|
||||
if (missile != NULL)
|
||||
{
|
||||
missile->SetOrigin(missile->Vec3Offset(missile->Vel.X, missile->Vel.Y, 0.), false);
|
||||
missile->tracer = self->target;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TRACEANGLE (16.875)
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Tracer)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
double dist;
|
||||
double slope;
|
||||
AActor *dest;
|
||||
AActor *smoke;
|
||||
|
||||
// killough 1/18/98: this is why some missiles do not have smoke
|
||||
// and some do. Also, internal demos start at random gametics, thus
|
||||
// the bug in which revenants cause internal demos to go out of sync.
|
||||
//
|
||||
// killough 3/6/98: fix revenant internal demo bug by subtracting
|
||||
// levelstarttic from gametic:
|
||||
//
|
||||
// [RH] level.time is always 0-based, so nothing special to do here.
|
||||
|
||||
if (level.time & 3)
|
||||
return 0;
|
||||
|
||||
// spawn a puff of smoke behind the rocket
|
||||
P_SpawnPuff (self, PClass::FindActor(NAME_BulletPuff), self->Pos(), self->Angles.Yaw, self->Angles.Yaw, 3);
|
||||
|
||||
smoke = Spawn ("RevenantTracerSmoke", self->Vec3Offset(-self->Vel.X, -self->Vel.Y, 0.), ALLOW_REPLACE);
|
||||
|
||||
smoke->Vel.Z = 1.;
|
||||
smoke->tics -= pr_tracer()&3;
|
||||
if (smoke->tics < 1)
|
||||
smoke->tics = 1;
|
||||
|
||||
// adjust direction
|
||||
dest = self->tracer;
|
||||
|
||||
if (!dest || dest->health <= 0 || self->Speed == 0 || !self->CanSeek(dest))
|
||||
return 0;
|
||||
|
||||
// change angle
|
||||
DAngle exact = self->AngleTo(dest);
|
||||
DAngle diff = deltaangle(self->Angles.Yaw, exact);
|
||||
|
||||
if (diff < 0)
|
||||
{
|
||||
self->Angles.Yaw -= TRACEANGLE;
|
||||
if (deltaangle(self->Angles.Yaw, exact) > 0)
|
||||
self->Angles.Yaw = exact;
|
||||
}
|
||||
else if (diff > 0)
|
||||
{
|
||||
self->Angles.Yaw += TRACEANGLE;
|
||||
if (deltaangle(self->Angles.Yaw, exact) < 0.)
|
||||
self->Angles.Yaw = exact;
|
||||
}
|
||||
|
||||
self->VelFromAngle();
|
||||
|
||||
if (!(self->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER)))
|
||||
{
|
||||
// change slope
|
||||
dist = self->DistanceBySpeed(dest, self->Speed);
|
||||
|
||||
if (dest->Height >= 56.)
|
||||
{
|
||||
slope = (dest->Z() + 40. - self->Z()) / dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
slope = (dest->Z() + self->Height*(2./3) - self->Z()) / dist;
|
||||
}
|
||||
|
||||
if (slope < self->Vel.Z)
|
||||
self->Vel.Z -= 1. / 8;
|
||||
else
|
||||
self->Vel.Z += 1. / 8;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SkelWhoosh)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
A_FaceTarget (self);
|
||||
S_Sound (self, CHAN_WEAPON, "skeleton/swing", 1, ATTN_NORM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SkelFist)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (!self->target)
|
||||
return 0;
|
||||
|
||||
A_FaceTarget (self);
|
||||
|
||||
if (self->CheckMeleeRange ())
|
||||
{
|
||||
int damage = ((pr_skelfist()%10)+1)*6;
|
||||
S_Sound (self, CHAN_WEAPON, "skeleton/melee", 1, ATTN_NORM);
|
||||
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,654 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "p_enemy.h"
|
||||
#include "a_action.h"
|
||||
#include "m_random.h"
|
||||
#include "p_local.h"
|
||||
#include "a_doomglobal.h"
|
||||
#include "s_sound.h"
|
||||
#include "r_data/r_translate.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
#include "g_level.h"
|
||||
*/
|
||||
|
||||
#define MARINE_PAIN_CHANCE 160
|
||||
|
||||
static FRandom pr_m_refire ("SMarineRefire");
|
||||
static FRandom pr_m_punch ("SMarinePunch");
|
||||
static FRandom pr_m_gunshot ("SMarineGunshot");
|
||||
static FRandom pr_m_saw ("SMarineSaw");
|
||||
static FRandom pr_m_fireshotgun2 ("SMarineFireSSG");
|
||||
|
||||
IMPLEMENT_CLASS (AScriptedMarine)
|
||||
|
||||
void AScriptedMarine::Serialize(FSerializer &arc)
|
||||
{
|
||||
Super::Serialize (arc);
|
||||
|
||||
auto def = (AScriptedMarine*)GetDefault();
|
||||
|
||||
arc.Sprite("spriteoverride", SpriteOverride, &def->SpriteOverride)
|
||||
("currentweapon", CurrentWeapon, def->CurrentWeapon);
|
||||
}
|
||||
|
||||
void AScriptedMarine::Activate (AActor *activator)
|
||||
{
|
||||
if (flags2 & MF2_DORMANT)
|
||||
{
|
||||
flags2 &= ~MF2_DORMANT;
|
||||
tics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void AScriptedMarine::Deactivate (AActor *activator)
|
||||
{
|
||||
if (!(flags2 & MF2_DORMANT))
|
||||
{
|
||||
flags2 |= MF2_DORMANT;
|
||||
tics = -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool AScriptedMarine::GetWeaponStates(int weap, FState *&melee, FState *&missile)
|
||||
{
|
||||
static ENamedName WeaponNames[] =
|
||||
{
|
||||
NAME_None,
|
||||
NAME_Fist,
|
||||
NAME_Berserk,
|
||||
NAME_Chainsaw,
|
||||
NAME_Pistol,
|
||||
NAME_Shotgun,
|
||||
NAME_SSG,
|
||||
NAME_Chaingun,
|
||||
NAME_Rocket,
|
||||
NAME_Plasma,
|
||||
NAME_Railgun,
|
||||
NAME_BFG
|
||||
};
|
||||
|
||||
if (weap < WEAPON_Dummy || weap > WEAPON_BFG) weap = WEAPON_Dummy;
|
||||
|
||||
melee = FindState(NAME_Melee, WeaponNames[weap], true);
|
||||
missile = FindState(NAME_Missile, WeaponNames[weap], true);
|
||||
|
||||
return melee != NULL || missile != NULL;
|
||||
}
|
||||
|
||||
void AScriptedMarine::BeginPlay ()
|
||||
{
|
||||
Super::BeginPlay ();
|
||||
|
||||
// Set the current weapon
|
||||
for(int i=WEAPON_Dummy; i<=WEAPON_BFG; i++)
|
||||
{
|
||||
FState *melee, *missile;
|
||||
if (GetWeaponStates(i, melee, missile))
|
||||
{
|
||||
if (melee == MeleeState && missile == MissileState)
|
||||
{
|
||||
CurrentWeapon = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AScriptedMarine::Tick ()
|
||||
{
|
||||
Super::Tick ();
|
||||
|
||||
// Override the standard sprite, if desired
|
||||
if (SpriteOverride != 0 && sprite == SpawnState->sprite)
|
||||
{
|
||||
sprite = SpriteOverride;
|
||||
}
|
||||
|
||||
if (special1 != 0)
|
||||
{
|
||||
if (CurrentWeapon == WEAPON_SuperShotgun)
|
||||
{ // Play SSG reload sounds
|
||||
int ticks = level.maptime - special1;
|
||||
if (ticks < 47)
|
||||
{
|
||||
switch (ticks)
|
||||
{
|
||||
case 14:
|
||||
S_Sound (this, CHAN_WEAPON, "weapons/sshoto", 1, ATTN_NORM);
|
||||
break;
|
||||
case 28:
|
||||
S_Sound (this, CHAN_WEAPON, "weapons/sshotl", 1, ATTN_NORM);
|
||||
break;
|
||||
case 41:
|
||||
S_Sound (this, CHAN_WEAPON, "weapons/sshotc", 1, ATTN_NORM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
special1 = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Wait for a long refire time
|
||||
if (level.maptime >= special1)
|
||||
{
|
||||
special1 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
flags |= MF_JUSTATTACKED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_M_Refire
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Refire)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_BOOL_OPT(ignoremissile) { ignoremissile = false; }
|
||||
|
||||
if (self->target == NULL || self->target->health <= 0)
|
||||
{
|
||||
if (self->MissileState && pr_m_refire() < 160)
|
||||
{ // Look for a new target most of the time
|
||||
if (P_LookForPlayers (self, true, NULL) && P_CheckMissileRange (self))
|
||||
{ // Found somebody new and in range, so don't stop shooting
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
self->SetState (self->state + 1);
|
||||
return 0;
|
||||
}
|
||||
if (((ignoremissile || self->MissileState == NULL) && !self->CheckMeleeRange ()) ||
|
||||
!P_CheckSight (self, self->target) ||
|
||||
pr_m_refire() < 4) // Small chance of stopping even when target not dead
|
||||
{
|
||||
self->SetState (self->state + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_M_SawRefire
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_M_SawRefire)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (self->target == NULL || self->target->health <= 0)
|
||||
{
|
||||
self->SetState (self->state + 1);
|
||||
return 0;
|
||||
}
|
||||
if (!self->CheckMeleeRange ())
|
||||
{
|
||||
self->SetState (self->state + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_MarineNoise
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_MarineNoise)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (static_cast<AScriptedMarine *>(self)->CurrentWeapon == AScriptedMarine::WEAPON_Chainsaw)
|
||||
{
|
||||
S_Sound (self, CHAN_WEAPON, "weapons/sawidle", 1, ATTN_NORM);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_MarineChase
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_MarineChase)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
CALL_ACTION(A_MarineNoise, self);
|
||||
A_Chase (stack, self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_MarineLook
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_MarineLook)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
CALL_ACTION(A_MarineNoise, self);
|
||||
CALL_ACTION(A_Look, self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_M_Saw
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Saw)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_SOUND_OPT (fullsound) { fullsound = "weapons/sawfull"; }
|
||||
PARAM_SOUND_OPT (hitsound) { hitsound = "weapons/sawhit"; }
|
||||
PARAM_INT_OPT (damage) { damage = 2; }
|
||||
PARAM_CLASS_OPT (pufftype, AActor) { pufftype = NULL; }
|
||||
|
||||
if (self->target == NULL)
|
||||
return 0;
|
||||
|
||||
if (pufftype == NULL)
|
||||
{
|
||||
pufftype = PClass::FindActor(NAME_BulletPuff);
|
||||
}
|
||||
if (damage == 0)
|
||||
{
|
||||
damage = 2;
|
||||
}
|
||||
|
||||
A_FaceTarget (self);
|
||||
if (self->CheckMeleeRange ())
|
||||
{
|
||||
DAngle angle;
|
||||
FTranslatedLineTarget t;
|
||||
|
||||
damage *= (pr_m_saw()%10+1);
|
||||
angle = self->Angles.Yaw + pr_m_saw.Random2() * (5.625 / 256);
|
||||
|
||||
P_LineAttack (self, angle, SAWRANGE,
|
||||
P_AimLineAttack (self, angle, SAWRANGE), damage,
|
||||
NAME_Melee, pufftype, false, &t);
|
||||
|
||||
if (!t.linetarget)
|
||||
{
|
||||
S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM);
|
||||
return 0;
|
||||
}
|
||||
S_Sound (self, CHAN_WEAPON, hitsound, 1, ATTN_NORM);
|
||||
|
||||
// turn to face target
|
||||
angle = t.angleFromSource;
|
||||
DAngle anglediff = deltaangle(self->Angles.Yaw, angle);
|
||||
|
||||
if (anglediff < 0.0)
|
||||
{
|
||||
if (anglediff < -4.5)
|
||||
self->Angles.Yaw = angle + 90.0 / 21;
|
||||
else
|
||||
self->Angles.Yaw -= 4.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (anglediff > 4.5)
|
||||
self->Angles.Yaw = angle - 90.0 / 21;
|
||||
else
|
||||
self->Angles.Yaw += 4.5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM);
|
||||
}
|
||||
//A_Chase (self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_M_Punch
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
static void MarinePunch(AActor *self, int damagemul)
|
||||
{
|
||||
DAngle angle;
|
||||
int damage;
|
||||
DAngle pitch;
|
||||
FTranslatedLineTarget t;
|
||||
|
||||
if (self->target == NULL)
|
||||
return;
|
||||
|
||||
damage = ((pr_m_punch()%10+1) << 1) * damagemul;
|
||||
|
||||
A_FaceTarget (self);
|
||||
angle = self->Angles.Yaw + pr_m_punch.Random2() * (5.625 / 256);
|
||||
pitch = P_AimLineAttack (self, angle, MELEERANGE);
|
||||
P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, true, &t);
|
||||
|
||||
// turn to face target
|
||||
if (t.linetarget)
|
||||
{
|
||||
S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM);
|
||||
self->Angles.Yaw = t.angleFromSource;
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Punch)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_INT(mult);
|
||||
|
||||
MarinePunch(self, mult);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// P_GunShot2
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void P_GunShot2 (AActor *mo, bool accurate, DAngle pitch, PClassActor *pufftype)
|
||||
{
|
||||
DAngle angle;
|
||||
int damage;
|
||||
|
||||
damage = 5*(pr_m_gunshot()%3+1);
|
||||
angle = mo->Angles.Yaw;
|
||||
|
||||
if (!accurate)
|
||||
{
|
||||
angle += pr_m_gunshot.Random2() * (5.625 / 256);
|
||||
}
|
||||
|
||||
P_LineAttack (mo, angle, MISSILERANGE, pitch, damage, NAME_Hitscan, pufftype);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_M_FirePistol
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_FirePistol)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_BOOL(accurate);
|
||||
|
||||
if (self->target == NULL)
|
||||
return 0;
|
||||
|
||||
S_Sound (self, CHAN_WEAPON, "weapons/pistol", 1, ATTN_NORM);
|
||||
A_FaceTarget (self);
|
||||
P_GunShot2 (self, accurate, P_AimLineAttack (self, self->Angles.Yaw, MISSILERANGE),
|
||||
PClass::FindActor(NAME_BulletPuff));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_M_FireShotgun
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_M_FireShotgun)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
DAngle pitch;
|
||||
|
||||
if (self->target == NULL)
|
||||
return 0;
|
||||
|
||||
S_Sound (self, CHAN_WEAPON, "weapons/shotgf", 1, ATTN_NORM);
|
||||
A_FaceTarget (self);
|
||||
pitch = P_AimLineAttack (self, self->Angles.Yaw, MISSILERANGE);
|
||||
for (int i = 0; i < 7; ++i)
|
||||
{
|
||||
P_GunShot2 (self, false, pitch, PClass::FindActor(NAME_BulletPuff));
|
||||
}
|
||||
self->special1 = level.maptime + 27;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_M_CheckAttack
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_M_CheckAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (self->special1 != 0 || self->target == NULL)
|
||||
{
|
||||
self->SetState (self->FindState("SkipAttack"));
|
||||
}
|
||||
else
|
||||
{
|
||||
A_FaceTarget (self);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_M_FireShotgun2
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_M_FireShotgun2)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
DAngle pitch;
|
||||
|
||||
if (self->target == NULL)
|
||||
return 0;
|
||||
|
||||
S_Sound (self, CHAN_WEAPON, "weapons/sshotf", 1, ATTN_NORM);
|
||||
A_FaceTarget (self);
|
||||
pitch = P_AimLineAttack (self, self->Angles.Yaw, MISSILERANGE);
|
||||
for (int i = 0; i < 20; ++i)
|
||||
{
|
||||
int damage = 5*(pr_m_fireshotgun2()%3+1);
|
||||
DAngle angle = self->Angles.Yaw + pr_m_fireshotgun2.Random2() * (11.25 / 256);
|
||||
|
||||
P_LineAttack (self, angle, MISSILERANGE,
|
||||
pitch + pr_m_fireshotgun2.Random2() * (7.097 / 256), damage,
|
||||
NAME_Hitscan, NAME_BulletPuff);
|
||||
}
|
||||
self->special1 = level.maptime;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_M_FireCGun
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_FireCGun)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_BOOL(accurate);
|
||||
|
||||
if (self->target == NULL)
|
||||
return 0;
|
||||
|
||||
S_Sound (self, CHAN_WEAPON, "weapons/chngun", 1, ATTN_NORM);
|
||||
A_FaceTarget (self);
|
||||
P_GunShot2 (self, accurate, P_AimLineAttack (self, self->Angles.Yaw, MISSILERANGE),
|
||||
PClass::FindActor(NAME_BulletPuff));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_M_FireMissile
|
||||
//
|
||||
// Giving a marine a rocket launcher is probably a bad idea unless you pump
|
||||
// up his health, because he's just as likely to kill himself as he is to
|
||||
// kill anything else with it.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_M_FireMissile)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (self->target == NULL)
|
||||
return 0;
|
||||
|
||||
if (self->CheckMeleeRange ())
|
||||
{ // If too close, punch it
|
||||
MarinePunch(self, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
A_FaceTarget (self);
|
||||
P_SpawnMissile (self, self->target, PClass::FindActor("Rocket"));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_M_FireRailgun
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_M_FireRailgun)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (self->target == NULL)
|
||||
return 0;
|
||||
|
||||
CALL_ACTION(A_MonsterRail, self);
|
||||
self->special1 = level.maptime + 50;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_M_FirePlasma
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_M_FirePlasma)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (self->target == NULL)
|
||||
return 0;
|
||||
|
||||
A_FaceTarget (self);
|
||||
P_SpawnMissile (self, self->target, PClass::FindActor("PlasmaBall"));
|
||||
self->special1 = level.maptime + 20;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_M_BFGsound
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_M_BFGsound)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (self->target == NULL)
|
||||
return 0;
|
||||
|
||||
if (self->special1 != 0)
|
||||
{
|
||||
self->SetState (self->SeeState);
|
||||
}
|
||||
else
|
||||
{
|
||||
A_FaceTarget (self);
|
||||
S_Sound (self, CHAN_WEAPON, "weapons/bfgf", 1, ATTN_NORM);
|
||||
// Don't interrupt the firing sequence
|
||||
self->PainChance = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_M_FireBFG
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_M_FireBFG)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (self->target == NULL)
|
||||
return 0;
|
||||
|
||||
A_FaceTarget (self);
|
||||
P_SpawnMissile (self, self->target, PClass::FindActor("BFGBall"));
|
||||
self->special1 = level.maptime + 30;
|
||||
self->PainChance = MARINE_PAIN_CHANCE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void AScriptedMarine::SetWeapon (EMarineWeapon type)
|
||||
{
|
||||
if (GetWeaponStates(type, MeleeState, MissileState))
|
||||
{
|
||||
static const char *classes[] = {
|
||||
"ScriptedMarine",
|
||||
"MarineFist",
|
||||
"MarineBerserk",
|
||||
"MarineChainsaw",
|
||||
"MarinePistol",
|
||||
"MarineShotgun",
|
||||
"MarineSSG",
|
||||
"MarineChaingun",
|
||||
"MarineRocket",
|
||||
"MarinePlasma",
|
||||
"MarineRailgun",
|
||||
"MarineBFG"
|
||||
};
|
||||
|
||||
const PClass *cls = PClass::FindClass(classes[type]);
|
||||
if (cls != NULL)
|
||||
DecalGenerator = GetDefaultByType(cls)->DecalGenerator;
|
||||
else
|
||||
DecalGenerator = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void AScriptedMarine::SetSprite (PClassActor *source)
|
||||
{
|
||||
if (source == NULL)
|
||||
{ // A valid actor class wasn't passed, so use the standard sprite
|
||||
SpriteOverride = sprite = GetClass()->OwnedStates[0].sprite;
|
||||
// Copy the standard scaling
|
||||
Scale = GetDefault()->Scale;
|
||||
}
|
||||
else
|
||||
{ // Use the same sprite and scaling the passed class spawns with
|
||||
SpriteOverride = sprite = GetDefaultByType (source)->SpawnState->sprite;
|
||||
Scale = GetDefaultByType(source)->Scale;
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
#include "templates.h"
|
||||
#include "actor.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_local.h"
|
||||
#include "p_enemy.h"
|
||||
#include "a_action.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_spidrefire ("SpidRefire");
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SpidRefire)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
// keep firing unless target got out of sight
|
||||
A_FaceTarget (self);
|
||||
|
||||
if (pr_spidrefire() < 10)
|
||||
return 0;
|
||||
|
||||
if (!self->target
|
||||
|| P_HitFriend (self)
|
||||
|| self->target->health <= 0
|
||||
|| !P_CheckSight (self, self->target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES))
|
||||
{
|
||||
self->SetState (self->SeeState);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Metal)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
S_Sound (self, CHAN_BODY, "spider/walk", 1, ATTN_IDLE);
|
||||
A_Chase (stack, self);
|
||||
return 0;
|
||||
}
|
|
@ -479,15 +479,15 @@ CCMD (useflechette)
|
|||
{ // Select from one of arti_poisonbag1-3, whichever the player has
|
||||
static const ENamedName bagnames[3] =
|
||||
{
|
||||
NAME_ArtiPoisonBag3, // use type 3 first because that's the default when the player has none specified.
|
||||
NAME_ArtiPoisonBag1,
|
||||
NAME_ArtiPoisonBag2,
|
||||
NAME_ArtiPoisonBag3
|
||||
NAME_ArtiPoisonBag2
|
||||
};
|
||||
|
||||
if (who == NULL)
|
||||
return;
|
||||
|
||||
PClassActor *type = GetFlechetteType(who);
|
||||
PClassActor *type = who->FlechetteType;
|
||||
if (type != NULL)
|
||||
{
|
||||
AInventory *item;
|
||||
|
@ -498,7 +498,7 @@ CCMD (useflechette)
|
|||
}
|
||||
}
|
||||
|
||||
// The default flechette could not be found. Try all 3 types then.
|
||||
// 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)
|
||||
{
|
||||
AInventory *item;
|
||||
|
@ -1537,6 +1537,36 @@ static FPlayerStart *SelectRandomDeathmatchSpot (int playernum, unsigned int sel
|
|||
return &deathmatchstarts[i];
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DObject, G_PickDeathmatchStart)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
unsigned int selections = deathmatchstarts.Size();
|
||||
DVector3 pos;
|
||||
int angle;
|
||||
if (selections == 0)
|
||||
{
|
||||
angle = INT_MAX;
|
||||
pos = DVector3(0, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int i = pr_dmspawn() % selections;
|
||||
angle = deathmatchstarts[i].angle;
|
||||
pos = deathmatchstarts[i].pos;
|
||||
}
|
||||
|
||||
if (numret > 1)
|
||||
{
|
||||
ret[1].SetInt(angle);
|
||||
numret = 2;
|
||||
}
|
||||
if (numret > 0)
|
||||
{
|
||||
ret[0].SetVector(pos);
|
||||
}
|
||||
return numret;
|
||||
}
|
||||
|
||||
void G_DeathMatchSpawnPlayer (int playernum)
|
||||
{
|
||||
unsigned int selections;
|
||||
|
@ -1578,6 +1608,7 @@ void G_DeathMatchSpawnPlayer (int playernum)
|
|||
if (mo != NULL) P_PlayerStartStomp(mo);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// G_PickPlayerStart
|
||||
//
|
||||
|
@ -1615,6 +1646,24 @@ FPlayerStart *G_PickPlayerStart(int playernum, int flags)
|
|||
return &playerstarts[playernum];
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DObject, G_PickPlayerStart)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(playernum);
|
||||
PARAM_INT_DEF(flags);
|
||||
auto ps = G_PickPlayerStart(playernum, flags);
|
||||
if (numret > 1)
|
||||
{
|
||||
ret[1].SetInt(ps? ps->angle : 0);
|
||||
numret = 2;
|
||||
}
|
||||
if (numret > 0)
|
||||
{
|
||||
ret[0].SetVector(ps ? ps->pos : DVector3(0, 0, 0));
|
||||
}
|
||||
return numret;
|
||||
}
|
||||
|
||||
//
|
||||
// G_QueueBody
|
||||
//
|
||||
|
|
|
@ -1,233 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "gi.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
#include "d_player.h"
|
||||
#include "a_action.h"
|
||||
#include "a_pickups.h"
|
||||
#include "p_local.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "p_enemy.h"
|
||||
#include "d_event.h"
|
||||
#include "gstrings.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
void P_UpdateBeak (AActor *actor);
|
||||
|
||||
static FRandom pr_chickenplayerthink ("ChickenPlayerThink");
|
||||
static FRandom pr_chicattack ("ChicAttack");
|
||||
static FRandom pr_feathers ("Feathers");
|
||||
static FRandom pr_beakatkpl1 ("BeakAtkPL1");
|
||||
static FRandom pr_beakatkpl2 ("BeakAtkPL2");
|
||||
|
||||
class AChickenPlayer : public APlayerPawn
|
||||
{
|
||||
DECLARE_CLASS (AChickenPlayer, APlayerPawn)
|
||||
public:
|
||||
void MorphPlayerThink ();
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(AChickenPlayer)
|
||||
|
||||
void AChickenPlayer::MorphPlayerThink ()
|
||||
{
|
||||
if (health > 0)
|
||||
{ // Handle beak movement
|
||||
P_UpdateBeak (this);
|
||||
}
|
||||
if (player->morphTics & 15)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (Vel.X == 0 && Vel.Y == 0 && pr_chickenplayerthink () < 160)
|
||||
{ // Twitch view angle
|
||||
Angles.Yaw += pr_chickenplayerthink.Random2() * (360. / 256. / 32.);
|
||||
}
|
||||
if ((Z() <= floorz) && (pr_chickenplayerthink() < 32))
|
||||
{ // Jump and noise
|
||||
Vel.Z += JumpZ;
|
||||
|
||||
FState * painstate = FindState(NAME_Pain);
|
||||
if (painstate != NULL) SetState (painstate);
|
||||
}
|
||||
if (pr_chickenplayerthink () < 48)
|
||||
{ // Just noise
|
||||
S_Sound (this, CHAN_VOICE, "chicken/active", 1, ATTN_NORM);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_ChicAttack
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_ChicAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (!self->target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (self->CheckMeleeRange())
|
||||
{
|
||||
int damage = 1 + (pr_chicattack() & 1);
|
||||
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_Feathers
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Feathers)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
int i;
|
||||
int count;
|
||||
AActor *mo;
|
||||
|
||||
if (self->health > 0)
|
||||
{ // Pain
|
||||
count = pr_feathers() < 32 ? 2 : 1;
|
||||
}
|
||||
else
|
||||
{ // Death
|
||||
count = 5 + (pr_feathers()&3);
|
||||
}
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
mo = Spawn("Feather", self->PosPlusZ(20.), NO_REPLACE);
|
||||
mo->target = self;
|
||||
mo->Vel.X = pr_feathers.Random2() / 256.;
|
||||
mo->Vel.Y = pr_feathers.Random2() / 256.;
|
||||
mo->Vel.Z = 1. + pr_feathers() / 128.;
|
||||
mo->SetState (mo->SpawnState + (pr_feathers()&7));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC P_UpdateBeak
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void P_UpdateBeak (AActor *self)
|
||||
{
|
||||
DPSprite *pspr;
|
||||
if (self->player != nullptr && (pspr = self->player->FindPSprite(PSP_WEAPON)) != nullptr)
|
||||
{
|
||||
pspr->y = WEAPONTOP + self->player->chickenPeck / 2;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_BeakRaise
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BeakRaise)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
player_t *player;
|
||||
|
||||
if (nullptr == (player = self->player))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
player->GetPSprite(PSP_WEAPON)->y = WEAPONTOP;
|
||||
P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->GetReadyState());
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC P_PlayPeck
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void P_PlayPeck (AActor *chicken)
|
||||
{
|
||||
S_Sound (chicken, CHAN_VOICE, "chicken/peck", 1, ATTN_NORM);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_BeakAttackPL1
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL1)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
DAngle angle;
|
||||
int damage;
|
||||
DAngle slope;
|
||||
player_t *player;
|
||||
FTranslatedLineTarget t;
|
||||
|
||||
if (NULL == (player = self->player))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
damage = 1 + (pr_beakatkpl1()&3);
|
||||
angle = player->mo->Angles.Yaw;
|
||||
slope = P_AimLineAttack (player->mo, angle, MELEERANGE);
|
||||
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &t);
|
||||
if (t.linetarget)
|
||||
{
|
||||
player->mo->Angles.Yaw = t.angleFromSource;
|
||||
}
|
||||
P_PlayPeck (player->mo);
|
||||
player->chickenPeck = 12;
|
||||
player->GetPSprite(PSP_WEAPON)->Tics -= pr_beakatkpl1() & 7;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_BeakAttackPL2
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL2)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
DAngle angle;
|
||||
int damage;
|
||||
DAngle slope;
|
||||
player_t *player;
|
||||
FTranslatedLineTarget t;
|
||||
|
||||
if (NULL == (player = self->player))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
damage = pr_beakatkpl2.HitDice (4);
|
||||
angle = player->mo->Angles.Yaw;
|
||||
slope = P_AimLineAttack (player->mo, angle, MELEERANGE);
|
||||
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &t);
|
||||
if (t.linetarget)
|
||||
{
|
||||
player->mo->Angles.Yaw = t.angleFromSource;
|
||||
}
|
||||
P_PlayPeck (player->mo);
|
||||
player->chickenPeck = 12;
|
||||
player->GetPSprite(PSP_WEAPON)->Tics -= pr_beakatkpl2()&3;
|
||||
return 0;
|
||||
}
|
|
@ -1,327 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "p_local.h"
|
||||
#include "p_enemy.h"
|
||||
#include "a_action.h"
|
||||
#include "s_sound.h"
|
||||
#include "m_random.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "gstrings.h"
|
||||
#include "a_specialspot.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
#include "g_level.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_s2fx1 ("S2FX1");
|
||||
static FRandom pr_scrc1atk ("Srcr1Attack");
|
||||
static FRandom pr_dst ("D'SparilTele");
|
||||
static FRandom pr_s2d ("Srcr2Decide");
|
||||
static FRandom pr_s2a ("Srcr2Attack");
|
||||
static FRandom pr_bluespark ("BlueSpark");
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_Sor1Pain
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Sor1Pain)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
self->special1 = 20; // Number of steps to walk fast
|
||||
CALL_ACTION(A_Pain, self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_Sor1Chase
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Sor1Chase)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (self->special1)
|
||||
{
|
||||
self->special1--;
|
||||
self->tics -= 3;
|
||||
}
|
||||
A_Chase(stack, self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_Srcr1Attack
|
||||
//
|
||||
// Sorcerer demon attack.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Srcr1Attack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
AActor *mo;
|
||||
DAngle angle;
|
||||
|
||||
if (!self->target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
S_Sound (self, CHAN_BODY, self->AttackSound, 1, ATTN_NORM);
|
||||
if (self->CheckMeleeRange ())
|
||||
{
|
||||
int damage = pr_scrc1atk.HitDice (8);
|
||||
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PClassActor *fx = PClass::FindActor("SorcererFX1");
|
||||
if (self->health > (self->SpawnHealth()/3)*2)
|
||||
{ // Spit one fireball
|
||||
P_SpawnMissileZ (self, self->Z() + 48, self->target, fx );
|
||||
}
|
||||
else
|
||||
{ // Spit three fireballs
|
||||
mo = P_SpawnMissileZ (self, self->Z() + 48, self->target, fx);
|
||||
if (mo != NULL)
|
||||
{
|
||||
angle = mo->Angles.Yaw;
|
||||
P_SpawnMissileAngleZ(self, self->Z() + 48, fx, angle - 3, mo->Vel.Z);
|
||||
P_SpawnMissileAngleZ(self, self->Z() + 48, fx, angle + 3, mo->Vel.Z);
|
||||
}
|
||||
if (self->health < self->SpawnHealth()/3)
|
||||
{ // Maybe attack again
|
||||
if (self->special1)
|
||||
{ // Just attacked, so don't attack again
|
||||
self->special1 = 0;
|
||||
}
|
||||
else
|
||||
{ // Set state to attack again
|
||||
self->special1 = 1;
|
||||
self->SetState (self->FindState("Missile2"));
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_SorcererRise
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SorcererRise)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
AActor *mo;
|
||||
|
||||
self->flags &= ~MF_SOLID;
|
||||
mo = Spawn("Sorcerer2", self->Pos(), ALLOW_REPLACE);
|
||||
mo->Translation = self->Translation;
|
||||
mo->SetState (mo->FindState("Rise"));
|
||||
mo->Angles.Yaw = self->Angles.Yaw;
|
||||
mo->CopyFriendliness (self, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC P_DSparilTeleport
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void P_DSparilTeleport (AActor *actor)
|
||||
{
|
||||
DVector3 prev;
|
||||
AActor *mo;
|
||||
AActor *spot;
|
||||
|
||||
DSpotState *state = DSpotState::GetSpotState();
|
||||
if (state == NULL) return;
|
||||
|
||||
spot = state->GetSpotWithMinMaxDistance(PClass::FindActor("BossSpot"), actor->X(), actor->Y(), 128, 0);
|
||||
if (spot == NULL) return;
|
||||
|
||||
prev = actor->Pos();
|
||||
if (P_TeleportMove (actor, spot->Pos(), false))
|
||||
{
|
||||
mo = Spawn("Sorcerer2Telefade", prev, ALLOW_REPLACE);
|
||||
if (mo) mo->Translation = actor->Translation;
|
||||
S_Sound (mo, CHAN_BODY, "misc/teleport", 1, ATTN_NORM);
|
||||
actor->SetState (actor->FindState("Teleport"));
|
||||
S_Sound (actor, CHAN_BODY, "misc/teleport", 1, ATTN_NORM);
|
||||
actor->SetZ(actor->floorz);
|
||||
actor->Angles.Yaw = spot->Angles.Yaw;
|
||||
actor->Vel.Zero();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_Srcr2Decide
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Srcr2Decide)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
static const int chance[] =
|
||||
{
|
||||
192, 120, 120, 120, 64, 64, 32, 16, 0
|
||||
};
|
||||
|
||||
unsigned int chanceindex = self->health / ((self->SpawnHealth()/8 == 0) ? 1 : self->SpawnHealth()/8);
|
||||
if (chanceindex >= countof(chance))
|
||||
{
|
||||
chanceindex = countof(chance) - 1;
|
||||
}
|
||||
|
||||
if (pr_s2d() < chance[chanceindex])
|
||||
{
|
||||
P_DSparilTeleport (self);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_Srcr2Attack
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Srcr2Attack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
int chance;
|
||||
|
||||
if (!self->target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
S_Sound (self, CHAN_BODY, self->AttackSound, 1, ATTN_NONE);
|
||||
if (self->CheckMeleeRange())
|
||||
{
|
||||
int damage = pr_s2a.HitDice (20);
|
||||
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||
return 0;
|
||||
}
|
||||
chance = self->health < self->SpawnHealth()/2 ? 96 : 48;
|
||||
if (pr_s2a() < chance)
|
||||
{ // Wizard spawners
|
||||
|
||||
PClassActor *fx = PClass::FindActor("Sorcerer2FX2");
|
||||
if (fx)
|
||||
{
|
||||
P_SpawnMissileAngle(self, fx, self->Angles.Yaw - 45, 0.5);
|
||||
P_SpawnMissileAngle(self, fx, self->Angles.Yaw + 45, 0.5);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Blue bolt
|
||||
P_SpawnMissile (self, self->target, PClass::FindActor("Sorcerer2FX1"));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_BlueSpark
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BlueSpark)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
int i;
|
||||
AActor *mo;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
mo = Spawn("Sorcerer2FXSpark", self->Pos(), ALLOW_REPLACE);
|
||||
mo->Vel.X = pr_bluespark.Random2() / 128.;
|
||||
mo->Vel.Y = pr_bluespark.Random2() / 128.;
|
||||
mo->Vel.Z = 1. + pr_bluespark() / 256.;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_GenWizard
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_GenWizard)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
AActor *mo;
|
||||
|
||||
mo = Spawn("Wizard", self->Pos(), ALLOW_REPLACE);
|
||||
if (mo != NULL)
|
||||
{
|
||||
mo->AddZ(-mo->GetDefault()->Height / 2, false);
|
||||
if (!P_TestMobjLocation (mo))
|
||||
{ // Didn't fit
|
||||
mo->ClearCounters();
|
||||
mo->Destroy ();
|
||||
}
|
||||
else
|
||||
{ // [RH] Make the new wizards inherit D'Sparil's target
|
||||
mo->CopyFriendliness (self->target, true);
|
||||
|
||||
self->Vel.Zero();
|
||||
self->SetState (self->FindState(NAME_Death));
|
||||
self->flags &= ~MF_MISSILE;
|
||||
mo->master = self->target;
|
||||
P_SpawnTeleportFog(self, self->Pos(), false, true);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_Sor2DthInit
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Sor2DthInit)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
self->special1 = 7; // Animation loop counter
|
||||
P_Massacre (); // Kill monsters early
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_Sor2DthLoop
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Sor2DthLoop)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (--self->special1)
|
||||
{ // Need to loop
|
||||
self->SetState (self->FindState("DeathLoop"));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
#include "info.h"
|
||||
#include "a_pickups.h"
|
||||
#include "a_artifacts.h"
|
||||
#include "gstrings.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
// Tome of power ------------------------------------------------------------
|
||||
|
||||
class AArtiTomeOfPower : public APowerupGiver
|
||||
{
|
||||
DECLARE_CLASS (AArtiTomeOfPower, APowerupGiver)
|
||||
public:
|
||||
bool Use (bool pickup);
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_CLASS (AArtiTomeOfPower)
|
||||
|
||||
bool AArtiTomeOfPower::Use (bool pickup)
|
||||
{
|
||||
if (Owner->player->morphTics && (Owner->player->MorphStyle & MORPH_UNDOBYTOMEOFPOWER))
|
||||
{ // Attempt to undo chicken
|
||||
if (!P_UndoPlayerMorph (Owner->player, Owner->player, MORPH_UNDOBYTOMEOFPOWER))
|
||||
{ // Failed
|
||||
if (!(Owner->player->MorphStyle & MORPH_FAILNOTELEFRAG))
|
||||
{
|
||||
P_DamageMobj (Owner, NULL, NULL, TELEFRAG_DAMAGE, NAME_Telefrag);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Succeeded
|
||||
S_Sound (Owner, CHAN_VOICE, "*evillaugh", 1, ATTN_IDLE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Super::Use (pickup);
|
||||
}
|
||||
}
|
||||
|
||||
// Time bomb ----------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_TimeBomb)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
self->AddZ(32, false);
|
||||
self->RenderStyle = STYLE_Add;
|
||||
self->Alpha = 1.;
|
||||
P_RadiusAttack (self, self->target, 128, 128, self->DamageType, RADF_HURTSOURCE);
|
||||
P_CheckSplash(self, 128);
|
||||
return 0;
|
||||
}
|
||||
|
||||
class AArtiTimeBomb : public AInventory
|
||||
{
|
||||
DECLARE_CLASS (AArtiTimeBomb, AInventory)
|
||||
public:
|
||||
bool Use (bool pickup);
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_CLASS (AArtiTimeBomb)
|
||||
|
||||
bool AArtiTimeBomb::Use (bool pickup)
|
||||
{
|
||||
AActor *mo = Spawn("ActivatedTimeBomb",
|
||||
Owner->Vec3Angle(24., Owner->Angles.Yaw, - Owner->Floorclip), ALLOW_REPLACE);
|
||||
mo->target = Owner;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
/*
|
||||
#include "templates.h"
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_local.h"
|
||||
#include "gstrings.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_impmsatk ("ImpMsAttack");
|
||||
static FRandom pr_imp ("ImpExplode");
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_ImpMsAttack
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_ImpMsAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (!self->target || pr_impmsatk() > 64)
|
||||
{
|
||||
self->SetState (self->SeeState);
|
||||
return 0;
|
||||
}
|
||||
A_SkullAttack(self, 12.);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_ImpExplode
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_ImpExplode)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
AActor *chunk;
|
||||
|
||||
self->flags &= ~MF_NOGRAVITY;
|
||||
|
||||
chunk = Spawn("HereticImpChunk1", self->Pos(), ALLOW_REPLACE);
|
||||
chunk->Vel.X = pr_imp.Random2() / 64.;
|
||||
chunk->Vel.Y = pr_imp.Random2() / 64.;
|
||||
chunk->Vel.Z = 9;
|
||||
|
||||
chunk = Spawn("HereticImpChunk2", self->Pos(), ALLOW_REPLACE);
|
||||
chunk->Vel.X = pr_imp.Random2() / 64.;
|
||||
chunk->Vel.Y = pr_imp.Random2() / 64.;
|
||||
chunk->Vel.Z = 9;
|
||||
if (self->special1 == 666)
|
||||
{ // Extreme death crash
|
||||
self->SetState (self->FindState("XCrash"));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_ImpDeath
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_ImpDeath)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
self->flags &= ~MF_SOLID;
|
||||
self->flags2 |= MF2_FLOORCLIP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_ImpXDeath1
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_ImpXDeath1)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
self->flags &= ~MF_SOLID;
|
||||
self->flags |= MF_NOGRAVITY;
|
||||
self->flags2 |= MF2_FLOORCLIP;
|
||||
self->special1 = 666; // Flag the crash routine
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,219 +0,0 @@
|
|||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "a_pickups.h"
|
||||
#include "a_action.h"
|
||||
#include "m_random.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "gstrings.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
#include "p_enemy.h"
|
||||
#include "a_specialspot.h"
|
||||
#include "g_level.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "templates.h"
|
||||
#include "r_data/r_translate.h"
|
||||
#include "doomstat.h"
|
||||
#include "d_player.h"
|
||||
#include "a_morph.h"
|
||||
#include "p_spec.h"
|
||||
#include "serializer.h"
|
||||
|
||||
// Include all the other Heretic stuff here to reduce compile time
|
||||
#include "a_chicken.cpp"
|
||||
#include "a_dsparil.cpp"
|
||||
#include "a_hereticartifacts.cpp"
|
||||
#include "a_hereticimp.cpp"
|
||||
#include "a_hereticweaps.cpp"
|
||||
#include "a_ironlich.cpp"
|
||||
#include "a_knight.cpp"
|
||||
#include "a_wizard.cpp"
|
||||
|
||||
|
||||
static FRandom pr_podpain ("PodPain");
|
||||
static FRandom pr_makepod ("MakePod");
|
||||
static FRandom pr_teleg ("TeleGlitter");
|
||||
static FRandom pr_teleg2 ("TeleGlitter2");
|
||||
static FRandom pr_volcano ("VolcanoSet");
|
||||
static FRandom pr_blast ("VolcanoBlast");
|
||||
static FRandom pr_volcimpact ("VolcBallImpact");
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_PodPain
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PodPain)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_CLASS_OPT (gootype, AActor) { gootype = PClass::FindActor("PodGoo"); }
|
||||
|
||||
int count;
|
||||
int chance;
|
||||
AActor *goo;
|
||||
|
||||
chance = pr_podpain ();
|
||||
if (chance < 128)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
for (count = chance > 240 ? 2 : 1; count; count--)
|
||||
{
|
||||
goo = Spawn(gootype, self->PosPlusZ(48.), ALLOW_REPLACE);
|
||||
goo->target = self;
|
||||
goo->Vel.X = pr_podpain.Random2() / 128.;
|
||||
goo->Vel.Y = pr_podpain.Random2() / 128.;
|
||||
goo->Vel.Z = 0.5 + pr_podpain() / 128.;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_RemovePod
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_RemovePod)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
AActor *mo;
|
||||
|
||||
if ( (mo = self->master) )
|
||||
{
|
||||
if (mo->special1 > 0)
|
||||
{
|
||||
mo->special1--;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_MakePod
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#define MAX_GEN_PODS 16
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MakePod)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_CLASS_OPT(podtype, AActor) { podtype = PClass::FindActor("Pod"); }
|
||||
|
||||
AActor *mo;
|
||||
|
||||
if (self->special1 == MAX_GEN_PODS)
|
||||
{ // Too many generated pods
|
||||
return 0;
|
||||
}
|
||||
mo = Spawn(podtype, self->PosAtZ(ONFLOORZ), ALLOW_REPLACE);
|
||||
if (!P_CheckPosition (mo, mo->Pos()))
|
||||
{ // Didn't fit
|
||||
mo->Destroy ();
|
||||
return 0;
|
||||
}
|
||||
mo->SetState (mo->FindState("Grow"));
|
||||
mo->Thrust(pr_makepod() * (360. / 256), 4.5);
|
||||
S_Sound (mo, CHAN_BODY, self->AttackSound, 1, ATTN_IDLE);
|
||||
self->special1++; // Increment generated pod count
|
||||
mo->master = self; // Link the generator to the pod
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_AccTeleGlitter
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_AccTeleGlitter)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (++self->health > 35)
|
||||
{
|
||||
self->Vel.Z *= 1.5;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_VolcanoSet
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_VolcanoSet)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
self->tics = 105 + (pr_volcano() & 127);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_VolcanoBlast
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_VolcanoBlast)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
int i;
|
||||
int count;
|
||||
AActor *blast;
|
||||
|
||||
count = 1 + (pr_blast() % 3);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
blast = Spawn("VolcanoBlast", self->PosPlusZ(44.), ALLOW_REPLACE);
|
||||
blast->target = self;
|
||||
blast->Angles.Yaw = pr_blast() * (360 / 256.);
|
||||
blast->VelFromAngle(1.);
|
||||
blast->Vel.Z = 2.5 + pr_blast() / 64.;
|
||||
S_Sound (blast, CHAN_BODY, "world/volcano/shoot", 1, ATTN_NORM);
|
||||
P_CheckMissileSpawn (blast, self->radius);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_VolcBallImpact
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_VolcBallImpact)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
unsigned int i;
|
||||
AActor *tiny;
|
||||
|
||||
if (self->Z() <= self->floorz)
|
||||
{
|
||||
self->flags |= MF_NOGRAVITY;
|
||||
self->Gravity = 1;
|
||||
self->AddZ(28);
|
||||
//self->Vel.Z = 3;
|
||||
}
|
||||
P_RadiusAttack (self, self->target, 25, 25, NAME_Fire, RADF_HURTSOURCE);
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
tiny = Spawn("VolcanoTBlast", self->Pos(), ALLOW_REPLACE);
|
||||
tiny->target = self;
|
||||
tiny->Angles.Yaw = 90.*i;
|
||||
tiny->VelFromAngle(0.7);
|
||||
tiny->Vel.Z = 1. + pr_volcimpact() / 128.;
|
||||
P_CheckMissileSpawn (tiny, self->radius);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -1,213 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_local.h"
|
||||
#include "p_enemy.h"
|
||||
#include "a_action.h"
|
||||
#include "gstrings.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
#include "g_level.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_foo ("WhirlwindDamage");
|
||||
static FRandom pr_atk ("LichAttack");
|
||||
static FRandom pr_seek ("WhirlwindSeek");
|
||||
|
||||
class AWhirlwind : public AActor
|
||||
{
|
||||
DECLARE_CLASS (AWhirlwind, AActor)
|
||||
public:
|
||||
int DoSpecialDamage (AActor *target, int damage, FName damagetype);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(AWhirlwind)
|
||||
|
||||
int AWhirlwind::DoSpecialDamage (AActor *target, int damage, FName damagetype)
|
||||
{
|
||||
int randVal;
|
||||
|
||||
if (!(target->flags7 & MF7_DONTTHRUST))
|
||||
{
|
||||
target->Angles.Yaw += pr_foo.Random2() * (360 / 4096.);
|
||||
target->Vel.X += pr_foo.Random2() / 64.;
|
||||
target->Vel.Y += pr_foo.Random2() / 64.;
|
||||
}
|
||||
|
||||
if ((level.time & 16) && !(target->flags2 & MF2_BOSS) && !(target->flags7 & MF7_DONTTHRUST))
|
||||
{
|
||||
randVal = pr_foo();
|
||||
if (randVal > 160)
|
||||
{
|
||||
randVal = 160;
|
||||
}
|
||||
target->Vel.Z += randVal / 32.;
|
||||
if (target->Vel.Z > 12)
|
||||
{
|
||||
target->Vel.Z = 12;
|
||||
}
|
||||
}
|
||||
if (!(level.time & 7))
|
||||
{
|
||||
P_DamageMobj (target, NULL, this->target, 3, NAME_Melee);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_LichAttack
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_LichAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
int i;
|
||||
AActor *fire;
|
||||
AActor *baseFire;
|
||||
AActor *mo;
|
||||
AActor *target;
|
||||
int randAttack;
|
||||
static const int atkResolve1[] = { 50, 150 };
|
||||
static const int atkResolve2[] = { 150, 200 };
|
||||
|
||||
// Ice ball (close 20% : far 60%)
|
||||
// Fire column (close 40% : far 20%)
|
||||
// Whirlwind (close 40% : far 20%)
|
||||
// Distance threshold = 8 cells
|
||||
|
||||
target = self->target;
|
||||
if (target == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
A_FaceTarget (self);
|
||||
if (self->CheckMeleeRange ())
|
||||
{
|
||||
int damage = pr_atk.HitDice (6);
|
||||
int newdam = P_DamageMobj (target, self, self, damage, NAME_Melee);
|
||||
P_TraceBleed (newdam > 0 ? newdam : damage, target, self);
|
||||
return 0;
|
||||
}
|
||||
int dist = self->Distance2D(target) > 8 * 64;
|
||||
randAttack = pr_atk ();
|
||||
if (randAttack < atkResolve1[dist])
|
||||
{ // Ice ball
|
||||
P_SpawnMissile (self, target, PClass::FindActor("HeadFX1"));
|
||||
S_Sound (self, CHAN_BODY, "ironlich/attack2", 1, ATTN_NORM);
|
||||
}
|
||||
else if (randAttack < atkResolve2[dist])
|
||||
{ // Fire column
|
||||
baseFire = P_SpawnMissile (self, target, PClass::FindActor("HeadFX3"));
|
||||
if (baseFire != NULL)
|
||||
{
|
||||
baseFire->SetState (baseFire->FindState("NoGrow"));
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
fire = Spawn("HeadFX3", baseFire->Pos(), ALLOW_REPLACE);
|
||||
if (i == 0)
|
||||
{
|
||||
S_Sound (self, CHAN_BODY, "ironlich/attack1", 1, ATTN_NORM);
|
||||
}
|
||||
fire->target = baseFire->target;
|
||||
fire->Angles.Yaw = baseFire->Angles.Yaw;
|
||||
fire->Vel = baseFire->Vel;
|
||||
fire->SetDamage(0);
|
||||
fire->health = (i+1) * 2;
|
||||
P_CheckMissileSpawn (fire, self->radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Whirlwind
|
||||
mo = P_SpawnMissile (self, target, RUNTIME_CLASS(AWhirlwind));
|
||||
if (mo != NULL)
|
||||
{
|
||||
mo->AddZ(-32);
|
||||
mo->tracer = target;
|
||||
mo->health = 20*TICRATE; // Duration
|
||||
S_Sound (self, CHAN_BODY, "ironlich/attack3", 1, ATTN_NORM);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_WhirlwindSeek
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_WhirlwindSeek)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
self->health -= 3;
|
||||
if (self->health < 0)
|
||||
{
|
||||
self->Vel.Zero();
|
||||
self->SetState(self->FindState(NAME_Death));
|
||||
self->flags &= ~MF_MISSILE;
|
||||
return 0;
|
||||
}
|
||||
if ((self->threshold -= 3) < 0)
|
||||
{
|
||||
self->threshold = 58 + (pr_seek() & 31);
|
||||
S_Sound(self, CHAN_BODY, "ironlich/attack3", 1, ATTN_NORM);
|
||||
}
|
||||
if (self->tracer && self->tracer->flags&MF_SHADOW)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
P_SeekerMissile(self, 10, 30);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_LichIceImpact
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_LichIceImpact)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
unsigned int i;
|
||||
AActor *shard;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
shard = Spawn("HeadFX2", self->Pos(), ALLOW_REPLACE);
|
||||
shard->target = self->target;
|
||||
shard->Angles.Yaw = i*45.;
|
||||
shard->VelFromAngle();
|
||||
shard->Vel.Z = -.6;
|
||||
P_CheckMissileSpawn (shard, self->radius);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_LichFireGrow
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_LichFireGrow)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
self->health--;
|
||||
self->AddZ(9.);
|
||||
if (self->health == 0)
|
||||
{
|
||||
self->RestoreDamage();
|
||||
self->SetState (self->FindState("NoGrow"));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_local.h"
|
||||
#include "a_action.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "gstrings.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_dripblood ("DripBlood");
|
||||
static FRandom pr_knightatk ("KnightAttack");
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_DripBlood
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_DripBlood)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
AActor *mo;
|
||||
|
||||
double xo = pr_dripblood.Random2() / 32.;
|
||||
double yo = pr_dripblood.Random2() / 32.;
|
||||
mo = Spawn ("Blood", self->Vec3Offset(xo, yo, 0.), ALLOW_REPLACE);
|
||||
mo->Vel.X = pr_dripblood.Random2 () / 64.;
|
||||
mo->Vel.Y = pr_dripblood.Random2() / 64.;
|
||||
mo->Gravity = 1./8;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_KnightAttack
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_KnightAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (!self->target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (self->CheckMeleeRange ())
|
||||
{
|
||||
int damage = pr_knightatk.HitDice (3);
|
||||
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||
S_Sound (self, CHAN_BODY, "hknight/melee", 1, ATTN_NORM);
|
||||
return 0;
|
||||
}
|
||||
// Throw axe
|
||||
S_Sound (self, CHAN_BODY, self->AttackSound, 1, ATTN_NORM);
|
||||
if (self->flags & MF_SHADOW || pr_knightatk () < 40)
|
||||
{ // Red axe
|
||||
P_SpawnMissileZ (self, self->Z() + 36, self->target, PClass::FindActor("RedAxe"));
|
||||
return 0;
|
||||
}
|
||||
// Green axe
|
||||
P_SpawnMissileZ (self, self->Z() + 36, self->target, PClass::FindActor("KnightAxe"));
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_local.h"
|
||||
#include "p_enemy.h"
|
||||
#include "a_action.h"
|
||||
#include "gstrings.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_wizatk3 ("WizAtk3");
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_GhostOff
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_GhostOff)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
self->RenderStyle = STYLE_Normal;
|
||||
self->flags3 &= ~MF3_GHOST;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_WizAtk1
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_WizAtk1)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
A_FaceTarget (self);
|
||||
CALL_ACTION(A_GhostOff, self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_WizAtk2
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_WizAtk2)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
A_FaceTarget (self);
|
||||
self->Alpha = HR_SHADOW;
|
||||
self->RenderStyle = STYLE_Translucent;
|
||||
self->flags3 |= MF3_GHOST;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_WizAtk3
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_WizAtk3)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
AActor *mo;
|
||||
|
||||
CALL_ACTION(A_GhostOff, self);
|
||||
if (!self->target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM);
|
||||
if (self->CheckMeleeRange())
|
||||
{
|
||||
int damage = pr_wizatk3.HitDice (4);
|
||||
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||
return 0;
|
||||
}
|
||||
PClassActor *fx = PClass::FindActor("WizardFX1");
|
||||
mo = P_SpawnMissile (self, self->target, fx);
|
||||
if (mo != NULL)
|
||||
{
|
||||
P_SpawnMissileAngle(self, fx, mo->Angles.Yaw - 45. / 8, mo->Vel.Z);
|
||||
P_SpawnMissileAngle(self, fx, mo->Angles.Yaw + 45. / 8, mo->Vel.Z);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "m_random.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_batspawn ("BatSpawn");
|
||||
static FRandom pr_batmove ("BatMove");
|
||||
|
||||
//===========================================================================
|
||||
// Bat Spawner Variables
|
||||
// special1 frequency counter
|
||||
// special2
|
||||
// args[0] frequency of spawn (1=fastest, 10=slowest)
|
||||
// args[1] spread angle (0..255)
|
||||
// args[2]
|
||||
// args[3] duration of bats (in octics)
|
||||
// args[4] turn amount per move (in degrees)
|
||||
//
|
||||
// Bat Variables
|
||||
// special2 lifetime counter
|
||||
// args[4] turn amount per move (in degrees)
|
||||
//===========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BatSpawnInit)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
self->special1 = 0; // Frequency count
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BatSpawn)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
AActor *mo;
|
||||
int delta;
|
||||
DAngle angle;
|
||||
|
||||
// Countdown until next spawn
|
||||
if (self->special1-- > 0) return 0;
|
||||
self->special1 = self->args[0]; // Reset frequency count
|
||||
|
||||
delta = self->args[1];
|
||||
if (delta==0) delta=1;
|
||||
|
||||
angle = self->Angles.Yaw + (((pr_batspawn() % delta) - (delta >> 1)) * (360 / 256.));
|
||||
|
||||
mo = P_SpawnMissileAngle (self, PClass::FindActor("Bat"), angle, 0);
|
||||
if (mo)
|
||||
{
|
||||
mo->args[0] = pr_batspawn()&63; // floatbob index
|
||||
mo->args[4] = self->args[4]; // turn degrees
|
||||
mo->special2 = self->args[3]<<3; // Set lifetime
|
||||
mo->target = self;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BatMove)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
DAngle newangle;
|
||||
|
||||
if (self->special2 < 0)
|
||||
{
|
||||
self->SetState (self->FindState(NAME_Death));
|
||||
}
|
||||
self->special2 -= 2; // Called every 2 tics
|
||||
|
||||
if (pr_batmove()<128)
|
||||
{
|
||||
newangle = self->Angles.Yaw + self->args[4];
|
||||
}
|
||||
else
|
||||
{
|
||||
newangle = self->Angles.Yaw - self->args[4];
|
||||
}
|
||||
|
||||
// Adjust velocity vector to new direction
|
||||
self->VelFromAngle(newangle, self->Speed);
|
||||
|
||||
if (pr_batmove()<15)
|
||||
{
|
||||
S_Sound (self, CHAN_VOICE, "BatScream", 1, ATTN_IDLE);
|
||||
}
|
||||
|
||||
// Handle Z movement
|
||||
self->SetZ(self->target->Z() + 2 * BobSin(self->args[0]));
|
||||
self->args[0] = (self->args[0]+3)&63;
|
||||
return 0;
|
||||
}
|
|
@ -1,230 +0,0 @@
|
|||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "a_action.h"
|
||||
#include "m_random.h"
|
||||
#include "a_hexenglobal.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_boom ("BishopBoom");
|
||||
static FRandom pr_atk ("BishopAttack");
|
||||
static FRandom pr_decide ("BishopDecide");
|
||||
static FRandom pr_doblur ("BishopDoBlur");
|
||||
static FRandom pr_sblur ("BishopSpawnBlur");
|
||||
static FRandom pr_pain ("BishopPainBlur");
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_BishopAttack
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BishopAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (!self->target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
S_Sound (self, CHAN_BODY, self->AttackSound, 1, ATTN_NORM);
|
||||
if (self->CheckMeleeRange())
|
||||
{
|
||||
int damage = pr_atk.HitDice (4);
|
||||
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||
return 0;
|
||||
}
|
||||
self->special1 = (pr_atk() & 3) + 5;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_BishopAttack2
|
||||
//
|
||||
// Spawns one of a string of bishop missiles
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BishopAttack2)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
AActor *mo;
|
||||
|
||||
if (!self->target || !self->special1)
|
||||
{
|
||||
self->special1 = 0;
|
||||
self->SetState (self->SeeState);
|
||||
return 0;
|
||||
}
|
||||
mo = P_SpawnMissile (self, self->target, PClass::FindActor("BishopFX"));
|
||||
if (mo != NULL)
|
||||
{
|
||||
mo->tracer = self->target;
|
||||
}
|
||||
self->special1--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_BishopMissileWeave
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BishopMissileWeave)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
A_Weave(self, 2, 2, 2., 1.);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_BishopDecide
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BishopDecide)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
if (pr_decide() < 220)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->SetState (self->FindState ("Blur"));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_BishopDoBlur
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BishopDoBlur)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
self->special1 = (pr_doblur() & 3) + 3; // Random number of blurs
|
||||
if (pr_doblur() < 120)
|
||||
{
|
||||
self->Thrust(self->Angles.Yaw + 90, 11);
|
||||
}
|
||||
else if (pr_doblur() > 125)
|
||||
{
|
||||
self->Thrust(self->Angles.Yaw - 90, 11);
|
||||
}
|
||||
else
|
||||
{ // Thrust forward
|
||||
self->Thrust(11);
|
||||
}
|
||||
S_Sound (self, CHAN_BODY, "BishopBlur", 1, ATTN_NORM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_BishopSpawnBlur
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BishopSpawnBlur)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
AActor *mo;
|
||||
|
||||
if (!--self->special1)
|
||||
{
|
||||
self->Vel.X = self->Vel.Y = 0;
|
||||
if (pr_sblur() > 96)
|
||||
{
|
||||
self->SetState (self->SeeState);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->SetState (self->MissileState);
|
||||
}
|
||||
}
|
||||
mo = Spawn ("BishopBlur", self->Pos(), ALLOW_REPLACE);
|
||||
if (mo)
|
||||
{
|
||||
mo->Angles.Yaw = self->Angles.Yaw;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_BishopChase
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BishopChase)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
double newz = self->Z() - BobSin(self->special2) / 2.;
|
||||
self->special2 = (self->special2 + 4) & 63;
|
||||
newz += BobSin(self->special2) / 2.;
|
||||
self->SetZ(newz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_BishopPuff
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BishopPuff)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
AActor *mo;
|
||||
|
||||
mo = Spawn ("BishopPuff", self->PosPlusZ(40.), ALLOW_REPLACE);
|
||||
if (mo)
|
||||
{
|
||||
mo->Vel.Z = -.5;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_BishopPainBlur
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BishopPainBlur)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
|
||||
AActor *mo;
|
||||
|
||||
if (pr_pain() < 64)
|
||||
{
|
||||
self->SetState (self->FindState ("Blur"));
|
||||
return 0;
|
||||
}
|
||||
double xo = pr_pain.Random2() / 16.;
|
||||
double yo = pr_pain.Random2() / 16.;
|
||||
double zo = pr_pain.Random2() / 32.;
|
||||
mo = Spawn ("BishopPainBlur", self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
|
||||
if (mo)
|
||||
{
|
||||
mo->Angles.Yaw = self->Angles.Yaw;
|
||||
}
|
||||
return 0;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue