Merge branch 'master' of https://github.com/rheit/zdoom into g1.8

Conflicts:
	wadsrc/static/compatibility.txt
This commit is contained in:
alexey.lysiuk 2015-12-23 12:19:42 +02:00
commit 07ece9a477
94 changed files with 3219 additions and 2701 deletions

View file

@ -123,7 +123,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS( GME
if( MSVC )
# Eliminate unreferenced functions and data
# Perform identical COMDAT folding
set( REL_LINKER_FLAGS "/opt:ref /opt:icf /nodefaultlib:msvcrt /TSAWARE" )
set( REL_LINKER_FLAGS "/opt:ref /opt:icf /nodefaultlib:msvcrt /TSAWARE /LARGEADDRESSAWARE" )
# String pooling
# Function-level linking

View file

@ -39,7 +39,6 @@ add_library( dumb
src/helpers/memfile.c
src/helpers/clickrem.c
src/helpers/barray.c
src/helpers/tarray.c
src/it/xmeffect.c
src/it/readxm2.c
src/it/readxm.c

View file

@ -36,24 +36,24 @@
#endif
#define DUMB_MAJOR_VERSION 0
#define DUMB_MINOR_VERSION 9
#define DUMB_REVISION_VERSION 3
#define DUMB_MAJOR_VERSION 1
#define DUMB_MINOR_VERSION 0
#define DUMB_REVISION_VERSION 0
#define DUMB_VERSION (DUMB_MAJOR_VERSION*10000 + DUMB_MINOR_VERSION*100 + DUMB_REVISION_VERSION)
#define DUMB_VERSION_STR "0.9.3"
#define DUMB_VERSION_STR "1.0.0"
#define DUMB_NAME "DUMB v" DUMB_VERSION_STR
#define DUMB_YEAR 2005
#define DUMB_MONTH 8
#define DUMB_DAY 7
#define DUMB_YEAR 2015
#define DUMB_MONTH 1
#define DUMB_DAY 17
#define DUMB_YEAR_STR2 "05"
#define DUMB_YEAR_STR4 "2005"
#define DUMB_MONTH_STR1 "8"
#define DUMB_DAY_STR1 "7"
#define DUMB_YEAR_STR2 "15"
#define DUMB_YEAR_STR4 "2015"
#define DUMB_MONTH_STR1 "1"
#define DUMB_DAY_STR1 "17"
#if DUMB_MONTH < 10
#define DUMB_MONTH_STR2 "0" DUMB_MONTH_STR1
@ -606,10 +606,6 @@ typedef void (*DUH_SIGRENDERER_GET_CURRENT_SAMPLE)(
sample_t *samples
);
typedef int32 (*DUH_SIGRENDERER_GET_POSITION)(
sigrenderer_t *sigrenderer
);
typedef void (*DUH_END_SIGRENDERER)(sigrenderer_t *sigrenderer);
typedef void (*DUH_UNLOAD_SIGDATA)(sigdata_t *sigdata);
@ -625,7 +621,6 @@ typedef struct DUH_SIGTYPE_DESC
DUH_SIGRENDERER_SET_SIGPARAM sigrenderer_set_sigparam;
DUH_SIGRENDERER_GENERATE_SAMPLES sigrenderer_generate_samples;
DUH_SIGRENDERER_GET_CURRENT_SAMPLE sigrenderer_get_current_sample;
DUH_SIGRENDERER_GET_POSITION sigrenderer_get_position;
DUH_END_SIGRENDERER end_sigrenderer;
DUH_UNLOAD_SIGDATA unload_sigdata;
}

View file

@ -33,7 +33,6 @@
#include <stddef.h>
#include "barray.h"
#include "tarray.h"
/** TO DO: THINK ABOUT THE FOLLOWING:
@ -724,21 +723,6 @@ struct DUMB_IT_SIGRENDERER
#ifdef BIT_ARRAY_BULLSHIT
/* bit array, which rows are played, only checked by pattern break or loop commands */
void * played;
/*
Loop indicator for internal processes, may also be useful for external processes
0 - Not looped
1 - Looped
-1 - Continued past loop
*/
int looped;
/*
Kept until looped
*/
LONG_LONG time_played;
void * row_timekeeper;
#endif
int32 gvz_time;

View file

@ -1,31 +0,0 @@
#ifndef _T_ARRAY_H_
#define _T_ARRAY_H_
#include <stdlib.h>
#ifndef LONG_LONG
#if defined __GNUC__ || defined __INTEL_COMPILER || defined __MWERKS__
#define LONG_LONG long long
#elif defined _MSC_VER || defined __WATCOMC__
#define LONG_LONG __int64
#elif defined __sgi
#define LONG_LONG long long
#else
#error 64-bit integer type unknown
#endif
#endif
void * timekeeping_array_create(size_t size);
void timekeeping_array_destroy(void * array);
void * timekeeping_array_dup(void * array);
void timekeeping_array_reset(void * array, size_t loop_start);
void timekeeping_array_push(void * array, size_t index, LONG_LONG time);
void timekeeping_array_bump(void * array, size_t index);
unsigned int timekeeping_array_get_count(void * array, size_t index);
LONG_LONG timekeeping_array_get_item(void * array, size_t index);
#endif

View file

@ -37,7 +37,6 @@ SOURCES += \
../../src/helpers/memfile.c \
../../src/helpers/clickrem.c \
../../src/helpers/barray.c \
../../src/helpers/tarray.c \
../../src/it/xmeffect.c \
../../src/it/readxm2.c \
../../src/it/readxm.c \
@ -109,7 +108,6 @@ HEADERS += \
../../include/internal/it.h \
../../include/internal/dumb.h \
../../include/internal/barray.h \
../../include/internal/tarray.h \
../../include/internal/aldumb.h \
../../include/internal/sinc_resampler.h \
../../include/internal/stack_alloc.h \

View file

@ -147,15 +147,7 @@ int DUMBEXPORT duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer)
int32 DUMBEXPORT duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer)
{
DUH_SIGRENDERER_GET_POSITION proc;
if (!sigrenderer) return -1;
proc = sigrenderer->desc->sigrenderer_get_position;
if (proc)
return (*proc)(sigrenderer->sigrenderer);
else
return sigrenderer->pos;
return sigrenderer ? sigrenderer->pos : -1;
}

View file

