Merge branch 'master' into WildMidi

This commit is contained in:
Christoph Oelckers 2015-12-28 21:01:17 +01:00
commit a94120b6a4
52 changed files with 430 additions and 402 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

@ -496,6 +496,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

@ -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

@ -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(","));
}

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)
{

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

@ -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

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

View file

@ -1264,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;
@ -1275,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;
}
@ -4442,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),
@ -5315,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:
@ -5914,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;
}
@ -7854,7 +7879,7 @@ scriptwait:
}
break;
}
msg->SetClipRect(ClipRectLeft, ClipRectTop, ClipRectWidth, ClipRectHeight);
msg->SetClipRect(ClipRectLeft, ClipRectTop, ClipRectWidth, ClipRectHeight, HandleAspect);
if (WrapWidth != 0)
{
msg->SetWrapWidth(WrapWidth);
@ -8337,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;
@ -9466,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

@ -1347,9 +1347,10 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
int rootnode = npc->ConversationRoot;
if (reply->NextNode < 0)
{
npc->Conversation = StrifeDialogues[rootnode - reply->NextNode - 1];
if (gameaction != ga_slideshow)
unsigned next = (unsigned)(rootnode - reply->NextNode - 1);
if (gameaction != ga_slideshow && next < StrifeDialogues.Size())
{
npc->Conversation = StrifeDialogues[next];
P_StartConversation (npc, player->mo, player->ConversationFaceTalker, false);
return;
}

View file

@ -1639,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

@ -1600,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)
{
@ -1616,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;

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)
{

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;

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;
}

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

@ -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

@ -566,6 +566,10 @@ void APlayerPawn::Serialize (FArchive &arc)
{
arc << AirCapacity;
}
if (SaveVersion >= 4526)
{
arc << ViewHeight;
}
}
//===========================================================================

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>

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

@ -1414,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;
@ -1443,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))
{
@ -1474,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))
@ -5886,6 +5893,103 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRipMax)
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)
@ -5944,4 +6048,4 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock)
{
ACTION_JUMP(block);
}
}
}

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 4526
#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

@ -1726,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

@ -337,6 +337,7 @@ 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

@ -484,6 +484,17 @@ 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

View file

@ -8,7 +8,7 @@ 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, 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);

View file

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