@ -1,175 +0,0 @@
#include "internal/tarray.h"
#include <string.h>
/*
Structures which contain the play times of each pattern and row combination in the song,
not guaranteed to be valid for the whole song until the loop status is no longer zero.
The initial count and restart count will both be zero on song start, then both will be
incremented until the song loops. Restart count will be reset to zero on loop for all
rows which have a time equal to or greater than the loop start point, so time keeping
functions will know which timestamp the song is currently located at.
Timestamp lists are guaranteed to be allocated in blocks of 16 timestamps at a time.
*/
/*
We don't need full timekeeping because the player loop only wants the first play time
of the loop start order/row. We also don't really want full timekeeping because it
involves a lot of memory allocations, which is also slow.
*/
#undef FULL_TIMEKEEPING
typedef struct DUMB_IT_ROW_TIME
{
unsigned int count, restart_count;
#ifndef FULL_TIMEKEEPING
LONG_LONG first_time;
#else
LONG_LONG * times;
#endif
} DUMB_IT_ROW_TIME;
void * timekeeping_array_create(size_t size)
{
size_t * _size = (size_t *) calloc( 1, sizeof(size_t) + sizeof(DUMB_IT_ROW_TIME) * size );
if ( _size ) {
*_size = size;
}
return _size;
}
void timekeeping_array_destroy(void * array)
{
#ifdef FULL_TIMEKEEPING
size_t i;
size_t * size = (size_t *) array;
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
for (i = 0; i < *size; i++) {
if (s[i].times) free(s[i].times);
}
#endif
free(array);
}
void * timekeeping_array_dup(void * array)
{
size_t i;
size_t * size = (size_t *) array;
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
size_t * new_size = (size_t *) calloc( 1, sizeof(size_t) + sizeof(DUMB_IT_ROW_TIME) * *size );
if ( new_size ) {
DUMB_IT_ROW_TIME * new_s = (DUMB_IT_ROW_TIME *)(new_size + 1);
*new_size = *size;
for (i = 0; i < *size; i++) {
new_s[i].count = s[i].count;
new_s[i].restart_count = s[i].restart_count;
#ifndef FULL_TIMEKEEPING
new_s[i].first_time = s[i].first_time;
#else
if ( s[i].times ) {
size_t time_count = ( s[i].count + 15 ) & ~15;
new_s[i].times = (LONG_LONG *) malloc( sizeof(LONG_LONG) * time_count );
if ( new_s[i].times == (void *)0 ) {
timekeeping_array_destroy( new_size );
return (void *) 0;
}
memcpy( new_s[i].times, s[i].times, sizeof(LONG_LONG) * s[i].count );
}
#endif
}
}
return new_size;
}
void timekeeping_array_reset(void * array, size_t loop_start)
{
size_t i;
size_t * size = (size_t *) array;
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
DUMB_IT_ROW_TIME * s_loop_start = s + loop_start;
LONG_LONG loop_start_time;
if ( loop_start >= *size || s_loop_start->count < 1 ) return;
#ifndef FULL_TIMEKEEPING
loop_start_time = s_loop_start->first_time;
#else
loop_start_time = s_loop_start->times[0];
#endif
for ( i = 0; i < *size; i++ ) {
#ifndef FULL_TIMEKEEPING
if ( s[i].count && s[i].first_time >= loop_start_time ) {
#else
if ( s[i].count && s[i].times[0] >= loop_start_time ) {
#endif
s[i].restart_count = 0;
}
}
}
void timekeeping_array_push(void * array, size_t index, LONG_LONG time)
{
#ifdef FULL_TIMEKEEPING
size_t i;
size_t time_count;
#endif
size_t * size = (size_t *) array;
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
if (index >= *size) return;
#ifndef FULL_TIMEKEEPING
if ( !s[index].count++ )
s[index].first_time = time;
#else
time_count = ( s[index].count + 16 ) & ~15;
s[index].times = (LONG_LONG *) realloc( s[index].times, sizeof(LONG_LONG) * time_count );
s[index].times[s[index].count++] = time;
#endif
}
void timekeeping_array_bump(void * array, size_t index)
{
size_t * size = (size_t *) array;
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
if (index >= *size) return;
s[index].restart_count++;
}
unsigned int timekeeping_array_get_count(void * array, size_t index)
{
size_t * size = (size_t *) array;
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
if (index >= *size) return 0;
return s[index].count;
}
LONG_LONG timekeeping_array_get_item(void * array, size_t index)
{
size_t * size = (size_t *) array;
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
if (index >= *size || s[index].restart_count >= s[index].count) return 0;
#ifndef FULL_TIMEKEEPING
return s[index].first_time;
#else
return s[index].times[s[index].restart_count];
#endif
}

View file

@ -290,12 +290,15 @@ static int it_read_envelope(IT_ENVELOPE *envelope, DUMBFILE *f)
envelope->flags = dumbfile_getc(f);
envelope->n_nodes = dumbfile_getc(f);
if(envelope->n_nodes > 25) {
TRACE("IT error: wrong number of envelope nodes (%d)\n", envelope->n_nodes);
envelope->n_nodes = 0;
return -1;
}
envelope->loop_start = dumbfile_getc(f);
envelope->loop_end = dumbfile_getc(f);
envelope->sus_loop_start = dumbfile_getc(f);
envelope->sus_loop_end = dumbfile_getc(f);
if (envelope->n_nodes > 25)
envelope->n_nodes = 25;
for (n = 0; n < envelope->n_nodes; n++) {
envelope->node_y[n] = dumbfile_getc(f);
envelope->node_t[n] = dumbfile_igetw(f);

View file

@ -352,10 +352,6 @@ static DUMB_IT_SIGRENDERER *dup_sigrenderer(DUMB_IT_SIGRENDERER *src, int n_chan
#ifdef BIT_ARRAY_BULLSHIT
dst->played = bit_array_dup(src->played);
dst->looped = src->looped;
dst->time_played = src->time_played;
dst->row_timekeeper = timekeeping_array_dup(src->row_timekeeper);
#endif
dst->gvz_time = src->gvz_time;
@ -2221,9 +2217,6 @@ Yxy This uses a table 4 times larger (hence 4 times slower) than
bit_array_set(sigrenderer->played, sigrenderer->order * 256 + sigrenderer->row);
#endif
sigrenderer->speed = 0;
#ifdef BIT_ARRAY_BULLSHIT
sigrenderer->looped = 1;
#endif
if (sigrenderer->callbacks->xm_speed_zero && (*sigrenderer->callbacks->xm_speed_zero)(sigrenderer->callbacks->xm_speed_zero_data))
return 1;
}
@ -4341,8 +4334,6 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
/* Fix play tracking and timekeeping for orders containing skip commands */
for (n = 0; n < 256; n++) {
bit_array_set(sigrenderer->played, sigrenderer->processorder * 256 + n);
timekeeping_array_push(sigrenderer->row_timekeeper, sigrenderer->processorder * 256 + n, sigrenderer->time_played);
timekeeping_array_bump(sigrenderer->row_timekeeper, sigrenderer->processorder * 256 + n);
}
#endif
}
@ -4367,9 +4358,6 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
&& bit_array_test(sigrenderer->played, sigrenderer->processorder * 256 + sigrenderer->processrow)
#endif
) {
#ifdef BIT_ARRAY_BULLSHIT
sigrenderer->looped = 1;
#endif
if (sigrenderer->callbacks->loop) {
if ((*sigrenderer->callbacks->loop)(sigrenderer->callbacks->loop_data))
return 1;
@ -4413,13 +4401,6 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
}
}
#ifdef BIT_ARRAY_BULLSHIT
if (sigrenderer->looped == 0) {
timekeeping_array_push(sigrenderer->row_timekeeper, sigrenderer->order * 256 + sigrenderer->row, sigrenderer->time_played);
}
timekeeping_array_bump(sigrenderer->row_timekeeper, sigrenderer->order * 256 + sigrenderer->row);
#endif
if (!(sigdata->flags & IT_WAS_A_669))
reset_effects(sigrenderer);
@ -4471,9 +4452,6 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
sigrenderer->gvz_time += (int)(t >> 16);
sigrenderer->gvz_sub_time = (int)t & 65535;
if (sigrenderer->gvz_time >= 65536 * 12) {
#ifdef BIT_ARRAY_BULLSHIT
sigrenderer->looped = 1;
#endif
if ((*sigrenderer->callbacks->global_volume_zero)(sigrenderer->callbacks->global_volume_zero_data))
return 1;
}
@ -5288,10 +5266,6 @@ static DUMB_IT_SIGRENDERER *init_sigrenderer(DUMB_IT_SIGDATA *sigdata, int n_cha
#ifdef BIT_ARRAY_BULLSHIT
sigrenderer->played = bit_array_create(sigdata->n_orders * 256);
sigrenderer->looped = 0;
sigrenderer->time_played = 0;
sigrenderer->row_timekeeper = timekeeping_array_create(sigdata->n_orders * 256);
#endif
{
@ -5310,8 +5284,6 @@ static DUMB_IT_SIGRENDERER *init_sigrenderer(DUMB_IT_SIGDATA *sigdata, int n_cha
/* Fix for played order detection for songs which have skips at the start of the orders list */
for (n = 0; n < 256; n++) {
bit_array_set(sigrenderer->played, order * 256 + n);
timekeeping_array_push(sigrenderer->row_timekeeper, order * 256 + n, 0);
timekeeping_array_bump(sigrenderer->row_timekeeper, order * 256 + n);
}
#endif
}
@ -5324,6 +5296,10 @@ static DUMB_IT_SIGRENDERER *init_sigrenderer(DUMB_IT_SIGDATA *sigdata, int n_cha
sigrenderer->time_left = 0;
sigrenderer->sub_time_left = 0;
#ifdef BIT_ARRAY_BULLSHIT
sigrenderer->played = bit_array_create(sigdata->n_orders * 256);
#endif
sigrenderer->gvz_time = 0;
sigrenderer->gvz_sub_time = 0;
@ -5482,10 +5458,6 @@ static sigrenderer_t *it_start_sigrenderer(DUH *duh, sigdata_t *vsigdata, int n_
while (pos > 0 && pos >= sigrenderer->time_left) {
render(sigrenderer, 0, 1.0f, 0, sigrenderer->time_left, NULL);
#ifdef BIT_ARRAY_BULLSHIT
sigrenderer->time_played += (LONG_LONG)sigrenderer->time_left << 16;
#endif
pos -= sigrenderer->time_left;
sigrenderer->time_left = 0;
@ -5498,10 +5470,6 @@ static sigrenderer_t *it_start_sigrenderer(DUH *duh, sigdata_t *vsigdata, int n_
render(sigrenderer, 0, 1.0f, 0, pos, NULL);
sigrenderer->time_left -= pos;
#ifdef BIT_ARRAY_BULLSHIT
sigrenderer->time_played += (LONG_LONG)pos << 16;
#endif
return sigrenderer;
}
@ -5517,7 +5485,6 @@ static int32 it_sigrenderer_get_samples(
int32 pos;
int dt;
int32 todo;
int ret;
LONG_LONG t;
if (sigrenderer->order < 0) return 0; // problematic
@ -5531,7 +5498,7 @@ static int32 it_sigrenderer_get_samples(
if (!samples) volume = 0;
for (;;) {
todo = (int32)((((LONG_LONG)sigrenderer->time_left << 16) | sigrenderer->sub_time_left) / dt);
todo = (long)((((LONG_LONG)sigrenderer->time_left << 16) | sigrenderer->sub_time_left) / dt);
if (todo >= size)
break;
@ -5545,28 +5512,9 @@ static int32 it_sigrenderer_get_samples(
sigrenderer->sub_time_left = (int32)t & 65535;
sigrenderer->time_left += (int32)(t >> 16);
#ifdef BIT_ARRAY_BULLSHIT
sigrenderer->time_played += (LONG_LONG)todo * dt;
#endif
ret = process_tick(sigrenderer);
if (ret) {
if (process_tick(sigrenderer)) {
sigrenderer->order = -1;
sigrenderer->row = -1;
}
#ifdef BIT_ARRAY_BULLSHIT
if (sigrenderer->looped == 1) {
sigrenderer->looped = -1;
size = 0;
timekeeping_array_reset(sigrenderer->row_timekeeper, sigrenderer->order * 256 + sigrenderer->row);
sigrenderer->time_played = timekeeping_array_get_item(sigrenderer->row_timekeeper, sigrenderer->order * 256 + sigrenderer->row);
break;
}
#endif
if (ret) {
return pos;
}
}
@ -5579,10 +5527,6 @@ static int32 it_sigrenderer_get_samples(
sigrenderer->sub_time_left = (int32)t & 65535;
sigrenderer->time_left += (int32)(t >> 16);
#ifdef BIT_ARRAY_BULLSHIT
sigrenderer->time_played += (LONG_LONG)size * dt;
#endif
if (samples)
dumb_remove_clicks_array(sigrenderer->n_channels, sigrenderer->click_remover, samples, pos, 512.0f / delta);
@ -5634,8 +5578,6 @@ void _dumb_it_end_sigrenderer(sigrenderer_t *vsigrenderer)
#ifdef BIT_ARRAY_BULLSHIT
bit_array_destroy(sigrenderer->played);
timekeeping_array_destroy(sigrenderer->row_timekeeper);
#endif
free(vsigrenderer);
@ -5644,17 +5586,6 @@ void _dumb_it_end_sigrenderer(sigrenderer_t *vsigrenderer)
#ifdef BIT_ARRAY_BULLSHIT
static int32 it_sigrenderer_get_position(sigrenderer_t *vsigrenderer)
{
DUMB_IT_SIGRENDERER *sigrenderer = vsigrenderer;
return (int32)(sigrenderer->time_played >> 16);
}
#endif
DUH_SIGTYPE_DESC _dumb_sigtype_it = {
SIGTYPE_IT,
NULL,
@ -5662,11 +5593,6 @@ DUH_SIGTYPE_DESC _dumb_sigtype_it = {
NULL,
&it_sigrenderer_get_samples,
&it_sigrenderer_get_current_sample,
#ifdef BIT_ARRAY_BULLSHIT
&it_sigrenderer_get_position,
#else
NULL,
#endif
&_dumb_it_end_sigrenderer,
&_dumb_it_unload_sigdata
};

View file

@ -320,6 +320,8 @@ static DUMB_IT_SIGDATA *it_amf_load_sigdata(DUMBFILE *f, int * version)
free( sigdata );
return NULL;
}
sigdata->n_pchannels = nchannels;
memset( sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS );

View file

@ -439,6 +439,7 @@ static DUMB_IT_SIGDATA *it_ptm_load_sigdata(DUMBFILE *f)
}
if (dumbfile_seek(f, 352, DFS_SEEK_SET)) {
free(component);
_dumb_it_unload_sigdata(sigdata);
return NULL;
}
@ -451,12 +452,14 @@ static DUMB_IT_SIGDATA *it_ptm_load_sigdata(DUMBFILE *f)
}
if (dumbfile_seek(f, 608, DFS_SEEK_SET)) {
free(component);
_dumb_it_unload_sigdata(sigdata);
return NULL;
}
for (n = 0; n < sigdata->n_samples; n++) {
if (it_ptm_read_sample_header(&sigdata->sample[n], &component[n_components].offset, f)) {
free(component);
_dumb_it_unload_sigdata(sigdata);
return NULL;
}

View file

@ -1197,6 +1197,7 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
sigdata->instrument = malloc(sigdata->n_instruments * sizeof(*sigdata->instrument));
if (!sigdata->instrument) {
free(roguebytes);
_dumb_it_unload_sigdata(sigdata);
return NULL;
}

View file

@ -118,7 +118,6 @@
<ClCompile Include="..\..\src\helpers\sampbuf.c" />
<ClCompile Include="..\..\src\helpers\silence.c" />
<ClCompile Include="..\..\src\helpers\stdfile.c" />
<ClCompile Include="..\..\src\helpers\tarray.c" />
<ClCompile Include="..\..\src\it\itmisc.c" />
<ClCompile Include="..\..\src\it\itorder.c" />
<ClCompile Include="..\..\src\it\itrender.c" />
@ -210,7 +209,6 @@
<ClInclude Include="..\..\include\internal\lpc.h" />
<ClInclude Include="..\..\include\internal\riff.h" />
<ClInclude Include="..\..\include\internal\stack_alloc.h" />
<ClInclude Include="..\..\include\internal\tarray.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View file

@ -279,9 +279,6 @@
<ClCompile Include="..\..\src\helpers\resampler.c">
<Filter>src\helpers</Filter>
</ClCompile>
<ClCompile Include="..\..\src\helpers\tarray.c">
<Filter>src\helpers</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\dumb.h">
@ -314,9 +311,6 @@
<ClInclude Include="..\..\include\internal\resampler.h">
<Filter>include\internal</Filter>
</ClInclude>
<ClInclude Include="..\..\include\internal\tarray.h">
<Filter>include\internal</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\..\src\helpers\resamp3.inc">

View file

@ -27,7 +27,8 @@ II. Implementation Semantics
II.A : Storage and Retrieval of Data
------------------------------------
No changes.
Any TEXTMAP lump in the described namespaces must be encoded in ISO 8859-1 which
as of this writing is the only character encoding supported by ZDoom.
-----------------------------------
II.B : Storage Within Archive Files
@ -237,6 +238,7 @@ Note: All <bool> fields default to false unless mentioned otherwise.
scalex = <float>; // Vertical scaling on thing. Default = 0 (ignored).
scaley = <float>; // Horizontal scaling on thing. Default = 0 (ignored).
scale = <float>; // Vertical and horizontal scaling on thing. Default = 0 (ignored).
floatbobphase = <int>; // Sets the thing's floatbobphase. Valid phase values are 0-63. Default = -1 (use actor class default).
* Note about arg0str

View file

@ -542,6 +542,11 @@ if( NOT MSVC )
add_definitions( -D__forceinline=inline )
endif( NOT MSVC )
# Fix stat in v140_xp (broken in RTM and Update 1 so far)
if( MSVC AND MSVC_VERSION EQUAL 1900 AND CMAKE_GENERATOR_TOOLSET STREQUAL "v140_xp" )
add_definitions( -D_stat64i32=VS14Stat )
endif( MSVC AND MSVC_VERSION EQUAL 1900 AND CMAKE_GENERATOR_TOOLSET STREQUAL "v140_xp" )
if( UNIX )
CHECK_LIBRARY_EXISTS( rt clock_gettime "" CLOCK_GETTIME_IN_RT )
if( NOT CLOCK_GETTIME_IN_RT )

View file

@ -373,6 +373,7 @@ enum ActorFlag7
MF7_NODECAL = 0x00040000, // [ZK] Forces puff to have no impact decal
MF7_FORCEDECAL = 0x00080000, // [ZK] Forces puff's decal to override the weapon's.
MF7_LAXTELEFRAGDMG = 0x00100000, // [MC] Telefrag damage can be reduced.
MF7_ICESHATTER = 0x00200000, // [MC] Shatters ice corpses regardless of damagetype.
};
// --- mobj.renderflags ---

View file

@ -2328,7 +2328,9 @@ void AM_drawWalls (bool allmap)
AM_drawMline (&l, AMColors.LockedColor); // locked special
}
}
else if (am_showtriggerlines && AMColors.isValid(AMColors.SpecialWallColor) && lines[i].special != 0
else if (am_showtriggerlines && AMColors.isValid(AMColors.SpecialWallColor)
&& LineSpecialsInfo[lines[i].special] != NULL
&& LineSpecialsInfo[lines[i].special]->max_args >= 0
&& lines[i].special != Door_Open
&& lines[i].special != Door_Close
&& lines[i].special != Door_CloseWaitOpen

View file

@ -145,6 +145,7 @@ static FCompatOption Options[] =
{ "badangles", COMPATF2_BADANGLES, SLOT_COMPAT2 },
{ "floormove", COMPATF2_FLOORMOVE, SLOT_COMPAT2 },
{ "soundcutoff", COMPATF2_SOUNDCUTOFF, SLOT_COMPAT2 },
{ "pointonline", COMPATF2_POINTONLINE, SLOT_COMPAT2 },
{ NULL, 0, 0 }
};

View file

@ -368,8 +368,7 @@ bool FConfigFile::DeleteCurrentSection()
LastSectionPtr = &sec->Next;
}
CurrentSection->~FConfigSection();
delete[] (char *)CurrentSection;
delete CurrentSection;
CurrentSection = sec->Next;
return CurrentSection != NULL;

View file

@ -784,7 +784,7 @@ static int PatchThing (int thingy)
bool hadStyle = false;
FStateDefinitions statedef;
bool patchedStates = false;
int oldflags;
ActorFlags oldflags;
const PClass *type;
SWORD *ednum, dummyed;
@ -1139,28 +1139,28 @@ static int PatchThing (int thingy)
}
if (vchanged[1])
{
info->flags2 = ActorFlags2::FromInt (value[1]);
if (info->flags2 & 0x00000004) // old BOUNCE1
if (value[1] & 0x00000004) // old BOUNCE1
{
info->flags2 &= ActorFlags2::FromInt (~4);
value[1] &= ~0x00000004;
info->BounceFlags = BOUNCE_DoomCompat;
}
// Damage types that once were flags but now are not
if (info->flags2 & 0x20000000)
if (value[1] & 0x20000000)
{
info->DamageType = NAME_Ice;
info->flags2 &= ActorFlags2::FromInt (~0x20000000);
value[1] &= ~0x20000000;
}
if (info->flags2 & 0x10000)
if (value[1] & 0x10000000)
{
info->DamageType = NAME_Fire;
info->flags2 &= ActorFlags2::FromInt (~0x10000);
value[1] &= ~0x10000000;
}
if (info->flags2 & 1)
if (value[1] & 0x00000001)
{
info->gravity = FRACUNIT/4;
info->flags2 &= ActorFlags2::FromInt (~1);
value[1] &= ~0x00000001;
}
info->flags2 = ActorFlags2::FromInt (value[1]);
}
if (vchanged[2])
{

View file

@ -561,7 +561,7 @@ CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_NO_PASSMOBJ|COMPATF_LIMITPAIN|
COMPATF_DEHHEALTH|COMPATF_INVISIBILITY|COMPATF_CROSSDROPOFF|COMPATF_CORPSEGIBS|COMPATF_HITSCAN|
COMPATF_WALLRUN|COMPATF_NOTOSSDROPS|COMPATF_LIGHT|COMPATF_MASKEDMIDTEX;
w = COMPATF2_BADANGLES|COMPATF2_FLOORMOVE;
w = COMPATF2_BADANGLES|COMPATF2_FLOORMOVE|COMPATF2_POINTONLINE;
break;
case 3: // Boom compat mode
@ -580,6 +580,7 @@ CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
case 6: // Boom with some added settings to reenable some 'broken' behavior
v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL|COMPATF_MISSILECLIP|COMPATF_NO_PASSMOBJ|
COMPATF_INVISIBILITY|COMPATF_CORPSEGIBS|COMPATF_HITSCAN|COMPATF_WALLRUN|COMPATF_NOTOSSDROPS;
w = COMPATF2_POINTONLINE;
break;
}
@ -622,6 +623,7 @@ CVAR (Flag, compat_maskedmidtex, compatflags, COMPATF_MASKEDMIDTEX);
CVAR (Flag, compat_badangles, compatflags2, COMPATF2_BADANGLES);
CVAR (Flag, compat_floormove, compatflags2, COMPATF2_FLOORMOVE);
CVAR (Flag, compat_soundcutoff, compatflags2, COMPATF2_SOUNDCUTOFF);
CVAR (Flag, compat_pointonline, compatflags2, COMPATF2_POINTONLINE);
//==========================================================================
//

View file

@ -973,7 +973,7 @@ void NetUpdate (void)
{
I_StartTic ();
D_ProcessEvents ();
if ((maketic - gametic) / ticdup >= BACKUPTICS/2-1)
if (pauseext || (maketic - gametic) / ticdup >= BACKUPTICS/2-1)
break; // can't hold any more
//Printf ("mk:%i ",maketic);
@ -1204,7 +1204,7 @@ void NetUpdate (void)
// Send current network delay
// The number of tics we just made should be removed from the count.
netbuffer[k++] = ((maketic - newtics - gametic) / ticdup);
netbuffer[k++] = ((maketic - numtics - gametic) / ticdup);
if (numtics > 0)
{
@ -1810,7 +1810,8 @@ void TryRunTics (void)
// If paused, do not eat more CPU time than we need, because it
// will all be wasted anyway.
if (pauseext) r_NoInterpolate = true;
if (pauseext)
r_NoInterpolate = true;
bool doWait = cl_capfps || r_NoInterpolate /*|| netgame*/;
// get real tics
@ -1828,6 +1829,9 @@ void TryRunTics (void)
// get available tics
NetUpdate ();
if (pauseext)
return;
lowtic = INT_MAX;
numplaying = 0;
for (i = 0; i < doomcom.numnodes; i++)
@ -1935,7 +1939,7 @@ void TryRunTics (void)
C_Ticker ();
M_Ticker ();
I_GetTime (true);
if (!pauseext) G_Ticker();
G_Ticker();
gametic++;
NetUpdate (); // check for new console commands

View file

@ -432,7 +432,7 @@ WORD FDecalLib::GetDecalID (FScanner &sc)
unsigned long num = strtoul (sc.String, NULL, 10);
if (num < 1 || num > 65535)
{
sc.MustGetStringName ("Decal ID must be between 1 and 65535");
sc.ScriptError ("Decal ID must be between 1 and 65535");
}
return (WORD)num;
}
@ -603,16 +603,18 @@ void FDecalLib::ParseGenerator (FScanner &sc)
{
const PClass *type;
FDecalBase *decal;
AActor *actor;
bool optional = false;
// Get name of generator (actor)
sc.MustGetString ();
optional = sc.Compare("optional");
if (optional) sc.MustGetString();
type = PClass::FindClass (sc.String);
if (type == NULL || type->ActorInfo == NULL)
{
sc.ScriptError ("%s is not an actor.", sc.String);
if (!optional) sc.ScriptError ("%s is not an actor.", sc.String);
}
actor = (AActor *)type->Defaults;
// Get name of generated decal
sc.MustGetString ();
@ -625,14 +627,17 @@ void FDecalLib::ParseGenerator (FScanner &sc)
decal = ScanTreeForName (sc.String, Root);
if (decal == NULL)
{
sc.ScriptError ("%s has not been defined.", sc.String);
if (!optional) sc.ScriptError ("%s has not been defined.", sc.String);
}
}
actor->DecalGenerator = decal;
if (decal != NULL)
if (type != NULL)
{
decal->Users.Push (type);
AActor *actor = (AActor *)type->Defaults;
actor->DecalGenerator = decal;
if (decal != NULL)
{
decal->Users.Push(type);
}
}
}

View file

@ -365,6 +365,7 @@ struct FMapThing
short pitch;
short roll;
DWORD RenderStyle;
int FloatbobPhase;
};

View file

@ -340,6 +340,7 @@ enum
COMPATF2_BADANGLES = 1 << 0, // It is impossible to face directly NSEW.
COMPATF2_FLOORMOVE = 1 << 1, // Use the same floor motion behavior as Doom.
COMPATF2_SOUNDCUTOFF = 1 << 2, // Cut off sounds when an actor vanishes instead of making it owner-less
COMPATF2_POINTONLINE = 1 << 3, // Use original but buggy P_PointOnLineSide() and P_PointOnDivlineSide()
};
// Emulate old bugs for select maps. These are not exposed by a cvar

View file

@ -1236,7 +1236,7 @@ void FParser::SF_ObjFlag(void)
t_return.type = svt_int;
if (mo && flagnum<26)
{
t_return.value.i = !!(mo->flags & (1 << flagnum));
t_return.value.i = !!(mo->flags & ActorFlags::FromInt(1 << flagnum));
}
else t_return.value.i = 0;
}

View file

@ -135,7 +135,7 @@ CCMD (dumpmapthings)
}
else
{
Printf("%6d none", infos[i]->Key);
Printf("%6d none\n", infos[i]->Key);
}
}

View file

@ -75,7 +75,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
{
pmo->angle = R_PointToAngle2 (pmo->x, pmo->y, linetarget->x, linetarget->y);
if (((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0))|| linetarget->flags3&MF3_ISMONSTER)
&& (!(linetarget->flags2&(MF2_DORMANT+MF2_INVULNERABLE))))
&& (!(linetarget->flags2&(MF2_DORMANT|MF2_INVULNERABLE))))
{
newLife = player->health+(damage>>3);
newLife = newLife > max ? max : newLife;

View file

@ -698,6 +698,13 @@ void G_DoCompleted (void)
gameaction = ga_nothing;
if ( gamestate == GS_DEMOSCREEN
|| gamestate == GS_FULLCONSOLE
|| gamestate == GS_STARTUP)
{
return;
}
if (gamestate == GS_TITLELEVEL)
{
level.MapName = nextlevel;

View file

@ -339,7 +339,7 @@ struct level_info_t
TArray<FSpecialAction> specialactions;
TArray<FSoundID> PrecacheSounds;
TArray<FTextureID> PrecacheTextures;
TArray<FString> PrecacheTextures;
level_info_t()
{
@ -563,8 +563,10 @@ enum ESkillProperty
SKILLP_FriendlyHealth,
SKILLP_NoPain,
SKILLP_ArmorFactor,
SKILLP_HealthFactor,
SKILLP_EasyKey,
SKILLP_SlowMonsters,
SKILLP_Infight,
};
int G_SkillProperty(ESkillProperty prop);
const char * G_SkillName();
@ -602,7 +604,9 @@ struct FSkillInfo
fixed_t MonsterHealth;
fixed_t FriendlyHealth;
bool NoPain;
int Infighting;
fixed_t ArmorFactor;
fixed_t HealthFactor;
FSkillInfo() {}
FSkillInfo(const FSkillInfo &other)

View file

@ -1077,15 +1077,8 @@ DEFINE_MAP_OPTION(PrecacheTextures, true)
do
{
parse.sc.MustGetString();
FTextureID tex = TexMan.CheckForTexture(parse.sc.String, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny|FTextureManager::TEXMAN_ReturnFirst);
if (!tex.isValid())
{
parse.sc.ScriptMessage("Unknown texture \"%s\"", parse.sc.String);
}
else
{
info->PrecacheTextures.Push(tex);
}
//the texture manager is not initialized here so all we can do is store the texture's name.
info->PrecacheTextures.Push(parse.sc.String);
} while (parse.sc.CheckString(","));
}
@ -1333,6 +1326,7 @@ MapFlagHandlers[] =
{ "compat_badangles", MITYPE_COMPATFLAG, 0, COMPATF2_BADANGLES },
{ "compat_floormove", MITYPE_COMPATFLAG, 0, COMPATF2_FLOORMOVE },
{ "compat_soundcutoff", MITYPE_COMPATFLAG, 0, COMPATF2_SOUNDCUTOFF },
{ "compat_pointonline", MITYPE_COMPATFLAG, 0, COMPATF2_POINTONLINE },
{ "cd_start_track", MITYPE_EATNEXT, 0, 0 },
{ "cd_end1_track", MITYPE_EATNEXT, 0, 0 },
{ "cd_end2_track", MITYPE_EATNEXT, 0, 0 },

View file

@ -236,10 +236,12 @@ bool P_GiveBody (AActor *actor, int num, int max)
return true;
}
}
else
else if (num > 0)
{
if (player->health < max)
{
num = FixedMul(num, G_SkillProperty(SKILLP_HealthFactor));
if (num < 1) num = 1;
player->health += num;
if (player->health > max)
{
@ -680,6 +682,7 @@ AInventory *AInventory::CreateCopy (AActor *other)
{
AInventory *copy;
Amount = MIN(Amount, MaxAmount);
if (GoAway ())
{
copy = static_cast<AInventory *>(Spawn (GetClass(), 0, 0, 0, NO_REPLACE));

View file

@ -15,10 +15,23 @@
#include "gstrings.h"
#include "a_action.h"
#include "thingdef/thingdef.h"
#include "v_text.h"
#define MAX_RANDOMSPAWNERS_RECURSION 32 // Should be largely more than enough, honestly.
static FRandom pr_randomspawn("RandomSpawn");
static bool IsMonster(const FDropItem *di)
{
const PClass *pclass = PClass::FindClass(di->Name);
if (NULL == pclass)
{
return false;
}
return 0 != (GetDefaultByType(pclass)->flags3 & MF3_ISMONSTER);
}
class ARandomSpawner : public AActor
{
DECLARE_CLASS (ARandomSpawner, AActor)
@ -41,7 +54,7 @@ class ARandomSpawner : public AActor
{
if (di->Name != NAME_None)
{
if (!nomonsters || !(GetDefaultByType(PClass::FindClass(di->Name))->flags3 & MF3_ISMONSTER))
if (!nomonsters || !IsMonster(di))
{
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.
@ -62,7 +75,7 @@ class ARandomSpawner : public AActor
while (n > -1 && di != NULL)
{
if (di->Name != NAME_None &&
(!nomonsters || !(GetDefaultByType(PClass::FindClass(di->Name))->flags3 & MF3_ISMONSTER)))
(!nomonsters || !IsMonster(di)))
{
n -= di->amount;
if ((di->Next != NULL) && (n > -1))
@ -106,6 +119,7 @@ class ARandomSpawner : public AActor
}
else
{
Printf(TEXTCOLOR_RED "Unknown item class %s to drop from a random spawner\n", di->Name.GetChars());
Species = NAME_None;
}
}

View file

@ -186,10 +186,12 @@ void ASkyPicker::PostBeginPlay ()
if (0 == (args[1] & 2))
{
Sector->CeilingSkyBox = box;
if (box == NULL) Sector->MoreFlags |= SECF_NOCEILINGSKYBOX; // sector should ignore the level's default skybox
}
if (0 == (args[1] & 1))
{
Sector->FloorSkyBox = box;
if (box == NULL) Sector->MoreFlags |= SECF_NOFLOORSKYBOX; // sector should ignore the level's default skybox
}
}
Destroy ();

View file

@ -134,6 +134,7 @@ DHUDMessage::DHUDMessage (FFont *font, const char *text, float x, float y, int h
NoWrap = false;
ClipX = ClipY = ClipWidth = ClipHeight = 0;
WrapWidth = 0;
HandleAspect = true;
Top = y;
Next = NULL;
Lines = NULL;
@ -196,6 +197,14 @@ void DHUDMessage::Serialize (FArchive &arc)
NoWrap = false;
ClipX = ClipY = ClipWidth = ClipHeight = WrapWidth = 0;
}
if (SaveVersion >= 4525)
{
arc << HandleAspect;
}
else
{
HandleAspect = true;
}
if (arc.IsLoading ())
{
Lines = NULL;
@ -257,7 +266,7 @@ void DHUDMessage::CalcClipCoords(int hudheight)
else
{
screen->VirtualToRealCoordsInt(x, y, w, h,
HUDWidth, hudheight, false, true);
HUDWidth, hudheight, false, HandleAspect);
ClipLeft = x;
ClipTop = y;
ClipRight = x + w;

View file

@ -94,12 +94,13 @@ public:
NoWrap = nowrap;
ResetText(SourceText);
}
void SetClipRect(int x, int y, int width, int height)
void SetClipRect(int x, int y, int width, int height, bool aspect)
{
ClipX = x;
ClipY = y;
ClipWidth = width;
ClipHeight = height;
HandleAspect = aspect;
}
void SetWrapWidth(int wrap)
{
@ -119,6 +120,7 @@ protected:
int HUDWidth, HUDHeight;
int ClipX, ClipY, ClipWidth, ClipHeight, WrapWidth; // in HUD coords
int ClipLeft, ClipTop, ClipRight, ClipBot; // in screen coords
bool HandleAspect;
EColorRange TextColor;
FFont *Font;
FRenderStyle Style;

View file

@ -1338,17 +1338,17 @@ void DBaseStatusBar::Draw (EHudState state)
{
if (Scaled)
{
y -= Scale (10, SCREENHEIGHT, 200);
y -= Scale (11, SCREENHEIGHT, 200);
}
else
{
if (SCREENWIDTH < 640)
{
y -= 11;
y -= 12;
}
else
{ // Get past the tops of the gargoyles' wings
y -= 26;
y -= 28;
}
}
}

View file

@ -83,6 +83,8 @@ void FMapInfoParser::ParseSkill ()
skill.FriendlyHealth = FRACUNIT;
skill.NoPain = false;
skill.ArmorFactor = FRACUNIT;
skill.Infighting = 0;
skill.HealthFactor = FRACUNIT;
sc.MustGetString();
skill.Name = sc.String;
@ -266,6 +268,20 @@ void FMapInfoParser::ParseSkill ()
sc.MustGetFloat();
skill.ArmorFactor = FLOAT2FIXED(sc.Float);
}
else if (sc.Compare("HealthFactor"))
{
ParseAssign();
sc.MustGetFloat();
skill.HealthFactor = FLOAT2FIXED(sc.Float);
}
else if (sc.Compare("NoInfighting"))
{
skill.Infighting = LEVEL2_NOINFIGHTING;
}
else if (sc.Compare("TotalInfighting"))
{
skill.Infighting = LEVEL2_TOTALINFIGHTING;
}
else if (sc.Compare("DefaultSkill"))
{
if (DefaultSkill >= 0)
@ -384,6 +400,17 @@ int G_SkillProperty(ESkillProperty prop)
case SKILLP_ArmorFactor:
return AllSkills[gameskill].ArmorFactor;
case SKILLP_HealthFactor:
return AllSkills[gameskill].HealthFactor;
case SKILLP_Infight:
// This property also needs to consider the level flags for the same info.
if (level.flags2 & LEVEL2_TOTALINFIGHTING) return 1;
if (level.flags2 & LEVEL2_NOINFIGHTING) return -1;
if (AllSkills[gameskill].Infighting == LEVEL2_TOTALINFIGHTING) return 1;
if (AllSkills[gameskill].Infighting == LEVEL2_NOINFIGHTING) return -1;
return infighting;
}
}
return 0;
@ -463,7 +490,9 @@ FSkillInfo &FSkillInfo::operator=(const FSkillInfo &other)
MonsterHealth = other.MonsterHealth;
FriendlyHealth = other.FriendlyHealth;
NoPain = other.NoPain;
Infighting = other.Infighting;
ArmorFactor = other.ArmorFactor;
HealthFactor = other.HealthFactor;
return *this;
}

View file

@ -385,6 +385,11 @@ FListMenuItemStaticPatch::FListMenuItemStaticPatch(int x, int y, FTextureID patc
void FListMenuItemStaticPatch::Drawer(bool selected)
{
if (!mTexture.Exists())
{
return;
}
int x = mXpos;
FTexture *tex = TexMan(mTexture);
if (mYpos >= 0)
@ -486,7 +491,7 @@ bool FListMenuItemSelectable::MouseEvent(int type, int x, int y)
{
if (type == DMenu::MOUSE_Release)
{
if (DMenu::CurrentMenu->MenuEvent(MKEY_Enter, true))
if (NULL != DMenu::CurrentMenu && DMenu::CurrentMenu->MenuEvent(MKEY_Enter, true))
{
return true;
}

View file

@ -95,6 +95,18 @@ static void DeinitMenus()
ClearSaveGames();
}
static FTextureID GetMenuTexture(const char* const name)
{
const FTextureID texture = TexMan.CheckForTexture(name, FTexture::TEX_MiscPatch);
if (!texture.Exists())
{
Printf("Missing menu texture: \"%s\"\n", name);
}
return texture;
}
//=============================================================================
//
//
@ -235,7 +247,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
else if (sc.Compare("Selector"))
{
sc.MustGetString();
desc->mSelector = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch);
desc->mSelector = GetMenuTexture(sc.String);
sc.MustGetStringName(",");
sc.MustGetNumber();
desc->mSelectOfsX = sc.Number;
@ -278,7 +290,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
int y = sc.Number;
sc.MustGetStringName(",");
sc.MustGetString();
FTextureID tex = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch);
FTextureID tex = GetMenuTexture(sc.String);
FListMenuItem *it = new FListMenuItemStaticPatch(x, y, tex, centered);
desc->mItems.Push(it);
@ -299,7 +311,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
else if (sc.Compare("PatchItem"))
{
sc.MustGetString();
FTextureID tex = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch);
FTextureID tex = GetMenuTexture(sc.String);
sc.MustGetStringName(",");
sc.MustGetString();
int hotkey = sc.String[0];
@ -1045,7 +1057,7 @@ static void BuildEpisodeMenu()
FListMenuItem *it;
if (AllEpisodes[i].mPicName.IsNotEmpty())
{
FTextureID tex = TexMan.CheckForTexture(AllEpisodes[i].mPicName, FTexture::TEX_MiscPatch);
FTextureID tex = GetMenuTexture(AllEpisodes[i].mPicName);
it = new FListMenuItemPatch(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut,
tex, NAME_Skillmenu, i);
}
@ -1442,7 +1454,7 @@ void M_StartupSkillMenu(FGameStartup *gs)
if (skill.PicName.Len() != 0 && pItemText == NULL)
{
FTextureID tex = TexMan.CheckForTexture(skill.PicName, FTexture::TEX_MiscPatch);
FTextureID tex = GetMenuTexture(skill.PicName);
li = new FListMenuItemPatch(ld->mXpos, y, ld->mLinespacing, skill.Shortcut, tex, action, i);
}
else

View file

@ -1045,6 +1045,19 @@ public:
return text;
}
int Draw(FOptionMenuDescriptor*desc, int y, int indent, bool selected)
{
if (mEntering)
{
// reposition the text so that the cursor is visible when in entering mode.
FString text = Represent();
int tlen = SmallFont->StringWidth(text) * CleanXfac_1;
int newindent = screen->GetWidth() - tlen - CURSORSPACE;
if (newindent < indent) indent = newindent;
}
return FOptionMenuFieldBase::Draw(desc, y, indent, selected);
}
bool MenuEvent ( int mkey, bool fromcontroller )
{
if ( mkey == MKEY_Enter )

View file

@ -396,6 +396,7 @@ xx(Roll)
xx(Scale)
xx(ScaleX)
xx(ScaleY)
xx(Floatbobphase)
xx(Blocking)
xx(Blockmonsters)

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2013-2014 Nuke.YKT
* Copyright (C) 2013-2015 Nuke.YKT(Alexey Khokholov)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -27,53 +27,31 @@
OPL2 ROMs.
*/
//version 1.5
//version 1.6
/* Changelog:
v1.1:
Vibrato's sign fix
Vibrato's sign fix.
v1.2:
Operator key fix
Corrected 4-operator mode
Corrected rhythm mode
Some small fixes
v1.2.1:
Small envelope generator fix
Removed EX_Get function(not used)
v1.3:
Complete rewrite
(Not released)
v1.4:
New envelope and waveform generator
Operator key fix.
Corrected 4-operator mode.
Corrected rhythm mode.
Some small fixes.
v1.2.1:
Small envelope generator fix.
v1.3:
Complete rewrite.
v1.4:
New envelope and waveform generator.
Some small fixes.
(Not released)
v1.4.1:
Envelope generator rate calculation fix
(Not released)
Envelope generator rate calculation fix.
v1.4.2:
Version for ZDoom.
v1.5:
Optimizations
*/
/* Verified:
Noise generator.
Waveform generator.
Envelope generator increase table.
Tremolo.
*/
/* TODO:
Verify:
kslrom[15] value(is it 128?).
Sustain level = 15.
Vibrato, Phase generator.
Rhythm part.
Envelope generator state switching(decay->sustain when egt = 1 and decay->release).
Feedback.
Register write.
4-operator.
Optimizations.
v1.6:
Improved emulation output.
*/
#include <stdlib.h>
@ -216,19 +194,17 @@ envelope_sinfunc envelope_sin[8] = {
};
void envelope_gen_off(opl_slot *slott);
void envelope_gen_change(opl_slot *slott);
void envelope_gen_attack(opl_slot *slott);
void envelope_gen_decay(opl_slot *slott);
void envelope_gen_sustain(opl_slot *slott);
void envelope_gen_release(opl_slot *slott);
envelope_genfunc envelope_gen[6] = {
envelope_genfunc envelope_gen[5] = {
envelope_gen_off,
envelope_gen_attack,
envelope_gen_decay,
envelope_gen_sustain,
envelope_gen_release,
envelope_gen_change
envelope_gen_release
};
enum envelope_gen_num {
@ -252,7 +228,7 @@ Bit8u envelope_calc_rate(opl_slot *slot, Bit8u reg_rate) {
}
void envelope_update_ksl(opl_slot *slot) {
Bit16s ksl = (kslrom[slot->channel->f_num >> 6] << 1) - ((slot->channel->block ^ 0x07) << 5) - 0x20;
Bit16s ksl = (kslrom[slot->channel->f_num >> 6] << 2) - ((0x08 - slot->channel->block) << 5);
if (ksl < 0) {
ksl = 0;
}
@ -281,28 +257,25 @@ void envelope_gen_off(opl_slot *slot) {
slot->eg_rout = 0x1ff;
}
void envelope_gen_change(opl_slot *slot) {
slot->eg_gen = slot->eg_gennext;
envelope_update_rate(slot);
}
void envelope_gen_attack(opl_slot *slot) {
if (slot->eg_rout == 0x00) {
slot->eg_gen = envelope_gen_num_decay;
envelope_update_rate(slot);
return;
}
slot->eg_rout += ((~slot->eg_rout) *slot->eg_inc) >> 3;
if (slot->eg_rout < 0x00) {
slot->eg_rout = 0x00;
}
if (!slot->eg_rout) {
slot->eg_gen = envelope_gen_num_change;
slot->eg_gennext = envelope_gen_num_decay;
}
}
void envelope_gen_decay(opl_slot *slot) {
slot->eg_rout += slot->eg_inc;
if (slot->eg_rout >= slot->reg_sl << 4) {
slot->eg_gen = envelope_gen_num_change;
slot->eg_gennext = envelope_gen_num_sustain;
slot->eg_gen = envelope_gen_num_sustain;
envelope_update_rate(slot);
return;
}
slot->eg_rout += slot->eg_inc;
}
void envelope_gen_sustain(opl_slot *slot) {
@ -312,11 +285,13 @@ void envelope_gen_sustain(opl_slot *slot) {
}
void envelope_gen_release(opl_slot *slot) {
slot->eg_rout += slot->eg_inc;
if (slot->eg_rout >= 0x1ff) {
slot->eg_gen = envelope_gen_num_change;
slot->eg_gennext = envelope_gen_num_off;
slot->eg_gen = envelope_gen_num_off;
slot->eg_rout = 0x1ff;
envelope_update_rate(slot);
return;
}
slot->eg_rout += slot->eg_inc;
}
void envelope_calc(opl_slot *slot) {
@ -324,10 +299,7 @@ void envelope_calc(opl_slot *slot) {
rate_h = slot->eg_rate >> 2;
rate_l = slot->eg_rate & 3;
Bit8u inc = 0;
if (slot->eg_gen == envelope_gen_num_attack && rate_h == 0x0f) {
inc = 8;
}
else if (eg_incsh[rate_h] > 0) {
if (eg_incsh[rate_h] > 0) {
if ((slot->chip->timer & ((1 << eg_incsh[rate_h]) - 1)) == 0) {
inc = eg_incstep[eg_incdesc[rate_h]][rate_l][((slot->chip->timer) >> eg_incsh[rate_h]) & 0x07];
}
@ -336,14 +308,19 @@ void envelope_calc(opl_slot *slot) {
inc = eg_incstep[eg_incdesc[rate_h]][rate_l][slot->chip->timer & 0x07] << (-eg_incsh[rate_h]);
}
slot->eg_inc = inc;
envelope_gen[slot->eg_gen](slot);
slot->eg_out = slot->eg_rout + (slot->reg_tl << 2) + (slot->eg_ksl >> kslshift[slot->reg_ksl]) + *slot->trem;
envelope_gen[slot->eg_gen](slot);
}
void eg_keyon(opl_slot *slot, Bit8u type) {
if (!slot->key) {
slot->eg_gen = envelope_gen_num_change;
slot->eg_gennext = envelope_gen_num_attack;
slot->eg_gen = envelope_gen_num_attack;
envelope_update_rate(slot);
if ((slot->eg_rate >> 2) == 0x0f) {
slot->eg_gen = envelope_gen_num_decay;
envelope_update_rate(slot);
slot->eg_rout = 0x00;
}
slot->pg_phase = 0x00;
}
slot->key |= type;
@ -353,8 +330,8 @@ void eg_keyoff(opl_slot *slot, Bit8u type) {
if (slot->key) {
slot->key &= (~type);
if (!slot->key) {
slot->eg_gen = envelope_gen_num_change;
slot->eg_gennext = envelope_gen_num_release;
slot->eg_gen = envelope_gen_num_release;
envelope_update_rate(slot);
}
}
}
@ -366,7 +343,7 @@ void eg_keyoff(opl_slot *slot, Bit8u type) {
void pg_generate(opl_slot *slot) {
Bit16u f_num = slot->channel->f_num;
if (slot->reg_vib) {
Bit8u f_num_high = f_num >> (7 + vib_table[(slot->chip->timer >> 10)&0x07] + (0x01 - slot->chip->dvb));
Bit8u f_num_high = f_num >> (7 + vib_table[(slot->chip->timer >> 10) & 0x07] + (0x01 - slot->chip->dvb));
f_num += f_num_high * vibsgn_table[(slot->chip->timer >> 10) & 0x07];
}
slot->pg_phase += (((f_num << slot->channel->block) >> 1) * mt[slot->reg_mult]) >> 1;
@ -387,7 +364,7 @@ void n_generate(opl_chip *chip) {
// Slot
//
void slot_write20(opl_slot *slot,Bit8u data) {
void slot_write20(opl_slot *slot, Bit8u data) {
if ((data >> 7) & 0x01) {
slot->trem = &slot->chip->tremval;
}
@ -434,14 +411,14 @@ void slot_generatephase(opl_slot *slot, Bit16u phase) {
}
void slot_generate(opl_slot *slot) {
slot->out = envelope_sin[slot->reg_wf]((slot->pg_phase >> 9) + (*slot->mod), slot->eg_out);
slot->out = envelope_sin[slot->reg_wf]((Bit16u)(slot->pg_phase >> 9) + (*slot->mod), slot->eg_out);
}
void slot_generatezm(opl_slot *slot) {
slot->out = envelope_sin[slot->reg_wf]((slot->pg_phase >> 9), slot->eg_out);
slot->out = envelope_sin[slot->reg_wf]((Bit16u)(slot->pg_phase >> 9), slot->eg_out);
}
void slot_calgfb(opl_slot *slot) {
void slot_calcfb(opl_slot *slot) {
slot->prout[1] = slot->prout[0];
slot->prout[0] = slot->out;
if (slot->channel->fb != 0x00) {
@ -461,57 +438,61 @@ void chan_setupalg(opl_channel *channel);
void chan_updaterhythm(opl_chip *chip, Bit8u data) {
chip->rhy = data & 0x3f;
if (chip->rhy & 0x20) {
chip->channel[6].out[0] = &chip->slot[13].out;
chip->channel[6].out[1] = &chip->slot[13].out;
chip->channel[6].out[2] = &chip->zeromod;
chip->channel[6].out[3] = &chip->zeromod;
chip->channel[7].out[0] = &chip->slot[14].out;
chip->channel[7].out[1] = &chip->slot[14].out;
chip->channel[7].out[2] = &chip->slot[15].out;
chip->channel[7].out[3] = &chip->slot[15].out;
chip->channel[8].out[0] = &chip->slot[16].out;
chip->channel[8].out[1] = &chip->slot[16].out;
chip->channel[8].out[2] = &chip->slot[17].out;
chip->channel[8].out[3] = &chip->slot[17].out;
opl_channel *channel6 = &chip->channel[6];
opl_channel *channel7 = &chip->channel[7];
opl_channel *channel8 = &chip->channel[8];
channel6->out[0] = &channel6->slots[1]->out;
channel6->out[1] = &channel6->slots[1]->out;
channel6->out[2] = &chip->zeromod;
channel6->out[3] = &chip->zeromod;
channel7->out[0] = &channel7->slots[0]->out;
channel7->out[1] = &channel7->slots[0]->out;
channel7->out[2] = &channel7->slots[1]->out;
channel7->out[3] = &channel7->slots[1]->out;
channel8->out[0] = &channel8->slots[0]->out;
channel8->out[1] = &channel8->slots[0]->out;
channel8->out[2] = &channel8->slots[1]->out;
channel8->out[3] = &channel8->slots[1]->out;
for (Bit8u chnum = 6; chnum < 9; chnum++) {
chip->channel[chnum].chtype = ch_drum;
}
chan_setupalg(channel6);
//hh
if (chip->rhy & 0x01) {
eg_keyon(&chip->slot[14], egk_drum);
eg_keyon(channel7->slots[0], egk_drum);
}
else {
eg_keyoff(&chip->slot[14], egk_drum);
eg_keyoff(channel7->slots[0], egk_drum);
}
//tc
if (chip->rhy & 0x02) {
eg_keyon(&chip->slot[17], egk_drum);
eg_keyon(channel8->slots[1], egk_drum);
}
else {
eg_keyoff(&chip->slot[17], egk_drum);
eg_keyoff(channel8->slots[1], egk_drum);
}
//tom
if (chip->rhy & 0x04) {
eg_keyon(&chip->slot[16], egk_drum);
eg_keyon(channel8->slots[0], egk_drum);
}
else {
eg_keyoff(&chip->slot[16], egk_drum);
eg_keyoff(channel8->slots[0], egk_drum);
}
//sd
if (chip->rhy & 0x08) {
eg_keyon(&chip->slot[15], egk_drum);
eg_keyon(channel7->slots[1], egk_drum);
}
else {
eg_keyoff(&chip->slot[15], egk_drum);
eg_keyoff(channel7->slots[1], egk_drum);
}
//bd
if (chip->rhy & 0x10) {
eg_keyon(&chip->slot[12], egk_drum);
eg_keyon(&chip->slot[13], egk_drum);
eg_keyon(channel6->slots[0], egk_drum);
eg_keyon(channel6->slots[1], egk_drum);
}
else {
eg_keyoff(&chip->slot[12], egk_drum);
eg_keyoff(&chip->slot[13], egk_drum);
eg_keyoff(channel6->slots[0], egk_drum);
eg_keyoff(channel6->slots[1], egk_drum);
}
}
else {
@ -566,6 +547,16 @@ void chan_writeb0(opl_channel *channel, Bit8u data) {
void chan_setupalg(opl_channel *channel) {
if (channel->chtype == ch_drum) {
switch (channel->alg & 0x01) {
case 0x00:
channel->slots[0]->mod = &channel->slots[0]->fbmod;
channel->slots[1]->mod = &channel->slots[0]->out;
break;
case 0x01:
channel->slots[0]->mod = &channel->slots[0]->fbmod;
channel->slots[1]->mod = &channel->chip->zeromod;
break;
}
return;
}
if (channel->alg & 0x08) {
@ -672,49 +663,39 @@ void chan_writec0(opl_channel *channel, Bit8u data) {
}
}
void chan_generaterhythm(opl_chip *chip) {
if (chip->rhy & 0x20) {
opl_channel *channel6 = &chip->channel[6];
opl_channel *channel7 = &chip->channel[7];
opl_channel *channel8 = &chip->channel[8];
slot_generate(channel6->slots[0]);
slot_generate(channel6->slots[1]);
Bit16u phase14 = channel7->slots[0]->pg_phase & 0x3ff;
Bit16u phase17 = channel8->slots[1]->pg_phase & 0x3ff;
Bit16u phase = 0x00;
//hh tc phase bit
Bit16u phasebit = ((phase14 & 0x08) | (((phase14 >> 5) ^ phase14) & 0x04) | (((phase17 >> 2) ^ phase17) & 0x08)) ? 0x01 : 0x00;
//hh
phase = (phasebit << 9) | (0x34 << ((phasebit ^ (chip->noise & 0x01) << 1)));
slot_generatephase(channel7->slots[0], phase);
//sd
phase = (0x100 << ((phase14 >> 8) & 0x01)) ^ ((chip->noise & 0x01) << 8);
slot_generatephase(channel7->slots[1], phase);
//tt
slot_generatezm(channel8->slots[0]);
//tc
phase = 0x100 | (phasebit << 9);
slot_generatephase(channel8->slots[1], phase);
}
void chan_generaterhythm1(opl_chip *chip) {
opl_channel *channel6 = &chip->channel[6];
opl_channel *channel7 = &chip->channel[7];
opl_channel *channel8 = &chip->channel[8];
slot_generate(channel6->slots[0]);
Bit16u phase14 = (channel7->slots[0]->pg_phase >> 9) & 0x3ff;
Bit16u phase17 = (channel8->slots[1]->pg_phase >> 9) & 0x3ff;
Bit16u phase = 0x00;
//hh tc phase bit
Bit16u phasebit = ((phase14 & 0x08) | (((phase14 >> 5) ^ phase14) & 0x04) | (((phase17 >> 2) ^ phase17) & 0x08)) ? 0x01 : 0x00;
//hh
phase = (phasebit << 9) | (0x34 << ((phasebit ^ (chip->noise & 0x01) << 1)));
slot_generatephase(channel7->slots[0], phase);
//tt
slot_generatezm(channel8->slots[0]);
}
void chan_generate(opl_channel *channel) {
if (channel->chtype == ch_drum) {
return;
}
if (channel->alg & 0x08) {
return;
}
if (channel->alg & 0x04) {
slot_generate(channel->pair->slots[0]);
slot_generate(channel->pair->slots[1]);
slot_generate(channel->slots[0]);
slot_generate(channel->slots[1]);
}
else {
slot_generate(channel->slots[0]);
slot_generate(channel->slots[1]);
}
void chan_generaterhythm2(opl_chip *chip) {
opl_channel *channel6 = &chip->channel[6];
opl_channel *channel7 = &chip->channel[7];
opl_channel *channel8 = &chip->channel[8];
slot_generate(channel6->slots[1]);
Bit16u phase14 = (channel7->slots[0]->pg_phase >> 9) & 0x3ff;
Bit16u phase17 = (channel8->slots[1]->pg_phase >> 9) & 0x3ff;
Bit16u phase = 0x00;
//hh tc phase bit
Bit16u phasebit = ((phase14 & 0x08) | (((phase14 >> 5) ^ phase14) & 0x04) | (((phase17 >> 2) ^ phase17) & 0x08)) ? 0x01 : 0x00;
//sd
phase = (0x100 << ((phase14 >> 8) & 0x01)) ^ ((chip->noise & 0x01) << 8);
slot_generatephase(channel7->slots[1], phase);
//tc
phase = 0x100 | (phasebit << 9);
slot_generatephase(channel8->slots[1], phase);
}
void chan_enable(opl_channel *channel) {
@ -782,21 +763,132 @@ Bit16s limshort(Bit32s a) {
return (Bit16s)a;
}
void chip_generate(opl_chip *chip, Bit16s *buff) {
buff[1] = limshort(chip->mixbuff[1]);
for (Bit8u ii = 0; ii < 12; ii++) {
slot_calcfb(&chip->slot[ii]);
pg_generate(&chip->slot[ii]);
envelope_calc(&chip->slot[ii]);
slot_generate(&chip->slot[ii]);
}
for (Bit8u ii = 12; ii < 15; ii++) {
slot_calcfb(&chip->slot[ii]);
pg_generate(&chip->slot[ii]);
envelope_calc(&chip->slot[ii]);
}
if (chip->rhy & 0x20) {
chan_generaterhythm1(chip);
}
else {
slot_generate(&chip->slot[12]);
slot_generate(&chip->slot[13]);
slot_generate(&chip->slot[14]);
}
chip->mixbuff[0] = 0;
for (Bit8u ii = 0; ii < 18; ii++) {
Bit16s accm = 0;
for (Bit8u jj = 0; jj < 4; jj++) {
accm += *chip->channel[ii].out[jj];
}
if (chip->FullPan) {
chip->mixbuff[0] += (Bit16s)(accm * chip->channel[ii].fcha);
}
else {
chip->mixbuff[0] += (Bit16s)(accm & chip->channel[ii].cha);
}
}
for (Bit8u ii = 15; ii < 18; ii++) {
slot_calcfb(&chip->slot[ii]);
pg_generate(&chip->slot[ii]);
envelope_calc(&chip->slot[ii]);
}
if (chip->rhy & 0x20) {
chan_generaterhythm2(chip);
}
else {
slot_generate(&chip->slot[15]);
slot_generate(&chip->slot[16]);
slot_generate(&chip->slot[17]);
}
buff[0] = limshort(chip->mixbuff[0]);
for (Bit8u ii = 18; ii < 33; ii++) {
slot_calcfb(&chip->slot[ii]);
pg_generate(&chip->slot[ii]);
envelope_calc(&chip->slot[ii]);
slot_generate(&chip->slot[ii]);
}
chip->mixbuff[1] = 0;
for (Bit8u ii = 0; ii < 18; ii++) {
Bit16s accm = 0;
for (Bit8u jj = 0; jj < 4; jj++) {
accm += *chip->channel[ii].out[jj];
}
if (chip->FullPan) {
chip->mixbuff[1] += (Bit16s)(accm * chip->channel[ii].fchb);
}
else {
chip->mixbuff[1] += (Bit16s)(accm & chip->channel[ii].chb);
}
}
for (Bit8u ii = 33; ii < 36; ii++) {
slot_calcfb(&chip->slot[ii]);
pg_generate(&chip->slot[ii]);
envelope_calc(&chip->slot[ii]);
slot_generate(&chip->slot[ii]);
}
n_generate(chip);
if ((chip->timer & 0x3f) == 0x3f) {
if (!chip->tremdir) {
if (chip->tremtval == 105) {
chip->tremtval--;
chip->tremdir = 1;
}
else {
chip->tremtval++;
}
}
else {
if (chip->tremtval == 0) {
chip->tremtval++;
chip->tremdir = 0;
}
else {
chip->tremtval--;
}
}
chip->tremval = (chip->tremtval >> 2) >> ((1 - chip->dam) << 1);
}
chip->timer++;
}
void NukedOPL3::Reset() {
memset(&opl3, 0, sizeof(opl_chip));
for (Bit8u slotnum = 0; slotnum < 36; slotnum++) {
opl3.slot[slotnum].channel = &opl3.channel[slotnum / 2];
opl3.slot[slotnum].chip = &opl3;
opl3.slot[slotnum].mod = &opl3.zeromod;
opl3.slot[slotnum].eg_rout = 0x1ff;
opl3.slot[slotnum].eg_out = 0x1ff;
opl3.slot[slotnum].eg_gen = envelope_gen_num_off;
opl3.slot[slotnum].eg_gennext = envelope_gen_num_off;
opl3.slot[slotnum].trem = (Bit8u*)&opl3.zeromod;
}
for (Bit8u channum = 0; channum < 18; channum++) {
opl3.channel[channum].slots[0] = &opl3.slot[2 * channum];
opl3.channel[channum].slots[1] = &opl3.slot[2 * channum + 1];
opl3.channel[channum].slots[0] = &opl3.slot[ch_slot[channum]];
opl3.channel[channum].slots[1] = &opl3.slot[ch_slot[channum] + 3];
opl3.slot[ch_slot[channum]].channel = &opl3.channel[channum];
opl3.slot[ch_slot[channum] + 3].channel = &opl3.channel[channum];
if ((channum % 9) < 3) {
opl3.channel[channum].pair = &opl3.channel[channum + 3];
}
@ -816,6 +908,8 @@ void NukedOPL3::Reset() {
chan_setupalg(&opl3.channel[channum]);
}
opl3.noise = 0x306600;
opl3.timer = 0;
opl3.FullPan = FullPan;
}
void NukedOPL3::WriteReg(int reg, int v) {
@ -903,58 +997,11 @@ void NukedOPL3::WriteReg(int reg, int v) {
}
void NukedOPL3::Update(float* sndptr, int numsamples) {
Bit32s outa, outb;
Bit16s buffer[2];
for (Bit32u i = 0; i < (Bit32u)numsamples; i++) {
outa = 0;
outb = 0;
for (Bit8u ii = 0; ii < 36; ii++) {
slot_calgfb(&opl3.slot[ii]);
}
chan_generaterhythm(&opl3);
for (Bit8u ii = 0; ii < 18; ii++) {
chan_generate(&opl3.channel[ii]);
Bit16s accm = 0;
for (Bit8u jj = 0; jj < 4; jj++) {
accm += *opl3.channel[ii].out[jj];
}
if (FullPan) {
outa += (Bit16s)(accm * opl3.channel[ii].fcha);
outb += (Bit16s)(accm * opl3.channel[ii].fchb);
}
else {
outa += (Bit16s)(accm & opl3.channel[ii].cha);
outb += (Bit16s)(accm & opl3.channel[ii].chb);
}
}
for (Bit8u ii = 0; ii < 36; ii++) {
envelope_calc(&opl3.slot[ii]);
pg_generate(&opl3.slot[ii]);
}
n_generate(&opl3);
opl3.timer++;
if (!(opl3.timer & 0x3f)) {
if (!opl3.tremdir) {
if (opl3.tremtval == 105) {
opl3.tremtval--;
opl3.tremdir = 1;
}
else {
opl3.tremtval++;
}
}
else {
if (opl3.tremtval == 0) {
opl3.tremtval++;
opl3.tremdir = 0;
}
else {
opl3.tremtval--;
}
}
opl3.tremval = (opl3.tremtval >> 2) >> ((1 - opl3.dam) << 1);
}
*sndptr++ += (float)(outa / 10240.0);
*sndptr++ += (float)(outb / 10240.0);
chip_generate(&opl3, buffer);
*sndptr++ += (float)(buffer[0] / 10240.0);
*sndptr++ += (float)(buffer[1] / 10240.0);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2013-2014 Nuke.YKT
* Copyright (C) 2013-2015 Nuke.YKT(Alexey Khokholov)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -27,7 +27,7 @@
OPL2 ROMs.
*/
//version 1.5
//version 1.6
#include "opl.h"
#include "muslib.h"
@ -116,7 +116,7 @@ static const Bit8u mt[16] = { 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24,
// ksl table
//
static const Bit8u kslrom[16] = { 0, 64, 80, 90, 96, 102, 106, 110, 112, 116, 118, 120, 122, 124, 126, 127 };
static const Bit8u kslrom[16] = { 0, 32, 40, 45, 48, 51, 53, 55, 56, 58, 59, 60, 61, 62, 63, 64 };
static const Bit8u kslshift[4] = { 8, 1, 2, 0 };
@ -133,7 +133,7 @@ static const Bit8s vibsgn_table[8] = { 1, 1, 1, 1, -1, -1, -1, -1 };
static const Bit8u eg_incstep[3][4][8] = {
{ { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 } },
{ { 0, 1, 0, 1, 0, 1, 0, 1 }, { 1, 1, 0, 1, 0, 1, 0, 1 }, { 1, 1, 0, 1, 1, 1, 0, 1 }, { 1, 1, 1, 1, 1, 1, 0, 1 } },
{ { 0, 1, 0, 1, 0, 1, 0, 1 }, { 0, 1, 0, 1, 1, 1, 0, 1 }, { 0, 1, 1, 1, 0, 1, 1, 1 }, { 0, 1, 1, 1, 1, 1, 1, 1 } },
{ { 1, 1, 1, 1, 1, 1, 1, 1 }, { 2, 2, 1, 1, 1, 1, 1, 1 }, { 2, 2, 1, 1, 2, 2, 1, 1 }, { 2, 2, 2, 2, 2, 2, 1, 1 } }
};
@ -149,8 +149,8 @@ static const Bit8s eg_incsh[16] = {
// address decoding
//
static const Bit8s ad_slot[0x20] = { 0, 2, 4, 1, 3, 5, -1, -1, 6, 8, 10, 7, 9, 11, -1, -1, 12, 14, 16, 13, 15, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
static const Bit8s ad_slot[0x20] = { 0, 1, 2, 3, 4, 5, -1, -1, 6, 7, 8, 9, 10, 11, -1, -1, 12, 13, 14, 15, 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
static const Bit8u ch_slot[18] = { 0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20, 24, 25, 26, 30, 31, 32 };
struct opl_chip;
struct opl_slot;
@ -167,7 +167,6 @@ struct opl_slot {
Bit16s eg_out;
Bit8u eg_inc;
Bit8u eg_gen;
Bit8u eg_gennext;
Bit8u eg_rate;
Bit8u eg_ksl;
Bit8u *trem;
@ -217,6 +216,8 @@ struct opl_chip {
Bit8u tremdir;
Bit32u noise;
Bit16s zeromod;
Bit32s mixbuff[2];
Bit8u FullPan;
};

View file

@ -75,6 +75,7 @@
#include "actorptrselect.h"
#include "farchive.h"
#include "decallib.h"
#include "version.h"
#include "g_shared/a_pickups.h"
@ -132,6 +133,16 @@ enum
ARMORINFO_ACTUALSAVEAMOUNT,
};
// PickActor
// [JP] I've renamed these flags to something else to avoid confusion with the other PAF_ flags
enum
{
// PAF_FORCETID,
// PAF_RETURNTID
PICKAF_FORCETID = 1,
PICKAF_RETURNTID = 2,
};
struct CallReturn
{
CallReturn(int pc, ScriptFunction *func, FBehavior *module, SDWORD *locals, ACSLocalArrays *arrays, bool discard, unsigned int runaway)
@ -1253,7 +1264,7 @@ static int UseInventory (AActor *activator, const char *type)
//
//============================================================================
static int CheckInventory (AActor *activator, const char *type)
static int CheckInventory (AActor *activator, const char *type, bool max)
{
if (activator == NULL || type == NULL)
return 0;
@ -1264,11 +1275,26 @@ static int CheckInventory (AActor *activator, const char *type)
}
else if (stricmp (type, "Health") == 0)
{
if (max)
{
if (activator->IsKindOf (RUNTIME_CLASS (APlayerPawn)))
return static_cast<APlayerPawn *>(activator)->MaxHealth;
else
return activator->SpawnHealth();
}
return activator->health;
}
const PClass *info = PClass::FindClass (type);
AInventory *item = activator->FindInventory (info);
if (max)
{
if (item)
return item->MaxAmount;
else
return ((AInventory *)GetDefaultByType (info))->MaxAmount;
}
return item ? item->Amount : 0;
}
@ -1417,7 +1443,7 @@ FBehavior *FBehavior::StaticLoadModule (int lumpnum, FileReader *fr, int len)
else
{
delete behavior;
Printf(TEXTCOLOR_RED "%s: invalid ACS module", Wads.GetLumpFullName(lumpnum));
Printf(TEXTCOLOR_RED "%s: invalid ACS module\n", Wads.GetLumpFullName(lumpnum));
return NULL;
}
}
@ -3364,6 +3390,14 @@ int DLevelScript::DoSpawn (int type, fixed_t x, fixed_t y, fixed_t z, int tid, i
if (info != NULL)
{
info = info->GetReplacement ();
if ((GetDefaultByType (info)->flags3 & MF3_ISMONSTER) &&
((dmflags & DF_NO_MONSTERS) || (level.flags2 & LEVEL2_NOMONSTERS)))
{
return 0;
}
actor = Spawn (info, x, y, z, ALLOW_REPLACE);
if (actor != NULL)
{
@ -4423,6 +4457,7 @@ enum EACSFunctions
ACSF_GetActorRoll,
ACSF_QuakeEx,
ACSF_Warp, // 92
ACSF_GetMaxInventory,
/* Zandronum's - these must be skipped when we reach 99!
-100:ResetMap(0),
@ -5296,6 +5331,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const
ClipRectWidth = argCount > 2 ? args[2] : 0;
ClipRectHeight = argCount > 3 ? args[3] : 0;
WrapWidth = argCount > 4 ? args[4] : 0;
HandleAspect = argCount > 5 ? !!args[5] : true;
break;
case ACSF_SetHUDWrapWidth:
@ -5760,9 +5796,9 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
return 0;
}
DWORD actorMask = MF_SHOOTABLE;
ActorFlags actorMask = MF_SHOOTABLE;
if (argCount >= 6) {
actorMask = args[5];
actorMask = ActorFlags::FromInt(args[5]);
}
DWORD wallMask = ML_BLOCKEVERYTHING | ML_BLOCKHITSCAN;
@ -5770,11 +5806,10 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
wallMask = args[6];
}
bool forceTID = 0;
int flags = 0;
if (argCount >= 8)
{
if (args[7] != 0)
forceTID = 1;
flags = args[7];
}
AActor* pickedActor = P_LinePickActor(actor, args[1] << 16, args[3], args[2] << 16, actorMask, wallMask);
@ -5782,15 +5817,19 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
return 0;
}
if (!(forceTID) && (args[4] == 0) && (pickedActor->tid == 0))
if (!(flags & PICKAF_FORCETID) && (args[4] == 0) && (pickedActor->tid == 0))
return 0;
if ((pickedActor->tid == 0) || (forceTID))
if ((pickedActor->tid == 0) || (flags & PICKAF_FORCETID))
{
pickedActor->RemoveFromHash();
pickedActor->tid = args[4];
pickedActor->AddToHash();
}
if (flags & PICKAF_RETURNTID)
{
return pickedActor->tid;
}
return 1;
}
break;
@ -5863,6 +5902,8 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
const char *statename = argCount > 6 ? FBehavior::StaticLookupString(args[6]) : "";
bool exact = argCount > 7 ? !!args[7] : false;
fixed_t heightoffset = argCount > 8 ? args[8] : 0;
fixed_t radiusoffset = argCount > 9 ? args[9] : 0;
fixed_t pitch = argCount > 10 ? args[10] : 0;
FState *state = argCount > 6 ? activator->GetClass()->ActorInfo->FindStateByString(statename, exact) : 0;
@ -5880,7 +5921,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
if (!reference)
return false;
if (P_Thing_Warp(activator, reference, xofs, yofs, zofs, angle, flags, heightoffset))
if (P_Thing_Warp(activator, reference, xofs, yofs, zofs, angle, flags, heightoffset, radiusoffset, pitch))
{
if (state && argCount > 6)
{
@ -5890,11 +5931,19 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
}
return false;
}
case ACSF_GetMaxInventory:
actor = SingleActorFromTID(args[0], activator);
if (actor != NULL)
{
return CheckInventory(actor, FBehavior::StaticLookupString(args[1]), true);
}
break;
default:
break;
}
return 0;
}
@ -6032,6 +6081,7 @@ int DLevelScript::RunScript ()
int sp = 0;
int *pc = this->pc;
ACSFormat fmt = activeBehavior->GetFormat();
FBehavior* const savedActiveBehavior = activeBehavior;
unsigned int runaway = 0; // used to prevent infinite loops
int pcd;
FString work;
@ -6065,6 +6115,7 @@ int DLevelScript::RunScript ()
{
default:
Printf ("Unknown P-Code %d in %s\n", pcd, ScriptPresentation(script).GetChars());
activeBehavior = savedActiveBehavior;
// fall through
case PCD_TERMINATE:
DPrintf ("%s finished\n", ScriptPresentation(script).GetChars());
@ -7271,9 +7322,9 @@ int DLevelScript::RunScript ()
sp--;
break;
case PCD_DROP:
case PCD_SETRESULTVALUE:
resultValue = STACK(1);
case PCD_DROP: //fall through.
sp--;
break;
@ -7828,7 +7879,7 @@ scriptwait:
}
break;
}
msg->SetClipRect(ClipRectLeft, ClipRectTop, ClipRectWidth, ClipRectHeight);
msg->SetClipRect(ClipRectLeft, ClipRectTop, ClipRectWidth, ClipRectHeight, HandleAspect);
if (WrapWidth != 0)
{
msg->SetWrapWidth(WrapWidth);
@ -8311,17 +8362,17 @@ scriptwait:
break;
case PCD_CHECKINVENTORY:
STACK(1) = CheckInventory (activator, FBehavior::StaticLookupString (STACK(1)));
STACK(1) = CheckInventory (activator, FBehavior::StaticLookupString (STACK(1)), false);
break;
case PCD_CHECKACTORINVENTORY:
STACK(2) = CheckInventory (SingleActorFromTID(STACK(2), NULL),
FBehavior::StaticLookupString (STACK(1)));
FBehavior::StaticLookupString (STACK(1)), false);
sp--;
break;
case PCD_CHECKINVENTORYDIRECT:
PushToStack (CheckInventory (activator, FBehavior::StaticLookupString (TAGSTR(uallong(pc[0])))));
PushToStack (CheckInventory (activator, FBehavior::StaticLookupString (TAGSTR(uallong(pc[0]))), false));
pc += 1;
break;
@ -9355,6 +9406,10 @@ scriptwait:
}
break;
case PCD_CONSOLECOMMAND:
Printf (TEXTCOLOR_RED GAMENAME " doesn't support execution of console commands from scripts\n");
sp -= 3;
break;
}
}
@ -9436,6 +9491,7 @@ DLevelScript::DLevelScript (AActor *who, line_t *where, int num, const ScriptPtr
activefont = SmallFont;
hudwidth = hudheight = 0;
ClipRectLeft = ClipRectTop = ClipRectWidth = ClipRectHeight = WrapWidth = 0;
HandleAspect = true;
state = SCRIPT_Running;
// Hexen waited one second before executing any open scripts. I didn't realize

View file

@ -891,6 +891,7 @@ protected:
int hudwidth, hudheight;
int ClipRectLeft, ClipRectTop, ClipRectWidth, ClipRectHeight;
int WrapWidth;
bool HandleAspect;
FBehavior *activeBehavior;
int InModuleScriptNumber;

View file

@ -707,6 +707,7 @@ static int LoadSprites (spritetype *sprites, Xsprite *xsprites, int numsprites,
mapthings[count].RenderStyle = STYLE_Count;
mapthings[count].alpha = -1;
mapthings[count].health = -1;
mapthings[count].FloatbobPhase = -1;
if (xsprites != NULL && sprites[i].lotag == 710)
{ // Blood ambient sound

View file

@ -184,7 +184,6 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf
const char *message;
const char *messagename;
char gendermessage[1024];
bool friendly;
int gender;
// No obituaries for non-players, voodoo dolls or when not wanted
@ -197,8 +196,6 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf
if (inflictor && inflictor->player && inflictor->player->mo != inflictor)
MeansOfDeath = NAME_None;
friendly = (self->player != attacker->player && self->IsTeammate(attacker));
mod = MeansOfDeath;
message = NULL;
messagename = NULL;
@ -266,7 +263,7 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf
if (message == NULL && attacker != NULL && attacker->player != NULL)
{
if (friendly)
if (self->player != attacker->player && self->IsTeammate(attacker))
{
self = attacker;
gender = self->player->userinfo.GetGender();
@ -973,7 +970,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
}
if (target->health <= 0)
{
if (inflictor && mod == NAME_Ice)
if (inflictor && mod == NAME_Ice && !(inflictor->flags7 & MF7_ICESHATTER))
{
return -1;
}
@ -1642,10 +1639,8 @@ bool AActor::OkayToSwitchTarget (AActor *other)
int infight;
if (flags5 & MF5_NOINFIGHTING) infight=-1;
else if (level.flags2 & LEVEL2_TOTALINFIGHTING) infight=1;
else if (level.flags2 & LEVEL2_NOINFIGHTING) infight=-1;
else infight = infighting;
else infight = G_SkillProperty(SKILLP_Infight);
if (infight < 0 && other->player == NULL && !IsHostile (other))
{
return false; // infighting off: Non-friendlies don't target other non-friendlies

View file

@ -56,6 +56,7 @@
#include "p_3dmidtex.h"
#include "d_net.h"
#include "d_event.h"
#include "gstrings.h"
#include "r_data/colormaps.h"
#define FUNC(a) static int a (line_t *ln, AActor *it, bool backSide, \
@ -1599,6 +1600,11 @@ FUNC(LS_Thing_Move) // [BC]
return P_Thing_Move (arg0, it, arg1, arg2 ? false : true);
}
enum
{
TRANSLATION_ICE = 0x100007
};
FUNC(LS_Thing_SetTranslation)
// Thing_SetTranslation (tid, range)
{
@ -1615,6 +1621,10 @@ FUNC(LS_Thing_SetTranslation)
{
range = TRANSLATION(TRANSLATION_LevelScripted, (arg1-1));
}
else if (arg1 == TRANSLATION_ICE)
{
range = TRANSLATION(TRANSLATION_Standard, 7);
}
else
{
range = 0;
@ -2985,13 +2995,14 @@ FUNC(LS_SendToCommunicator)
{
S_StopSound (CHAN_VOICE);
S_Sound (CHAN_VOICE, name, 1, ATTN_NORM);
if (arg2 == 0)
// Get the message from the LANGUAGE lump.
FString msg;
msg.Format("TXT_COMM%d", arg2);
const char *str = GStrings[msg];
if (str != NULL)
{
Printf (PRINT_CHAT, "Incoming Message\n");
}
else if (arg2 == 1)
{
Printf (PRINT_CHAT, "Incoming Message from BlackBird\n");
Printf (PRINT_CHAT, "%s\n", str);
}
}
return true;

View file

@ -153,7 +153,7 @@ AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, const PCl
AActor *P_SpawnPlayerMissile (AActor* source, const PClass *type);
AActor *P_SpawnPlayerMissile (AActor *source, const PClass *type, angle_t angle);
AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, const PClass *type, angle_t angle,
AActor **pLineTarget = NULL, AActor **MissileActor = NULL, bool nofreeaim = false);
AActor **pLineTarget = NULL, AActor **MissileActor = NULL, bool nofreeaim = false, bool noautoaim = false);
void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz, bool oldz_has_viewheight=false);
@ -176,7 +176,7 @@ bool P_Thing_Raise(AActor *thing, AActor *raiser);
bool P_Thing_CanRaise(AActor *thing);
const PClass *P_GetSpawnableType(int spawnnum);
void InitSpawnablesFromMapinfo();
int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs, fixed_t zofs, angle_t angle, int flags, fixed_t heightoffset);
int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs, fixed_t zofs, angle_t angle, int flags, fixed_t heightoffset, fixed_t radiusoffset, angle_t pitch);
enum WARPF
{
@ -198,6 +198,8 @@ enum WARPF
WARPF_MOVEPTR = 0x1000,
WARPF_USEPTR = 0x2000,
WARPF_USETID = 0x2000,
WARPF_COPYVELOCITY = 0x4000,
WARPF_COPYPITCH = 0x8000,
};
@ -240,7 +242,11 @@ fixed_t P_AproxDistance (fixed_t dx, fixed_t dy);
inline int P_PointOnLineSide (fixed_t x, fixed_t y, const line_t *line)
{
return DMulScale32 (y-line->v1->y, line->dx, line->v1->x-x, line->dy) > 0;
extern int P_VanillaPointOnLineSide(fixed_t x, fixed_t y, const line_t* line);
return i_compatflags2 & COMPATF2_POINTONLINE
? P_VanillaPointOnLineSide(x, y, line)
: DMulScale32 (y-line->v1->y, line->dx, line->v1->x-x, line->dy) > 0;
}
//==========================================================================
@ -254,7 +260,11 @@ inline int P_PointOnLineSide (fixed_t x, fixed_t y, const line_t *line)
inline int P_PointOnDivlineSide (fixed_t x, fixed_t y, const divline_t *line)
{
return DMulScale32 (y-line->y, line->dx, line->x-x, line->dy) > 0;
extern int P_VanillaPointOnDivlineSide(fixed_t x, fixed_t y, const divline_t* line);
return (i_compatflags2 & COMPATF2_POINTONLINE)
? P_VanillaPointOnDivlineSide(x, y, line)
: (DMulScale32 (y-line->y, line->dx, line->x-x, line->dy) > 0);
}
//==========================================================================
@ -492,7 +502,7 @@ enum // P_LineAttack flags
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, const PClass *pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL);
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, FName pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL);
AActor *P_LinePickActor (AActor *t1, angle_t angle, fixed_t distance, int pitch, DWORD actorMask, DWORD wallMask);
AActor *P_LinePickActor (AActor *t1, angle_t angle, fixed_t distance, int pitch, ActorFlags actorMask, DWORD wallMask);
void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *target, angle_t angle, int pitch);
void P_TraceBleed (int damage, AActor *target, angle_t angle, int pitch);
void P_TraceBleed (int damage, AActor *target, AActor *missile); // missile version

View file

@ -938,10 +938,7 @@ static bool CanAttackHurt(AActor *victim, AActor *shooter)
// to harm / be harmed by anything.
if (!victim->player && !shooter->player)
{
int infight;
if (level.flags2 & LEVEL2_TOTALINFIGHTING) infight = 1;
else if (level.flags2 & LEVEL2_NOINFIGHTING) infight = -1;
else infight = infighting;
int infight = G_SkillProperty(SKILLP_Infight);
if (infight < 0)
{
@ -3912,7 +3909,7 @@ AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance,
//==========================================================================
AActor *P_LinePickActor(AActor *t1, angle_t angle, fixed_t distance, int pitch,
DWORD actorMask, DWORD wallMask)
ActorFlags actorMask, DWORD wallMask)
{
fixed_t vx, vy, vz, shootz;

View file

@ -1523,3 +1523,92 @@ static AActor *RoughBlockCheck (AActor *mo, int index, void *param)
}
return NULL;
}
//===========================================================================
//
// P_VanillaPointOnLineSide
// P_PointOnLineSide() from the initial Doom source code release
//
//===========================================================================
int P_VanillaPointOnLineSide(fixed_t x, fixed_t y, const line_t* line)
{
fixed_t dx;
fixed_t dy;
fixed_t left;
fixed_t right;
if (!line->dx)
{
if (x <= line->v1->x)
return line->dy > 0;
return line->dy < 0;
}
if (!line->dy)
{
if (y <= line->v1->y)
return line->dx < 0;
return line->dx > 0;
}
dx = (x - line->v1->x);
dy = (y - line->v1->y);
left = FixedMul ( line->dy>>FRACBITS , dx );
right = FixedMul ( dy , line->dx>>FRACBITS );
if (right < left)
return 0; // front side
return 1; // back side
}
//===========================================================================
//
// P_VanillaPointOnDivlineSide
// P_PointOnDivlineSide() from the initial Doom source code release
//
//===========================================================================
int P_VanillaPointOnDivlineSide(fixed_t x, fixed_t y, const divline_t* line)
{
fixed_t dx;
fixed_t dy;
fixed_t left;
fixed_t right;
if (!line->dx)
{
if (x <= line->x)
return line->dy > 0;
return line->dy < 0;
}
if (!line->dy)
{
if (y <= line->y)
return line->dx < 0;
return line->dx > 0;
}
dx = (x - line->x);
dy = (y - line->y);
// try to quickly decide by looking at sign bits
if ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 )
{
if ( (line->dy ^ dx) & 0x80000000 )
return 1; // (left is negative)
return 0;
}
left = FixedMul ( line->dy>>8, dx>>8 );
right = FixedMul ( dy>>8 , line->dx>>8 );
if (right < left)
return 0; // front side
return 1; // back side
}

View file

@ -4917,6 +4917,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
mobj->SpawnPoint[2] = mthing->z;
mobj->SpawnAngle = mthing->angle;
mobj->SpawnFlags = mthing->flags;
if (mthing->FloatbobPhase >= 0 && mthing->FloatbobPhase < 64) mobj->FloatBobPhase = mthing->FloatbobPhase;
if (mthing->gravity < 0) mobj->gravity = -mthing->gravity;
else if (mthing->gravity > 0) mobj->gravity = FixedMul(mobj->gravity, mthing->gravity);
else mobj->flags &= ~MF_NOGRAVITY;
@ -5923,7 +5924,7 @@ AActor *P_SpawnPlayerMissile (AActor *source, const PClass *type, angle_t angle)
AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z,
const PClass *type, angle_t angle, AActor **pLineTarget, AActor **pMissileActor,
bool nofreeaim)
bool nofreeaim, bool noautoaim)
{
static const int angdiff[3] = { -1<<26, 1<<26, 0 };
angle_t an = angle;
@ -5936,7 +5937,7 @@ AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z,
{
return NULL;
}
if (source->player && source->player->ReadyWeapon && (source->player->ReadyWeapon->WeaponFlags & WIF_NOAUTOAIM))
if (source->player && source->player->ReadyWeapon && ((source->player->ReadyWeapon->WeaponFlags & WIF_NOAUTOAIM) || noautoaim))
{
// Keep exactly the same angle and pitch as the player's own aim
an = angle;
@ -6467,25 +6468,25 @@ void PrintMiscActorInfo(AActor *query)
Printf("%s @ %p has the following flags:\n flags: %x", query->GetTag(), query, query->flags.GetValue());
for (flagi = 0; flagi <= 31; flagi++)
if (query->flags & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags));
if (query->flags & ActorFlags::FromInt(1<<flagi)) Printf(" %s", FLAG_NAME(1<<flagi, flags));
Printf("\n flags2: %x", query->flags2.GetValue());
for (flagi = 0; flagi <= 31; flagi++)
if (query->flags2 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags2));
if (query->flags2 & ActorFlags2::FromInt(1<<flagi)) Printf(" %s", FLAG_NAME(1<<flagi, flags2));
Printf("\n flags3: %x", query->flags3.GetValue());
for (flagi = 0; flagi <= 31; flagi++)
if (query->flags3 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags3));
if (query->flags3 & ActorFlags3::FromInt(1<<flagi)) Printf(" %s", FLAG_NAME(1<<flagi, flags3));
Printf("\n flags4: %x", query->flags4.GetValue());
for (flagi = 0; flagi <= 31; flagi++)
if (query->flags4 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags4));
if (query->flags4 & ActorFlags4::FromInt(1<<flagi)) Printf(" %s", FLAG_NAME(1<<flagi, flags4));
Printf("\n flags5: %x", query->flags5.GetValue());
for (flagi = 0; flagi <= 31; flagi++)
if (query->flags5 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags5));
if (query->flags5 & ActorFlags5::FromInt(1<<flagi)) Printf(" %s", FLAG_NAME(1<<flagi, flags5));
Printf("\n flags6: %x", query->flags6.GetValue());
for (flagi = 0; flagi <= 31; flagi++)
if (query->flags6 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags6));
if (query->flags6 & ActorFlags6::FromInt(1<<flagi)) Printf(" %s", FLAG_NAME(1<<flagi, flags6));
Printf("\n flags7: %x", query->flags7.GetValue());
for (flagi = 0; flagi <= 31; flagi++)
if (query->flags7 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags7));
if (query->flags7 & ActorFlags7::FromInt(1<<flagi)) Printf(" %s", FLAG_NAME(1<<flagi, flags7));
Printf("\nBounce flags: %x\nBounce factors: f:%f, w:%f",
query->BounceFlags.GetValue(), FIXED2FLOAT(query->bouncefactor),
FIXED2FLOAT(query->wallbouncefactor));

View file

@ -29,6 +29,7 @@
#include "po_man.h"
#include "farchive.h"
#include "r_utility.h"
#include "a_sharedglobal.h"
#include "r_data/colormaps.h"
@ -800,6 +801,23 @@ int sector_t::GetCeilingLight () const
}
}
ASkyViewpoint *sector_t::GetSkyBox(int which)
{
if (which == floor)
{
if (FloorSkyBox != NULL) return FloorSkyBox;
if (MoreFlags & SECF_NOFLOORSKYBOX) return NULL;
}
else
{
if (CeilingSkyBox != NULL) return CeilingSkyBox;
if (MoreFlags & SECF_NOCEILINGSKYBOX) return NULL;
}
return level.DefaultSkybox;
}
sector_t *sector_t::GetHeightSec() const
{
if (heightsec == NULL)

View file

@ -1758,6 +1758,7 @@ void P_LoadThings (MapData * map)
mti[i].RenderStyle = STYLE_Count;
mti[i].alpha = -1;
mti[i].health = 1;
mti[i].FloatbobPhase = -1;
flags &= ~MTF_SKILLMASK;
mti[i].flags = (short)((flags & 0xf) | 0x7e0);
if (gameinfo.gametype == GAME_Strife)
@ -1842,6 +1843,7 @@ void P_LoadThings2 (MapData * map)
mti[i].RenderStyle = STYLE_Count;
mti[i].alpha = -1;
mti[i].health = 1;
mti[i].FloatbobPhase = -1;
}
delete[] mtp;
}
@ -2353,7 +2355,16 @@ static void P_LoopSidedefs (bool firstloop)
// instead of as part of another loop
if (line->frontsector == line->backsector)
{
right = DWORD(line->sidedef[!sidetemp[i].b.lineside] - sides);
const side_t* const rightside = line->sidedef[!sidetemp[i].b.lineside];
if (NULL == rightside)
{
// There is no right side!
if (firstloop) Printf ("Line %d's right edge is unconnected\n", linemap[unsigned(line-lines)]);
continue;
}
right = DWORD(rightside - sides);
}
else
{

View file

@ -288,16 +288,16 @@ bool P_TestActivateLine (line_t *line, AActor *mo, int side, int activationType)
}
}
if (activationType == SPAC_Use && (lineActivation & SPAC_MUse) && !mo->player && mo->flags4 & MF4_CANUSEWALLS)
{
return true;
}
if (activationType == SPAC_Push && (lineActivation & SPAC_MPush) && !mo->player && mo->flags2 & MF2_PUSHWALL)
{
return true;
}
if ((lineActivation & activationType) == 0)
{
if (activationType == SPAC_Use && (lineActivation & SPAC_MUse) && !mo->player && mo->flags4 & MF4_CANUSEWALLS)
{
return true;
}
if (activationType == SPAC_Push && (lineActivation & SPAC_MPush) && !mo->player && mo->flags2 & MF2_PUSHWALL)
{
return true;
}
if (activationType != SPAC_MCross || lineActivation != SPAC_Cross)
{
return false;

View file

@ -177,10 +177,47 @@ bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno)
if ((TexMan.FindSwitch(side->GetTexture(side_t::top))) != NULL)
{
// Check 3D floors on back side
{
sector_t * back = line->sidedef[1 - sideno]->sector;
for (unsigned i = 0; i < back->e->XFloor.ffloors.Size(); i++)
{
F3DFloor *rover = back->e->XFloor.ffloors[i];
if (!(rover->flags & FF_EXISTS)) continue;
if (!(rover->flags & FF_UPPERTEXTURE)) continue;
if (user->z > rover->top.plane->ZatPoint(checkx, checky) ||
user->z + user->height < rover->bottom.plane->ZatPoint(checkx, checky))
continue;
// This 3D floor depicts a switch texture in front of the player's eyes
return true;
}
}
return (user->z + user->height > open.top);
}
else if ((TexMan.FindSwitch(side->GetTexture(side_t::bottom))) != NULL)
{
// Check 3D floors on back side
{
sector_t * back = line->sidedef[1 - sideno]->sector;
for (unsigned i = 0; i < back->e->XFloor.ffloors.Size(); i++)
{
F3DFloor *rover = back->e->XFloor.ffloors[i];
if (!(rover->flags & FF_EXISTS)) continue;
if (!(rover->flags & FF_LOWERTEXTURE)) continue;
if (user->z > rover->top.plane->ZatPoint(checkx, checky) ||
user->z + user->height < rover->bottom.plane->ZatPoint(checkx, checky))
continue;
// This 3D floor depicts a switch texture in front of the player's eyes
return true;
}
}
return (user->z < open.bottom);
}
else if ((flags & ML_3DMIDTEX) || (TexMan.FindSwitch(side->GetTexture(side_t::mid))) != NULL)

View file

@ -680,7 +680,7 @@ void InitSpawnablesFromMapinfo()
}
int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs, fixed_t zofs, angle_t angle, int flags, fixed_t heightoffset)
int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs, fixed_t zofs, angle_t angle, int flags, fixed_t heightoffset, fixed_t radiusoffset, angle_t pitch)
{
if (flags & WARPF_MOVEPTR)
{
@ -692,25 +692,27 @@ int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs,
fixed_t oldx = caller->x;
fixed_t oldy = caller->y;
fixed_t oldz = caller->z;
zofs += FixedMul(reference->height, heightoffset);
if (!(flags & WARPF_ABSOLUTEANGLE))
{
angle += (flags & WARPF_USECALLERANGLE) ? caller->angle : reference->angle;
}
const fixed_t rad = FixedMul(radiusoffset, reference->radius);
const angle_t fineangle = angle >> ANGLETOFINESHIFT;
if (!(flags & WARPF_ABSOLUTEPOSITION))
{
if (!(flags & WARPF_ABSOLUTEOFFSET))
{
angle_t fineangle = angle >> ANGLETOFINESHIFT;
fixed_t xofs1 = xofs;
// (borrowed from A_SpawnItemEx, assumed workable)
// in relative mode negative y values mean 'left' and positive ones mean 'right'
// This is the inverse orientation of the absolute mode!
xofs = FixedMul(xofs1, finecosine[fineangle]) + FixedMul(yofs, finesine[fineangle]);
yofs = FixedMul(xofs1, finesine[fineangle]) - FixedMul(yofs, finecosine[fineangle]);
}
@ -722,15 +724,16 @@ int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs,
// assigning position again with.
// extra unlink, link and environment calculation
caller->SetOrigin(
reference->x + xofs,
reference->y + yofs,
reference->floorz + zofs);
reference->x + xofs + FixedMul(rad, finecosine[fineangle]),
reference->y + yofs + FixedMul(rad, finesine[fineangle]),
reference->z);
caller->z = caller->floorz + zofs;
}
else
{
caller->SetOrigin(
reference->x + xofs,
reference->y + yofs,
reference->x + xofs + FixedMul(rad, finecosine[fineangle]),
reference->y + yofs + FixedMul(rad, finesine[fineangle]),
reference->z + zofs);
}
}
@ -738,11 +741,12 @@ int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs,
{
if (flags & WARPF_TOFLOOR)
{
caller->SetOrigin(xofs, yofs, caller->floorz + zofs);
caller->SetOrigin(xofs + FixedMul(rad, finecosine[fineangle]), yofs + FixedMul(rad, finesine[fineangle]), zofs);
caller->z = caller->floorz + zofs;
}
else
{
caller->SetOrigin(xofs, yofs, zofs);
caller->SetOrigin(xofs + FixedMul(rad, finecosine[fineangle]), yofs + FixedMul(rad, finesine[fineangle]), zofs);
}
}
@ -756,6 +760,18 @@ int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs,
{
caller->angle = angle;
if (flags & WARPF_COPYPITCH)
caller->SetPitch(reference->pitch, false);
if (pitch)
caller->SetPitch(caller->pitch + pitch, false);
if (flags & WARPF_COPYVELOCITY)
{
caller->velx = reference->velx;
caller->vely = reference->vely;
caller->velz = reference->velz;
}
if (flags & WARPF_STOP)
{
caller->velx = 0;

View file

@ -42,7 +42,8 @@ struct FTraceInfo
{
fixed_t StartX, StartY, StartZ;
fixed_t Vx, Vy, Vz;
DWORD ActorMask, WallMask;
ActorFlags ActorMask;
DWORD WallMask;
AActor *IgnoreThis;
FTraceResults *Results;
sector_t *CurSector;
@ -70,7 +71,7 @@ static bool EditTraceResult (DWORD flags, FTraceResults &res);
bool Trace (fixed_t x, fixed_t y, fixed_t z, sector_t *sector,
fixed_t vx, fixed_t vy, fixed_t vz, fixed_t maxDist,
DWORD actorMask, DWORD wallMask, AActor *ignore,
ActorFlags actorMask, DWORD wallMask, AActor *ignore,
FTraceResults &res,
DWORD flags, ETraceStatus (*callback)(FTraceResults &res, void *), void *callbackdata)
{

View file

@ -35,6 +35,7 @@
#define __P_TRACE_H__
#include <stddef.h>
#include "actor.h"
#include "textures/textures.h"
struct sector_t;
@ -96,7 +97,7 @@ enum ETraceStatus
bool Trace (fixed_t x, fixed_t y, fixed_t z, sector_t *sector,
fixed_t vx, fixed_t vy, fixed_t vz, fixed_t maxDist,
DWORD ActorMask, DWORD WallMask, AActor *ignore,
ActorFlags ActorMask, DWORD WallMask, AActor *ignore,
FTraceResults &res,
DWORD traceFlags=0,
ETraceStatus (*callback)(FTraceResults &res, void *)=NULL, void *callbackdata=NULL);

View file

@ -474,6 +474,7 @@ public:
th->RenderStyle = STYLE_Count;
th->alpha = -1;
th->health = 1;
th->FloatbobPhase = -1;
sc.MustGetToken('{');
while (!sc.CheckToken('}'))
{
@ -631,6 +632,11 @@ public:
Flag(th->flags, MTF_SECRET, key);
break;
case NAME_Floatbobphase:
CHECK_N(Zd | Zdt)
th->FloatbobPhase = CheckInt(key);
break;
case NAME_Renderstyle:
{
FName style = CheckString(key);
@ -779,7 +785,7 @@ public:
bool strifetrans = false;
bool strifetrans2 = false;
FString arg0str, arg1str;
int lineid; // forZDoomTranslated namespace
int lineid = -1; // forZDoomTranslated namespace
FString tagstring;
memset(ld, 0, sizeof(*ld));
@ -1076,7 +1082,7 @@ public:
maplinedef_t mld;
memset(&mld, 0, sizeof(mld));
mld.special = ld->special;
mld.tag = lineid;
mld.tag = ld->args[0];
P_TranslateLineDef(ld, &mld);
ld->flags = saved | (ld->flags&(ML_MONSTERSCANACTIVATE|ML_REPEAT_SPECIAL|ML_FIRSTSIDEONLY));
}

View file

@ -1562,12 +1562,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullPop)
if (player != NULL)
{
player->mo = mo;
if (player->camera == self)
{
player->camera = mo;
}
player->damagecount = 32;
}
for (int i = 0; i < MAXPLAYERS; ++i)
{
if (playeringame[i] && players[i].camera == self)
{
players[i].camera = mo;
}
}
}
//----------------------------------------------------------------------------

View file

@ -342,17 +342,19 @@ VideoModes[] =
{ 1680, 1050 }, // 16:10
{ 1920, 1080 },
{ 1920, 1200 },
{ 2048, 1152 }, // 16:9, iMac Retina 4K 21.5", HiDPI off
{ 2048, 1536 },
{ 2304, 1440 },
{ 2304, 1440 }, // 16:10, MacBook Retina 12"
{ 2560, 1440 },
{ 2560, 1600 },
{ 2560, 2048 },
{ 2880, 1800 },
{ 2880, 1800 }, // 16:10, MacBook Pro Retina 15"
{ 3200, 1800 },
{ 3840, 2160 },
{ 3840, 2400 },
{ 4096, 2160 },
{ 5120, 2880 }
{ 4096, 2304 }, // 16:9, iMac Retina 4K 21.5"
{ 5120, 2880 } // 16:9, iMac Retina 5K 27"
};

View file

@ -1087,7 +1087,8 @@ void R_Subsector (subsector_t *sub)
basecolormap = frontsector->ColorMap;
}
skybox = frontsector->CeilingSkyBox != NULL ? frontsector->CeilingSkyBox : level.DefaultSkybox;
skybox = frontsector->GetSkyBox(sector_t::ceiling);
ceilingplane = frontsector->ceilingplane.PointOnSide(viewx, viewy, viewz) > 0 ||
frontsector->GetTexture(sector_t::ceiling) == skyflatnum ||
(skybox != NULL && skybox->bAlways) ||
@ -1127,7 +1128,7 @@ void R_Subsector (subsector_t *sub)
// killough 3/7/98: Add (x,y) offsets to flats, add deep water check
// killough 3/16/98: add floorlightlevel
// killough 10/98: add support for skies transferred from sidedefs
skybox = frontsector->FloorSkyBox != NULL ? frontsector->FloorSkyBox : level.DefaultSkybox;
skybox = frontsector->GetSkyBox(sector_t::floor);
floorplane = frontsector->floorplane.PointOnSide(viewx, viewy, viewz) > 0 || // killough 3/7/98
frontsector->GetTexture(sector_t::floor) == skyflatnum ||
(skybox != NULL && skybox->bAlways) ||

View file

@ -377,6 +377,8 @@ enum
SECF_UNDERWATERMASK = 32+64,
SECF_DRAWN = 128, // sector has been drawn at least once
SECF_HIDDEN = 256, // Do not draw on textured automap
SECF_NOFLOORSKYBOX = 512, // force use of regular sky
SECF_NOCEILINGSKYBOX = 1024, // force use of regular sky
};
enum
@ -490,6 +492,8 @@ struct sector_t
DInterpolation *SetInterpolation(int position, bool attach);
void StopInterpolation(int position);
ASkyViewpoint *GetSkyBox(int which);
enum
{
floor,

View file

@ -254,7 +254,7 @@ void R_InitTextureMapping ()
void R_SetVisibility (float vis)
{
// Allow negative visibilities, just for novelty's sake
//vis = clamp (vis, -204.7f, 204.7f);
vis = clamp (vis, -204.7f, 204.7f); // (205 and larger do not work in 5:4 aspect ratio)
CurrentVisibility = vis;

View file

@ -2375,6 +2375,16 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
}
}
FName *aliasp = MusicAliases.CheckKey(musicname);
if (aliasp != NULL)
{
if (*aliasp == NAME_None)
{
return true; // flagged to be ignored
}
musicname = aliasp->GetChars();
}
if (!mus_playing.name.IsEmpty() &&
mus_playing.handle != NULL &&
stricmp (mus_playing.name, musicname) == 0 &&
@ -2413,16 +2423,8 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
int length = 0;
int device = MDEV_DEFAULT;
MusInfo *handle = NULL;
FName musicasname = musicname;
FName *aliasp = MusicAliases.CheckKey(musicasname);
if (aliasp != NULL)
{
musicname = (musicasname = *aliasp).GetChars();
if (musicasname == NAME_None) return true;
}
int *devp = MidiDevices.CheckKey(musicasname);
int *devp = MidiDevices.CheckKey(musicname);
if (devp != NULL) device = *devp;
// Strip off any leading file:// component.

View file

@ -44,7 +44,7 @@ extern HWND Window;
#define FALSE 0
#define TRUE 1
#endif
#ifdef __APPLE__
#if defined(__FreeBSD__) || defined(__APPLE__)
#include <stdlib.h>
#elif __sun
#include <alloca.h>
@ -771,7 +771,7 @@ bool FMODSoundRenderer::Init()
}
#endif
#ifndef _WIN32
#if !defined _WIN32 && !defined __APPLE__
// Try to load SDL output plugin
result = Sys->setPluginPath(progdir); // Should we really look for it in the program directory?
result = Sys->loadPlugin("liboutput_sdl.so", &OutputPlugin);

View file

@ -713,11 +713,11 @@ BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode)
if ( hRT )
{
// Must wait process to terminate to guarantee that it has exited...
WaitForSingleObject(hProcess, INFINITE);
// Must wait for process to terminate to guarantee that it has exited...
DWORD res = WaitForSingleObject(hProcess, 1000);
CloseHandle(hRT);
bSuccess = TRUE;
bSuccess = (res == WAIT_OBJECT_0);
dwErr = WAIT_TIMEOUT;
}
if ( !bSuccess )

File diff suppressed because it is too large Load diff

View file

@ -1246,7 +1246,8 @@ void FTextureManager::PrecacheLevel (void)
for (unsigned i = 0; i < level.info->PrecacheTextures.Size(); i++)
{
hitlist[level.info->PrecacheTextures[i].GetIndex()] |= FTextureManager::HIT_Wall;
FTextureID tex = TexMan.CheckForTexture(level.info->PrecacheTextures[i], FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny|FTextureManager::TEXMAN_ReturnFirst);
if (tex.Exists()) hitlist[tex.GetIndex()] |= FTextureManager::HIT_Wall;
}
for (int i = cnt - 1; i >= 0; i--)

View file

@ -94,6 +94,10 @@ public:
static Self FromInt (TT value) { return Self (static_cast<T> (value)); }
private:
template<typename X> Self operator| (X value) const { return Self::FromInt (Value | value); }
template<typename X> Self operator& (X value) const { return Self::FromInt (Value & value); }
template<typename X> Self operator^ (X value) const { return Self::FromInt (Value ^ value); }
TT Value;
};

View file

@ -660,18 +660,20 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInsideMeleeRange)
//==========================================================================
void DoJumpIfCloser(AActor *target, DECLARE_PARAMINFO)
{
ACTION_PARAM_START(2);
ACTION_PARAM_START(3);
ACTION_PARAM_FIXED(dist, 0);
ACTION_PARAM_STATE(jump, 1);
ACTION_PARAM_BOOL(noz, 2);
ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
// No target - no jump
if (target != NULL && P_AproxDistance(self->x-target->x, self->y-target->y) < dist &&
( (self->z > target->z && self->z - (target->z + target->height) < dist) ||
(self->z <=target->z && target->z - (self->z + self->height) < dist)
)
)
if (!target)
return;
if (P_AproxDistance(self->x-target->x, self->y-target->y) < dist &&
(noz ||
((self->z > target->z && self->z - (target->z + target->height) < dist) ||
(self->z <= target->z && target->z - (self->z + self->height) < dist))))
{
ACTION_JUMP(jump);
}
@ -1012,7 +1014,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile)
targ=owner;
missile->target=owner;
// automatic handling of seeker missiles
if (self->flags & missile->flags2 & MF2_SEEKERMISSILE)
if (self->flags2 & missile->flags2 & MF2_SEEKERMISSILE)
{
missile->tracer=self->tracer;
}
@ -1320,6 +1322,7 @@ enum FP_Flags
{
FPF_AIMATANGLE = 1,
FPF_TRANSFERTRANSLATION = 2,
FPF_NOAUTOAIM = 4,
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile)
{
@ -1358,7 +1361,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile)
// Temporarily adjusts the pitch
fixed_t SavedPlayerPitch = self->pitch;
self->pitch -= pitch;
AActor * misl=P_SpawnPlayerMissile (self, x, y, z, ti, shootangle, &linetarget);
AActor * misl=P_SpawnPlayerMissile (self, x, y, z, ti, shootangle, &linetarget, NULL, false, (Flags & FPF_NOAUTOAIM) != 0);
self->pitch = SavedPlayerPitch;
// automatic handling of seeker missiles
@ -1411,6 +1414,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch)
ACTION_PARAM_FIXED(LifeSteal, 5);
ACTION_PARAM_INT(lifestealmax, 6);
ACTION_PARAM_CLASS(armorbonustype, 7);
ACTION_PARAM_SOUND(MeleeSound, 8);
ACTION_PARAM_SOUND(MissSound, 9);
if (!self->player) return;
@ -1440,7 +1445,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch)
P_LineAttack (self, angle, Range, pitch, Damage, NAME_Melee, PuffType, puffFlags, &linetarget, &actualdamage);
if (linetarget)
if (!linetarget)
{
if (MissSound) S_Sound(self, CHAN_WEAPON, MissSound, 1, ATTN_NORM);
}
else
{
if (LifeSteal && !(linetarget->flags5 & MF5_DONTDRAIN))
{
@ -1471,7 +1480,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch)
if (weapon != NULL)
{
S_Sound (self, CHAN_WEAPON, weapon->AttackSound, 1, ATTN_NORM);
if (MeleeSound) S_Sound(self, CHAN_WEAPON, MeleeSound, 1, ATTN_NORM);
else S_Sound (self, CHAN_WEAPON, weapon->AttackSound, 1, ATTN_NORM);
}
if (!(flags & CPF_NOTURN))
@ -3411,7 +3421,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
lof_data.Flags = flags;
lof_data.BadActor = false;
Trace(x1, y1, z1, sec, vx, vy, vz, range, 0xFFFFFFFF, ML_BLOCKEVERYTHING, self, trace, 0,
Trace(x1, y1, z1, sec, vx, vy, vz, range, ActorFlags::FromInt(0xFFFFFFFF), ML_BLOCKEVERYTHING, self, trace, 0,
CheckLOFTraceFunc, &lof_data);
if (trace.HitType == TRACE_HitActor ||
@ -4672,7 +4682,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp)
{
ACTION_PARAM_START(8);
ACTION_PARAM_START(10);
ACTION_PARAM_INT(destination_selector, 0);
ACTION_PARAM_FIXED(xofs, 1);
@ -4681,7 +4691,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp)
ACTION_PARAM_ANGLE(angle, 4);
ACTION_PARAM_INT(flags, 5);
ACTION_PARAM_STATE(success_state, 6);
ACTION_PARAM_FIXED(heightoffset,7)
ACTION_PARAM_FIXED(heightoffset, 7);
ACTION_PARAM_FIXED(radiusoffset, 8);
ACTION_PARAM_ANGLE(pitch, 9);
AActor *reference;
@ -4701,7 +4713,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp)
return;
}
if (P_Thing_Warp(self, reference, xofs, yofs, zofs, angle, flags, heightoffset))
if (P_Thing_Warp(self, reference, xofs, yofs, zofs, angle, flags, heightoffset, radiusoffset, pitch))
{
if (success_state)
{
@ -4879,17 +4891,19 @@ enum RadiusGiveFlags
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
{
ACTION_PARAM_START(6);
ACTION_PARAM_START(7);
ACTION_PARAM_CLASS(item, 0);
ACTION_PARAM_FIXED(distance, 1);
ACTION_PARAM_INT(flags, 2);
ACTION_PARAM_INT(amount, 3);
ACTION_PARAM_CLASS(filter, 4);
ACTION_PARAM_NAME(species, 5);
ACTION_PARAM_FIXED(mindist, 6);
// We need a valid item, valid targets, and a valid range
if (item == NULL || (flags & RGF_MASK) == 0 || !flags || distance <= 0)
if (item == NULL || (flags & RGF_MASK) == 0 || !flags || distance <= 0 || mindist >= distance)
{
ACTION_SET_RESULT(false);
return;
}
@ -4898,9 +4912,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
amount = 1;
}
FBlockThingsIterator it(FBoundingBox(self->x, self->y, distance));
double distsquared = double(distance) * double(distance);
AActor *thing;
bool given = false;
while ((thing = it.Next()))
{
//[MC] Check for a filter, species, and the related exfilter/expecies/either flag(s).
@ -4945,7 +4959,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
bool corpsePass = !!((flags & RGF_CORPSES) && thing->flags & MF_CORPSE);
bool killedPass = !!((flags & RGF_KILLED) && thing->flags6 & MF6_KILLED);
bool monsterPass = !!((flags & RGF_MONSTERS) && thing->flags3 & MF3_ISMONSTER);
bool objectPass = !!((flags & RGF_OBJECTS) && ((thing->flags & MF_SHOOTABLE) || (thing->flags6 & MF6_VULNERABLE)));
bool objectPass = !!((flags & RGF_OBJECTS) && (thing->player == NULL) && (!(thing->flags3 & MF3_ISMONSTER))
&& ((thing->flags & MF_SHOOTABLE) || (thing->flags6 & MF6_VULNERABLE)));
bool playerPass = !!((flags & RGF_PLAYERS) && (thing->player != NULL) && (thing->player->mo == thing));
bool voodooPass = !!((flags & RGF_VOODOO) && (thing->player != NULL) && (thing->player->mo != thing));
//Self calls priority over the rest of this.
@ -4968,20 +4983,26 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
if (selfPass || monsterPass || corpsePass || killedPass || itemPass || objectPass || missilePass || playerPass || voodooPass)
{
if (flags & RGF_CUBE)
{ // check if inside a cube
if (fabs((double)thing->x - self->x) > (double)distance ||
fabs((double)thing->y - self->y) > (double)distance ||
fabs((double)(thing->z + thing->height / 2) - (self->z + self->height / 2)) > (double)distance)
double dx = fabs((double)(thing->x - self->x));
double dy = fabs((double)(thing->y - self->y));
double dz = fabs((double)(thing->z + thing->height / 2) - (self->z + self->height / 2));
double dist = (double)distance;
double min = (double)mindist;
if ((dx > dist || dy > dist || dz > dist) || (min && (dx < min && dy < min && dz < min)))
{
continue;
}
}
else
{ // check if inside a sphere
double distsquared = double(distance) * double(distance);
double minsquared = double(mindist) * double(mindist);
TVector3<double> tpos(thing->x, thing->y, thing->z + thing->height / 2);
TVector3<double> spos(self->x, self->y, self->z + self->height / 2);
if ((tpos - spos).LengthSquared() > distsquared)
if ((tpos - spos).LengthSquared() > distsquared || (minsquared && ((tpos - spos).LengthSquared() < minsquared)))
{
continue;
}
@ -5004,9 +5025,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
{
gift->Destroy();
}
else
{
given = true;
}
}
}
}
ACTION_SET_RESULT(given);
}
@ -5071,7 +5097,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DropItem)
// A_SetSpeed
//
//==========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpeed)
{
ACTION_PARAM_START(2);
@ -5089,6 +5114,50 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpeed)
ref->Speed = speed;
}
//==========================================================================
//
// A_SetFloatSpeed
//
//==========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetFloatSpeed)
{
ACTION_PARAM_START(2);
ACTION_PARAM_FIXED(speed, 0);
ACTION_PARAM_INT(ptr, 1);
AActor *ref = COPY_AAPTR(self, ptr);
if (!ref)
{
ACTION_SET_RESULT(false);
return;
}
ref->FloatSpeed = speed;
}
//==========================================================================
//
// A_SetPainThreshold
//
//==========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPainThreshold)
{
ACTION_PARAM_START(2);
ACTION_PARAM_INT(threshold, 0);
ACTION_PARAM_INT(ptr, 1);
AActor *ref = COPY_AAPTR(self, ptr);
if (!ref)
{
ACTION_SET_RESULT(false);
return;
}
ref->PainThreshold = threshold;
}
//===========================================================================
//
// Common A_Damage handler
@ -5823,3 +5892,160 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRipMax)
ACTION_PARAM_INT(max, 0);
self->RipLevelMax = max;
}
//==========================================================================
//
// A_CheckProximity(jump, classname, distance, count, flags, ptr)
//
// Checks to see if a certain actor class is close to the
// actor/pointer within distance, in numbers.
//==========================================================================
enum CPXFflags
{
CPXF_ANCESTOR = 1,
CPXF_LESSOREQUAL = 1 << 1,
CPXF_NOZ = 1 << 2,
CPXF_COUNTDEAD = 1 << 3,
CPXF_DEADONLY = 1 << 4,
CPXF_EXACT = 1 << 5,
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity)
{
ACTION_PARAM_START(6);
ACTION_PARAM_STATE(jump, 0);
ACTION_PARAM_CLASS(classname, 1);
ACTION_PARAM_FIXED(distance, 2);
ACTION_PARAM_INT(count, 3);
ACTION_PARAM_INT(flags, 4);
ACTION_PARAM_INT(ptr, 5);
ACTION_SET_RESULT(false); //No inventory chain results please.
AActor *ref = COPY_AAPTR(self, ptr);
//We need these to check out.
if (!ref || !jump || !classname || distance <= 0)
return;
int counter = 0;
bool result = false;
TThinkerIterator<AActor> it;
AActor * mo;
//[MC] Process of elimination, I think, will get through this as quickly and
//efficiently as possible.
while ((mo = it.Next()))
{
if (mo == ref) //Don't count self.
continue;
//Check inheritance for the classname. Taken partly from CheckClass DECORATE function.
if (flags & CPXF_ANCESTOR)
{
if (!(mo->GetClass()->IsAncestorOf(classname)))
continue;
}
//Otherwise, just check for the regular class name.
else if (classname != mo->GetClass())
continue;
//Make sure it's in range and respect the desire for Z or not.
if (P_AproxDistance(ref->x - mo->x, ref->y - mo->y) < distance &&
((flags & CPXF_NOZ) ||
((ref->z > mo->z && ref->z - (mo->z + mo->height) < distance) ||
(ref->z <= mo->z && mo->z - (ref->z + ref->height) < distance))))
{
if (mo->flags6 & MF6_KILLED)
{
if (!(flags & (CPXF_COUNTDEAD | CPXF_DEADONLY)))
continue;
counter++;
}
else
{
if (flags & CPXF_DEADONLY)
continue;
counter++;
}
//Abort if the number of matching classes nearby is greater, we have obviously succeeded in our goal.
if (counter > count)
{
result = (flags & (CPXF_LESSOREQUAL | CPXF_EXACT)) ? false : true;
break;
}
}
}
if (counter == count)
result = true;
else if (counter < count)
result = !!((flags & CPXF_LESSOREQUAL) && !(flags & CPXF_EXACT));
if (result)
{
ACTION_JUMP(jump);
}
}
/*===========================================================================
A_CheckBlock
(state block, int flags, int ptr)
Checks if something is blocking the actor('s pointer) 'ptr'.
The SET pointer flags only affect the caller, not the pointer.
===========================================================================*/
enum CBF
{
CBF_NOLINES = 1 << 0, //Don't check actors.
CBF_SETTARGET = 1 << 1, //Sets the caller/pointer's target to the actor blocking it. Actors only.
CBF_SETMASTER = 1 << 2, //^ but with master.
CBF_SETTRACER = 1 << 3, //^ but with tracer.
CBF_SETONPTR = 1 << 4, //Sets the pointer change on the actor doing the checking instead of self.
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock)
{
ACTION_PARAM_START(3);
ACTION_PARAM_STATE(block, 0);
ACTION_PARAM_INT(flags, 1);
ACTION_PARAM_INT(ptr, 2);
AActor *mobj = COPY_AAPTR(self, ptr);
ACTION_SET_RESULT(false);
//Needs at least one state jump to work.
if (!mobj)
{
return;
}
//Nothing to block it so skip the rest.
if (P_TestMobjLocation(mobj)) return;
if (mobj->BlockingMobj)
{
AActor *setter = (flags & CBF_SETONPTR) ? mobj : self;
if (setter)
{
if (flags & CBF_SETTARGET) setter->target = mobj->BlockingMobj;
if (flags & CBF_SETMASTER) setter->master = mobj->BlockingMobj;
if (flags & CBF_SETTRACER) setter->tracer = mobj->BlockingMobj;
}
}
//[MC] If modders don't want jumping, but just getting the pointer, only abort at
//this point. I.e. A_CheckBlock("",CBF_SETTRACER) is like having CBF_NOLINES.
//It gets the mobj blocking, if any, and doesn't jump at all.
if (!block)
return;
//[MC] Easiest way to tell if an actor is blocking it, use the pointers.
if (mobj->BlockingMobj || (!(flags & CBF_NOLINES) && mobj->BlockingLine != NULL))
{
ACTION_JUMP(block);
}
}

View file

@ -253,12 +253,10 @@ static FFlagDef ActorFlagDefs[]=
DEFINE_FLAG(MF7, HITTARGET, AActor, flags7),
DEFINE_FLAG(MF7, HITMASTER, AActor, flags7),
DEFINE_FLAG(MF7, HITTRACER, AActor, flags7),
// [ZK] Decal flags
DEFINE_FLAG(MF7, NODECAL, AActor, flags7),
DEFINE_FLAG(MF7, NODECAL, AActor, flags7), // [ZK] Decal flags
DEFINE_FLAG(MF7, FORCEDECAL, AActor, flags7),
DEFINE_FLAG(MF7, LAXTELEFRAGDMG, AActor, flags7),
DEFINE_FLAG(MF7, ICESHATTER, AActor, flags7),
// Effect flags
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),

View file

@ -76,7 +76,7 @@ const char *GetVersionString();
// Use 4500 as the base git save version, since it's higher than the
// SVN revision ever got.
#define SAVEVER 4524
#define SAVEVER 4525
#define SAVEVERSTRINGIFY2(x) #x
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)

View file

@ -184,6 +184,7 @@ void FWadCollection::InitMultipleFiles (TArray<FString> &filenames)
}
RenameNerve();
RenameSprites();
FixMacHexen();
// [RH] Set up hash table
FirstLumpIndex = new DWORD[NumLumps];
@ -956,6 +957,41 @@ void FWadCollection::RenameNerve ()
}
}
//==========================================================================
//
// FixMacHexen
//
// Rename unused high resolution font lumps because they are incorrectly
// treated as extended characters
//
//==========================================================================
void FWadCollection::FixMacHexen()
{
if (GAME_Hexen != gameinfo.gametype)
{
return;
}
for (int i = GetFirstLump(IWAD_FILENUM), last = GetLastLump(IWAD_FILENUM); i <= last; ++i)
{
assert(IWAD_FILENUM == LumpInfo[i].wadnum);
FResourceLump* const lump = LumpInfo[i].lump;
char* const name = lump->Name;
// Unwanted lumps are named like FONTA??1
if (8 == strlen(name)
&& MAKE_ID('F', 'O', 'N', 'T') == lump->dwName
&& 'A' == name[4] && '1' == name[7]
&& isdigit(name[5]) && isdigit(name[6]))
{
name[0] = '\0';
}
}
}
//==========================================================================
//
// W_FindLump

View file

@ -238,6 +238,7 @@ protected:
private:
void RenameSprites();
void RenameNerve();
void FixMacHexen();
void DeleteAll();
};

View file

@ -1808,18 +1808,16 @@ void WI_updateStats ()
if (acceleratestage && sp_state != 10)
{
if (acceleratestage)
{
acceleratestage = 0;
sp_state = 10;
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/nextstage", 1, ATTN_NONE);
}
acceleratestage = 0;
sp_state = 10;
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/nextstage", 1, ATTN_NONE);
cnt_kills[0] = plrs[me].skills;
cnt_items[0] = plrs[me].sitems;
cnt_secret[0] = plrs[me].ssecret;
cnt_time = Tics2Seconds(plrs[me].stime);
cnt_par = wbs->partime / TICRATE;
cnt_total_time = Tics2Seconds(wbs->totaltime);
cnt_total_time = Tics2Seconds(wbs->totaltime);
}
if (sp_state == 2)

View file

@ -137,6 +137,7 @@ extern bool ConWindowHidden;
// PUBLIC DATA DEFINITIONS -------------------------------------------------
CVAR (String, queryiwad_key, "shift", CVAR_GLOBALCONFIG|CVAR_ARCHIVE);
CVAR (Bool, con_debugoutput, false, 0);
double PerfToSec, PerfToMillisec;
UINT TimerPeriod;
@ -1053,6 +1054,31 @@ static TArray<FString> bufferedConsoleStuff;
void I_PrintStr(const char *cp)
{
if (con_debugoutput)
{
// Strip out any color escape sequences before writing to debug output
char * copy = new char[strlen(cp)+1];
const char * srcp = cp;
char * dstp = copy;
while (*srcp != 0)
{
if (*srcp!=0x1c && *srcp!=0x1d && *srcp!=0x1e && *srcp!=0x1f)
{
*dstp++=*srcp++;
}
else
{
if (srcp[1]!=0) srcp+=2;
else break;
}
}
*dstp=0;
OutputDebugStringA(copy);
delete [] copy;
}
if (ConWindowHidden)
{
bufferedConsoleStuff.Push(cp);
@ -1700,3 +1726,36 @@ FString I_GetLongPathName(FString shortpath)
delete[] buff;
return longpath;
}
#if _MSC_VER == 1900 && defined(_USING_V110_SDK71_)
//==========================================================================
//
// VS14Stat
//
// Work around an issue where stat doesn't work with v140_xp. This was
// supposedly fixed, but as of Update 1 continues to not function on XP.
//
//==========================================================================
#include <sys/stat.h>
int VS14Stat(const char *path, struct _stat64i32 *buffer)
{
WIN32_FILE_ATTRIBUTE_DATA data;
if(!GetFileAttributesEx(path, GetFileExInfoStandard, &data))
return -1;
buffer->st_ino = 0;
buffer->st_mode = ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? S_IFDIR : S_IFREG)|
((data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? S_IREAD : S_IREAD|S_IWRITE);
buffer->st_dev = buffer->st_rdev = 0;
buffer->st_nlink = 1;
buffer->st_uid = 0;
buffer->st_gid = 0;
buffer->st_size = data.nFileSizeLow;
buffer->st_atime = (*(QWORD*)&data.ftLastAccessTime) / 10000000 - 11644473600LL;
buffer->st_mtime = (*(QWORD*)&data.ftLastWriteTime) / 10000000 - 11644473600LL;
buffer->st_ctime = (*(QWORD*)&data.ftCreationTime) / 10000000 - 11644473600LL;
return 0;
}
#endif

View file

@ -3061,6 +3061,7 @@ struct lemon *lemp;
FILE *in;
char *tpltname;
char *cp;
Boolean tpltnameinbuf;
cp = strrchr(lemp->filename,'.');
if( cp ){
@ -3070,10 +3071,13 @@ struct lemon *lemp;
}
if( access(buf,004)==0 ){
tpltname = buf;
tpltnameinbuf = LEMON_TRUE;
}else if( access(templatename,004)==0 ){
tpltname = templatename;
tpltnameinbuf = LEMON_TRUE;
}else{
tpltname = pathsearch(lemp->argv0,templatename,0);
tpltnameinbuf = LEMON_FALSE;
}
if( tpltname==0 ){
fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
@ -3084,11 +3088,11 @@ struct lemon *lemp;
in = fopen(tpltname,"rb");
if( in==0 ){
fprintf(stderr,"Can't open the template file \"%s\".\n",templatename);
free(tpltname);
if (tpltnameinbuf == LEMON_FALSE) free(tpltname);
lemp->errorcnt++;
return 0;
}
free(tpltname);
if (tpltnameinbuf == LEMON_FALSE) free(tpltname);
return in;
}

View file

@ -212,9 +212,9 @@ ACTOR Actor native //: Thinker
action native A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET);
action native A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, bool aim = false, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270);
action native A_JumpIfHealthLower(int health, state label, int ptr_selector = AAPTR_DEFAULT);
action native A_JumpIfCloser(float distance, state label);
action native A_JumpIfTracerCloser(float distance, state label);
action native A_JumpIfMasterCloser(float distance, state label);
action native A_JumpIfCloser(float distance, state label, bool noz = false);
action native A_JumpIfTracerCloser(float distance, state label, bool noz = false);
action native A_JumpIfMasterCloser(float distance, state label, bool noz = false);
action native A_JumpIfTargetOutsideMeleeRange(state label);
action native A_JumpIfTargetInsideMeleeRange(state label);
action native A_JumpIfInventory(class<Inventory> itemtype, int itemamount, state label, int owner = AAPTR_DEFAULT);
@ -249,7 +249,7 @@ ACTOR Actor native //: Thinker
action native A_PlayerSkinCheck(state label);
action native A_BasicAttack(int meleedamage, sound meleesound, class<actor> missiletype, float missileheight);
action native A_Teleport(state teleportstate = "", class<SpecialSpot> targettype = "BossSpot", class<Actor> fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0, int ptr = AAPTR_DEFAULT);
action native A_Warp(int ptr_destination, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0, int flags = 0, state success_state = "", float heightoffset = 0);
action native A_Warp(int ptr_destination, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0, int flags = 0, state success_state = "", float heightoffset = 0, float radiusoffset = 0, float pitch = 0);
action native A_ThrowGrenade(class<Actor> itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true);
action native A_Weave(int xspeed, int yspeed, float xdist, float ydist);
@ -257,7 +257,7 @@ ACTOR Actor native //: Thinker
action native A_JumpIfInTargetInventory(class<Inventory> itemtype, int amount, state label, int forward_ptr = AAPTR_DEFAULT);
action native A_GiveToTarget(class<Inventory> itemtype, int amount = 0, int forward_ptr = AAPTR_DEFAULT);
action native A_TakeFromTarget(class<Inventory> itemtype, int amount = 0, int flags = 0, int forward_ptr = AAPTR_DEFAULT);
action native A_RadiusGive(class<Inventory> itemtype, int distance, int flags, int amount = 0, class<Actor> filter = "None", name species = "None");
action native A_RadiusGive(class<Inventory> itemtype, int distance, int flags, int amount = 0, class<Actor> filter = "None", name species = "None", int mindist = 0);
action native A_CountdownArg(int argnum, state targstate = "");
action native A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true);
action native A_CustomComboAttack(class<Actor> missiletype, float spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true);
@ -304,6 +304,8 @@ ACTOR Actor native //: Thinker
action native A_SetDamageType(name damagetype);
action native A_DropItem(class<Actor> item, int dropamount = -1, int chance = 256);
action native A_SetSpeed(float speed, int ptr = AAPTR_DEFAULT);
action native A_SetFloatSpeed(float speed, int ptr = AAPTR_DEFAULT);
action native A_SetPainThreshold(int threshold, int ptr = AAPTR_DEFAULT);
action native A_DamageSelf(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_DamageTarget(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
action native A_DamageMaster(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
@ -335,7 +337,8 @@ ACTOR Actor native //: Thinker
action native A_SetRipperLevel(int level);
action native A_SetRipMin(int min);
action native A_SetRipMax(int max);
action native A_CheckProximity(state jump, class<Actor> classname, float distance, int count = 1, int flags = 0, int ptr = AAPTR_DEFAULT);
action native A_CheckBlock(state block, int flags = 0, int ptr = AAPTR_DEFAULT);
action native A_CheckSightOrRange(float distance, state label, bool two_dimension = false);
action native A_CheckRange(float distance, state label, bool two_dimension = false);

View file

@ -188,6 +188,7 @@ const int CPF_STEALARMOR = 32;
// Flags for A_CustomMissile
const int FPF_AIMATANGLE = 1;
const int FPF_TRANSFERTRANSLATION = 2;
const int FPF_NOAUTOAIM = 4;
// Flags for A_Teleport
enum
@ -361,6 +362,8 @@ Const Int WARPF_ABSOLUTEPOSITION = 0x400;
Const Int WARPF_BOB = 0x800;
Const Int WARPF_MOVEPTR = 0x1000;
Const Int WARPF_USETID = 0x2000;
Const Int WARPF_COPYVELOCITY = 0x4000;
Const Int WARPF_COPYPITCH = 0x8000;
// flags for A_SetPitch/SetAngle/SetRoll
const int SPF_FORCECLAMP = 1;
@ -481,5 +484,28 @@ enum
QF_WAVE = 1 << 5,
};
// A_CheckProximity flags
enum
{
CPXF_ANCESTOR = 1,
CPXF_LESSOREQUAL = 1 << 1,
CPXF_NOZ = 1 << 2,
CPXF_COUNTDEAD = 1 << 3,
CPXF_DEADONLY = 1 << 4,
CPXF_EXACT = 1 << 5,
};
// Flags for A_CheckBlock
// These flags only affect the calling actor('s pointer), not the ones being searched.
enum
{
CBF_NOLINES = 1 << 0, //Don't check actors.
CBF_SETTARGET = 1 << 1, //Sets the caller/pointer's target to the actor blocking it. Actors only.
CBF_SETMASTER = 1 << 2, //^ but with master.
CBF_SETTRACER = 1 << 3, //^ but with tracer.
CBF_SETONPTR = 1 << 4, //Sets the pointer change on the actor doing the checking instead of self.
};
// This is only here to provide one global variable for testing.
native int testglobalvar;

View file

@ -30,9 +30,9 @@ ACTOR Fatso
Missile:
FATT G 20 A_FatRaise
FATT H 10 BRIGHT A_FatAttack1
FATT IG 5
FATT IG 5 A_FaceTarget
FATT H 10 BRIGHT A_FatAttack2
FATT IG 5
FATT IG 5 A_FaceTarget
FATT H 10 BRIGHT A_FatAttack3
FATT IG 5
Goto See

View file

@ -28,7 +28,7 @@ ACTOR CommanderKeen
KEEN AB 6
KEEN C 6 A_Scream
KEEN DEFGH 6
KEEN I 6 A_NoBlocking
KEEN I 6
KEEN J 6
KEEN K 6 A_KeenDie
KEEN L -1

View file

@ -802,6 +802,7 @@ ACTOR BlasterPuff
+NOGRAVITY
+PUFFONACTORS
RenderStyle Add
SeeSound "weapons/blasterhit"
States
{
Crash:

View file

@ -8,9 +8,9 @@ ACTOR Inventory native
Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG"
action native A_JumpIfNoAmmo(state label);
action native A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class<Actor> pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus");
action native A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class<Actor> pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus", sound MeleeSound = "", sound MissSound = "");
action native A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", int flags = 1, float range = 0);
action native A_FireCustomMissile(class<Actor> missiletype, float angle = 0, bool useammo = true, int spawnofs_xy = 0, float spawnheight = 0, bool aimatangle = false, float pitch = 0);
action native A_FireCustomMissile(class<Actor> missiletype, float angle = 0, bool useammo = true, int spawnofs_xy = 0, float spawnheight = 0, int flags = 0, float pitch = 0);
action native A_RailAttack(int damage, int spawnofs_xy = 0, int useammo = true, color color1 = "", color color2 = "", int flags = 0, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270);
action native A_Light(int extralight);
action native A_Light0();

View file

@ -44,7 +44,7 @@ ACTOR Macil1
Death:
LEAD E 2 A_FaceTarget
LEAD F 2 BRIGHT A_ShootGun
LEAD E 2 A_SentinelRefire
LEAD E 1 A_SentinelRefire
Loop
Pain:
LEAD Y 3
@ -80,7 +80,7 @@ ACTOR Macil2 : Macil1
LEAD K 3
LEAD L 3 A_NoBlocking
LEAD MNOPQRSTUV 3
LEAD W 4 Bright A_SpawnItemEx("AlienSpectre4", 0, 0, 0, 0, 0, random[spectrespawn](0,255)*0.0078125, 0, SXF_NOCHECKPOSITION)
LEAD W 3 A_SpawnItemEx("AlienSpectre4", 0, 0, 0, 0, 0, random[spectrespawn](0,255)*0.0078125, 0, SXF_NOCHECKPOSITION)
LEAD X -1
Stop
}

View file

@ -55,6 +55,8 @@ A80E7EE40E0D0C76A6FBD242BE29FE27 // map15
{
stairs
maskedmidtex
corpsegibs
vileghosts
}
10E1E2B36302D31AC4AE68C84B5DC457 // Eternal Doom MAP28
@ -125,7 +127,6 @@ BA530202AF0BA0C6CBAE6A0C7076FB72 // Requiem map04
CBDFEFAC579A62DE8F1B48CA4A09D381 // gather2.wad map05 and darkside.wad map01
C7A2FAFB0AFB2632C50AD625CDB50E51 // Reverie map18
9E5724BC6135AA6F86EE54FD4D91F1E2 // Project X map14
6DA6FCBA8089161BDEC6A1D3F6C8D60F // Eternal Doom map25
01899825FFEAE016D39C02A7DA4B218F // Archie map01
1D9F3AFDC2517C2E450491ED13896712 // Seej map01
0AE745A3AB86D15FB2FB74489962C421 // 6pack2 map02
@ -320,8 +321,7 @@ F481922F4881F74760F3C0437FD5EDD0 // map03
7C1913DEE396BA26CFF22A0E9369B7D2 // Nuke Mine, e1m2
{
clearlinespecial 1107
clearlinespecial 1108
pointonline
}
5B862477519B21B30059A466F2FF6460 // Khorus, map08
@ -397,6 +397,16 @@ A53AE580A4AF2B5D0B0893F86914781E // TNT: Evilution map31
setthingflags 470 2016
}
D0139194F7817BF06F3988DFC47DB38D // Whispers of Satan map29
{
nopassover
}
D7F6E9F08C39A17026349A04F8C0B0BE // Return to Hadron, e1m9
{
pointonline
}
712BB4CFBD0753178CA0C6814BE4C288 // map12 BTSX_E1 - patch some rendering glitches that are problematic to detect
{
setsectortag 545 32000
@ -409,4 +419,3 @@ A53AE580A4AF2B5D0B0893F86914781E // TNT: Evilution map31
setsectortag 910 32002
setlinespecial 2410 Sector_Set3DFloor 32002 4 1 0 0
}

View file

@ -534,7 +534,13 @@ SoundMap
"skeleton/active",
"skeleton/sight",
"skeleton/attack",
"misc/chat"
"misc/chat",
"dog/sight",
"dog/attack",
"dog/active",
"dog/death",
"dog/pain",
};
// Names of different actor types, in original Doom 2 order

View file

@ -1550,6 +1550,10 @@ TXT_RANDOMGOODBYE_3 = "See you later!";
TXT_HAVEENOUGH = "You seem to have enough!";
TXT_GOAWAY = "Go away!";
TXT_COMM0 = "Incoming Message";
TXT_COMM1 = "Incoming Message from BlackBird";
// Skills:
SKILL_BABY = "I'm too young to die";

View file

@ -56,4 +56,12 @@ gameinfo
statscreen_enteringpatch = "WIENTER"
}
DoomEdNums
{
4001 = "$Player5Start"
4002 = "$Player6Start"
4003 = "$Player7Start"
4004 = "$Player8Start"
}
include "mapinfo/common.txt"

View file

@ -456,6 +456,7 @@ OptionMenu "CustomizeControls"
Control "Look down", "+lookdown"
Control "Center view", "centerview"
Control "Run", "+speed"
Control "Toggle Run", "toggle cl_run"
Control "Strafe", "+strafe"
Control "Show Scoreboard", "+showscores"
Control "Toggle Scoreboard", "togglescoreboard"
@ -1303,6 +1304,7 @@ OptionMenu "CompatibilityOptions"
Option "Find shortest textures like Doom", "compat_SHORTTEX", "YesNo"
Option "Use buggier stair building", "compat_stairs", "YesNo"
Option "Use Doom's floor motion behavior", "compat_floormove", "YesNo"
Option "Use Doom's point-on-line algorithm", "compat_pointonline", "YesNo"
StaticText " "
StaticText "Physics Behavior",1
@ -1588,10 +1590,24 @@ OptionMenu AdvSoundOptions
Option "OPL Emulator Core", "opl_core", "OplCores"
StaticText " "
StaticText "GUS Emulation", 1
TextField "GUS config file", "midi_config"
Slider "MIDI voices", "midi_voices", 16, 256, 4, 0
Option "Emulate TiMidity", "midi_timiditylike", "OnOff"
Option "Read DMXGUS lumps", "midi_dmxgus", "OnOff"
Option "GUS memory size", "gus_memsize", "GusMemory"
StaticText " "
StaticText "FluidSynth", 1
TextField "Patch set", "fluid_patchset"
Slider "Gain", "fluid_gain", 0, 10, 0.5, 1
Option "Reverb", "fluid_reverb", "OnOff"
Slider "MIDI voices", "fluid_voices", 16, 4096, 16, 1
// Leaving out the more advanced stuff for now.
StaticText " "
StaticText "Timidity++", 1
TextField "Path for executable", "timidity_exe"
Option "Reverb", "timidity_reverb", "OnOff"
Option "Chorus", "timidity_chorus", "OnOff"
Slider "Relative volume", "timidity_mastervolume", 0, 4, 0.2, 1
}
/*=======================================