diff --git a/polymer/eduke32/Makefile b/polymer/eduke32/Makefile index f59df8b93..d86ae9000 100644 --- a/polymer/eduke32/Makefile +++ b/polymer/eduke32/Makefile @@ -220,7 +220,7 @@ MAPSTER32_TARGET:=$(MAPSTER32)$(EXESUFFIX) COMMON_OBJS=rev COMMON_EDITOR_OBJS=m32common m32def m32exec m32vars mathutil rev -DUKE3D_OBJS=game actors anim common config demo gamedef gameexec gamevars global input menus namesdyn net player premap savegame sector rts osdfuncs osdcmds grpscan sounds soundsdyn $(MACT_OBJ) +DUKE3D_OBJS=game global actors gamedef gameexec gamevars player premap sector anim animsounds common config demo input menus namesdyn net savegame rts osdfuncs osdcmds grpscan sounds soundsdyn $(MACT_OBJ) DUKE3D_EDITOR_OBJS=astub common grpscan sounds_mapster32 ifneq ($(USE_LIBVPX),0) diff --git a/polymer/eduke32/Makefile.deps b/polymer/eduke32/Makefile.deps index 1cb0b182d..b24ade034 100644 --- a/polymer/eduke32/Makefile.deps +++ b/polymer/eduke32/Makefile.deps @@ -38,7 +38,8 @@ game_defs_dep=$(DUKE3D_SRC)/lunatic/defs.ilua $(DUKE3D_OBJ)/game.$o: $(DUKE3D_SRC)/game.c $(game_defs_dep) $(DUKE3D_SRC)/jmact/scriplib.h $(duke3d_h) $(DUKE3D_SRC)/input.h $(DUKE3D_INC)/osdfuncs.h $(DUKE3D_INC)/osdcmds.h $(DUKE3D_INC)/grpscan.h $(DUKE3D_INC)/demo.h $(ENGINE_INC)/hightile.h $(DUKE3D_OBJ)/actors.$o: $(DUKE3D_SRC)/actors.c $(duke3d_h) -$(DUKE3D_OBJ)/anim.$o: $(DUKE3D_SRC)/anim.c $(duke3d_h) $(DUKE3D_SRC)/input.h $(DUKE3D_SRC)/jmact/animlib.h $(DUKE3D_SRC)/animvpx.h +$(DUKE3D_OBJ)/anim.$o: $(DUKE3D_SRC)/anim.c $(duke3d_h) $(DUKE3D_SRC)/input.h $(DUKE3D_SRC)/jmact/animlib.h $(DUKE3D_SRC)/animvpx.h $(DUKE3D_SRC)/animsounds.h +$(DUKE3D_OBJ)/animsounds.$o: $(DUKE3D_SRC)/animsounds.c $(DUKE3D_SRC)/animsounds.h $(DUKE3D_OBJ)/demo.$o: $(DUKE3D_SRC)/demo.c $(duke3d_h) $(DUKE3D_SRC)/input.h $(DUKE3D_OBJ)/gamedef.$o: $(DUKE3D_SRC)/gamedef.c $(duke3d_h) $(gamedef_h) $(DUKE3D_SRC)/savegame.h $(DUKE3D_OBJ)/gameexec.$o: $(DUKE3D_SRC)/gameexec.c $(DUKE3D_SRC)/gamestructures.c $(duke3d_h) $(gamedef_h) diff --git a/polymer/eduke32/Makefile.msvc b/polymer/eduke32/Makefile.msvc index 690f0ef45..81eb5d6fb 100644 --- a/polymer/eduke32/Makefile.msvc +++ b/polymer/eduke32/Makefile.msvc @@ -190,6 +190,7 @@ DUKE3D_OBJS=$(DUKE3D_OBJ)\game.$o \ $(DUKE3D_OBJ)\actors.$o \ $(DUKE3D_OBJ)\actors_inline.$o \ $(DUKE3D_OBJ)\anim.$o \ + $(DUKE3D_OBJ)\animsounds.$o \ $(DUKE3D_OBJ)\animvpx.$o \ $(DUKE3D_OBJ)\common.$o \ $(DUKE3D_OBJ)\demo.$o \ diff --git a/polymer/eduke32/build/src/defs.c b/polymer/eduke32/build/src/defs.c index 2b8e9a07f..077ce98bb 100644 --- a/polymer/eduke32/build/src/defs.c +++ b/polymer/eduke32/build/src/defs.c @@ -86,6 +86,7 @@ enum scripttoken_t T_TILEFROMTEXTURE, T_XOFFSET, T_YOFFSET, T_TEXHITSCAN, T_NOFULLBRIGHT, T_INCLUDEDEFAULT, T_ANIMSOUNDS, + T_CUTSCENE, T_NOFLOORPALRANGE, T_TEXHITSCANRANGE, T_NOFULLBRIGHTRANGE, @@ -250,6 +251,7 @@ static int32_t defsparser(scriptfile *script) { "music", T_MUSIC }, { "sound", T_SOUND }, { "animsounds", T_ANIMSOUNDS }, // dummy + { "cutscene", T_CUTSCENE }, { "nofloorpalrange", T_NOFLOORPALRANGE }, { "texhitscanrange", T_TEXHITSCANRANGE }, { "nofullbrightrange", T_NOFULLBRIGHTRANGE }, @@ -2073,6 +2075,7 @@ static int32_t defsparser(scriptfile *script) } break; + case T_CUTSCENE: case T_ANIMSOUNDS: { char *dummy; diff --git a/polymer/eduke32/eduke32.vcxproj b/polymer/eduke32/eduke32.vcxproj index e2993eada..4e2d1fca6 100644 --- a/polymer/eduke32/eduke32.vcxproj +++ b/polymer/eduke32/eduke32.vcxproj @@ -293,9 +293,11 @@ + + @@ -407,6 +409,7 @@ + diff --git a/polymer/eduke32/eduke32.vcxproj.filters b/polymer/eduke32/eduke32.vcxproj.filters index ef0cec099..9816ee6c5 100644 --- a/polymer/eduke32/eduke32.vcxproj.filters +++ b/polymer/eduke32/eduke32.vcxproj.filters @@ -363,6 +363,9 @@ eduke32\headers + + eduke32\headers + eduke32\headers @@ -453,6 +456,9 @@ build\headers + + eduke32\headers + @@ -785,6 +791,9 @@ build\source + + eduke32\source + diff --git a/polymer/eduke32/source/anim.c b/polymer/eduke32/source/anim.c index e8afd3225..97cf9b15a 100644 --- a/polymer/eduke32/source/anim.c +++ b/polymer/eduke32/source/anim.c @@ -32,228 +32,77 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifdef USE_LIBVPX # include "animvpx.h" - -uint16_t anim_hi_numsounds[NUM_HARDCODED_ANIMS], *anim_hi_sounds[NUM_HARDCODED_ANIMS]; #endif -static void endanimsounds(int32_t fr) +#include "animsounds.h" + +hashtable_t h_dukeanim = { 8, NULL }; +dukeanim_t * g_animPtr; + +dukeanim_t *G_FindAnim(const char *s) { - switch (ud.volume_number) - { - case 0: - break; - case 1: - switch (fr) - { - case 1: - S_PlaySound(WIND_AMBIENCE); - break; - case 26: - S_PlaySound(ENDSEQVOL2SND1); - break; - case 36: - S_PlaySound(ENDSEQVOL2SND2); - break; - case 54: - S_PlaySound(THUD); - break; - case 62: - S_PlaySound(ENDSEQVOL2SND3); - break; - case 75: - S_PlaySound(ENDSEQVOL2SND4); - break; - case 81: - S_PlaySound(ENDSEQVOL2SND5); - break; - case 115: - S_PlaySound(ENDSEQVOL2SND6); - break; - case 124: - S_PlaySound(ENDSEQVOL2SND7); - break; - } - break; - case 2: - switch (fr) - { - case 1: - S_PlaySound(WIND_REPEAT); - break; - case 98: - S_PlaySound(DUKE_GRUNT); - break; - case 82+20: - S_PlaySound(THUD); - S_PlaySound(SQUISHED); - break; - case 104+20: - S_PlaySound(ENDSEQVOL3SND3); - break; - case 114+20: - S_PlaySound(ENDSEQVOL3SND2); - break; - case 158: - S_PlaySound(PIPEBOMB_EXPLODE); - break; - } - break; - } + intptr_t ptr = hash_findcase(&h_dukeanim, s); + return (dukeanim_t *)(ptr == -1 ? NULL : (dukeanim_t *)ptr); } -static void logoanimsounds(int32_t fr) +dukeanim_t * G_DefineAnim(const char *fn, uint8_t fdelay, void (*sound_func)(int32_t)) { - switch (fr) - { - case 1: - S_PlaySound(FLY_BY); - break; - case 19: - S_PlaySound(PIPEBOMB_EXPLODE); - break; - } + dukeanim_t * anim = G_FindAnim(fn); + + if (!anim) + anim = (dukeanim_t *)Xcalloc(1, sizeof(dukeanim_t)); + + hash_add(&h_dukeanim, fn, (intptr_t)anim, 0); + + if (sound_func) + anim->sound_func = sound_func; + + anim->framedelay = fdelay; + + return anim; } -static void intro4animsounds(int32_t fr) +void G_InitAnim(void) { - switch (fr) - { - case 1: - S_PlaySound(INTRO4_B); - break; - case 12: - case 34: - S_PlaySound(SHORT_CIRCUIT); - break; - case 18: - S_PlaySound(INTRO4_5); - break; - } + hash_init(&h_dukeanim); + + G_DefineAnim("logo.anm", 9, logoanimsounds); + G_DefineAnim("3dr.anm", 10, NULL); + G_DefineAnim("vol4e1.anm", 10, endanimvol41); + G_DefineAnim("vol4e2.anm", 14, endanimvol42); + G_DefineAnim("vol4e3.anm", 10, endanimvol43); + G_DefineAnim("vol41a.anm", 14, first4animsounds); + G_DefineAnim("vol42a.anm", 18, intro4animsounds); + G_DefineAnim("vol43a.anm", 10, intro42animsounds); + G_DefineAnim("duketeam.anm", 10, NULL); + G_DefineAnim("radlogo.anm", 10, NULL); + G_DefineAnim("cineov2.anm", 18, endanimsounds); + G_DefineAnim("cineov3.anm", 10, endanimsounds); } -static void first4animsounds(int32_t fr) +int32_t G_PlayAnim(const char *fn) { - switch (fr) + dukeanim_t *anim = G_FindAnim(fn); + + if (!anim) { - case 1: - S_PlaySound(INTRO4_1); - break; - case 12: - S_PlaySound(INTRO4_2); - break; - case 7: - S_PlaySound(INTRO4_3); - break; - case 26: - S_PlaySound(INTRO4_4); - break; + OSD_Printf("Animation %s is undefined!\n", fn); + return 0; } -} -static void intro42animsounds(int32_t fr) -{ - switch (fr) - { - case 10: - S_PlaySound(INTRO4_6); - break; - } -} - -static void endanimvol41(int32_t fr) -{ - switch (fr) - { - case 3: - S_PlaySound(DUKE_UNDERWATER); - break; - case 35: - S_PlaySound(VOL4ENDSND1); - break; - } -} - -static void endanimvol42(int32_t fr) -{ - switch (fr) - { - case 11: - S_PlaySound(DUKE_UNDERWATER); - break; - case 20: - S_PlaySound(VOL4ENDSND1); - break; - case 39: - S_PlaySound(VOL4ENDSND2); - break; - case 50: - FX_StopAllSounds(); - break; - } -} - -static void endanimvol43(int32_t fr) -{ - switch (fr) - { - case 1: - S_PlaySound(BOSS4_DEADSPEECH); - break; - case 40: - S_PlaySound(VOL4ENDSND1); - S_PlaySound(DUKE_UNDERWATER); - break; - case 50: - S_PlaySound(BIGBANG); - break; - } -} - -static uint8_t* animbuf[NUM_HARDCODED_ANIMS]; -static char animlock[NUM_HARDCODED_ANIMS]; - -int32_t G_PlayAnim(const char *fn, char t) -{ - int32_t i, length=0, numframes=0; -#ifdef USE_OPENGL - int32_t ogltexfiltermode=gltexfiltermode; -#endif - int32_t handle=-1; - int32_t frametime = 0; - int32_t running = 1; - - // t parameter: - // - // 1: cineov2 - // 2: cineov3 - // 3: RADLOGO - // 4: DUKETEAM - // 5: logo - // 6: vol41a - // 7: vol42a - // 8: vol4e1 - // 9: vol43a - // 10: vol4e2 - // 11: vol4e3 - // 12: 3drealms anim + int32_t framenum = 0, soundidx = 0; // custom anim sounds + int32_t running = 1, i; I_ClearAllInput(); #ifdef USE_LIBVPX while (getrendermode() >= REND_POLYMOST && glinfo.glsl) // if, really { - char vpxfn[BMAX_PATH], *dot; - animvpx_ivf_header_t info; - - animvpx_codec_ctx codec; - uint8_t *pic; - uint32_t msecsperframe, nextframetime; - int32_t animidx, framenum=0, soundidx=0, numtotalsounds=0; // custom anim sounds - + char vpxfn[BMAX_PATH]; Bstrncpyz(vpxfn, fn, BMAX_PATH); - dot = Bstrrchr(vpxfn, '.'); - if (!dot || (dot-vpxfn)+4 >= BMAX_PATH) + char *dot = Bstrrchr(vpxfn, '.'); + if (!dot || (dot - vpxfn) + 4 >= BMAX_PATH) break; dot[1] = 'i'; @@ -261,20 +110,24 @@ int32_t G_PlayAnim(const char *fn, char t) dot[3] = 'f'; dot[4] = 0; - handle = kopen4loadfrommod(vpxfn, 0); + int32_t handle = kopen4loadfrommod(vpxfn, 0); if (handle == -1) break; + animvpx_ivf_header_t info; i = animvpx_read_ivf_header(handle, &info); + if (i) { - OSD_Printf("Failed reading IVF file: %s\n", - animvpx_read_ivf_header_errmsg[i]); + OSD_Printf("Failed reading IVF file: %s\n", animvpx_read_ivf_header_errmsg[i]); kclose(handle); return 0; } animvpx_setup_glstate(); + + animvpx_codec_ctx codec; + if (animvpx_init_codec(&info, handle, &codec)) { OSD_Printf("Error initializing VPX codec.\n"); @@ -282,24 +135,20 @@ int32_t G_PlayAnim(const char *fn, char t) return 0; } - animidx = t-1; - if ((unsigned)animidx < NUM_HARDCODED_ANIMS && anim_hi_sounds[animidx]) - numtotalsounds = anim_hi_numsounds[animidx]; + uint32_t msecsperframe = ((uint64_t)info.fpsdenom * 1000) / info.fpsnumer; + uint32_t nextframetime = getticks(); + uint8_t *pic; - msecsperframe = ((uint64_t)info.fpsdenom*1000)/info.fpsnumer; -// OSD_Printf("msecs per frame: %d\n", msecsperframe); + // OSD_Printf("msecs per frame: %d\n", msecsperframe); - nextframetime = getticks(); - - while (running) + do { nextframetime += msecsperframe; i = animvpx_nextpic(&codec, &pic); if (i) { - OSD_Printf("Failed getting next pic: %s\n", - animvpx_nextpic_errmsg[i]); + OSD_Printf("Failed getting next pic: %s\n", animvpx_nextpic_errmsg[i]); if (codec.errmsg) { OSD_Printf(" %s\n", codec.errmsg); @@ -316,9 +165,9 @@ int32_t G_PlayAnim(const char *fn, char t) // after rendering the frame but before displaying: maybe play sound... framenum++; - while (soundidx < numtotalsounds && anim_hi_sounds[animidx][2*soundidx] == framenum) + while (soundidx < anim->numsounds && anim->sounds[soundidx << 1] == framenum) { - S_PlaySound(anim_hi_sounds[animidx][2*soundidx+1]); + S_PlaySound(anim->sounds[(soundidx << 1) + 1]); soundidx++; } @@ -327,7 +176,7 @@ int32_t G_PlayAnim(const char *fn, char t) palfadedelta = 0; showframe(0); -// I_ClearAllInput(); + // I_ClearAllInput(); do { @@ -338,9 +187,8 @@ int32_t G_PlayAnim(const char *fn, char t) running = 0; break; } - } - while (getticks() < nextframetime); - } + } while (getticks() < nextframetime); + } while (running); animvpx_print_stats(&codec); @@ -353,32 +201,39 @@ int32_t G_PlayAnim(const char *fn, char t) return !running; // done with playing VP8! } #endif - // ANM playback --- v v v --- +// ANM playback --- v v v --- + +#ifdef USE_OPENGL + int32_t ogltexfiltermode = gltexfiltermode; +#endif + int32_t handle = kopen4load(fn, 0); - handle = kopen4load(fn, 0); if (handle == -1) return 0; - length = kfilelength(handle); + int32_t length = kfilelength(handle); + if (length == 0) { OSD_Printf("Warning: skipping playback of empty ANM file \"%s\".\n", fn); goto end_anim; } - walock[TILE_ANIM] = 219+t; - animlock[t-1] = 1; + walock[TILE_ANIM] = 219; + anim->animlock = 1; - if (!animbuf[t-1]) - allocache((intptr_t *)&animbuf[t-1], length+1, &animlock[t-1]); + if (!anim->animbuf) + allocache((intptr_t *)&anim->animbuf, length + 1, &anim->animlock); tilesiz[TILE_ANIM].x = 200; tilesiz[TILE_ANIM].y = 320; - kread(handle, animbuf[t-1], length); + kread(handle, anim->animbuf, length); kclose(handle); - if (ANIM_LoadAnim(animbuf[t-1], length) < 0 || (numframes = ANIM_NumFrames()) <= 0) + int32_t numframes; + + if (ANIM_LoadAnim(anim->animbuf, length) < 0 || (numframes = ANIM_NumFrames()) <= 0) { // XXX: ANM_LoadAnim() still checks less than the bare minimum, // e.g. ANM file could still be too small and not contain any frames. @@ -388,9 +243,9 @@ int32_t G_PlayAnim(const char *fn, char t) basepaltable[ANIMPAL] = ANIM_GetPalette(); - //setpalette(0L,256L,tempbuf); - //setbrightness(ud.brightness>>2,tempbuf,2); - P_SetGamePalette(g_player[myconnectindex].ps, ANIMPAL, 8+2); + // setpalette(0L,256L,tempbuf); + // setbrightness(ud.brightness>>2,tempbuf,2); + P_SetGamePalette(g_player[myconnectindex].ps, ANIMPAL, 8 + 2); #ifdef USE_OPENGL gltexfiltermode = 0; @@ -400,6 +255,7 @@ int32_t G_PlayAnim(const char *fn, char t) ototalclock = totalclock + 10; i = 1; + int32_t frametime; frametime = 0; do { @@ -411,11 +267,11 @@ int32_t G_PlayAnim(const char *fn, char t) G_HandleAsync(); - if (totalclock < ototalclock-1) + if (totalclock < ototalclock - 1) continue; - waloff[TILE_ANIM] = (intptr_t) ANIM_DrawFrame(i); - invalidatetile(TILE_ANIM, 0, 1<<4); // JBF 20031228 + waloff[TILE_ANIM] = (intptr_t)ANIM_DrawFrame(i); + invalidatetile(TILE_ANIM, 0, 1 << 4); // JBF 20031228 if (I_CheckAllInput()) { @@ -433,30 +289,28 @@ int32_t G_PlayAnim(const char *fn, char t) clearallviews(0); - rotatesprite_fs(0<<16, 0<<16, 65536L, 512, TILE_ANIM, 0, 0, 2+4+8+16+64+(ud.bgstretch ? 1024 : 0)); + rotatesprite_fs(0 << 16, 0 << 16, 65536L, 512, TILE_ANIM, 0, 0, 2 + 4 + 8 + 16 + 64 + BGSTRETCH); + + g_animPtr = anim; + i = VM_OnEventWithReturn(EVENT_CUTSCENE, -1, myconnectindex, i); + g_animPtr = NULL; + nextpage(); I_ClearAllInput(); - if (t == 10) ototalclock += 14; - else if (t == 9) ototalclock += 10; - else if (t == 7) ototalclock += 18; - else if (t == 6) ototalclock += 14; - else if (t == 5) ototalclock += 9; - else if (ud.volume_number == 3) ototalclock += 10; - else if (ud.volume_number == 2) ototalclock += 10; - else if (ud.volume_number == 1) ototalclock += 18; - else ototalclock += 10; + ototalclock += anim->framedelay; - if (t == 8) endanimvol41(i); - else if (t == 10) endanimvol42(i); - else if (t == 11) endanimvol43(i); - else if (t == 9) intro42animsounds(i); - else if (t == 7) intro4animsounds(i); - else if (t == 6) first4animsounds(i); - else if (t == 5) logoanimsounds(i); - else if (t < 4) endanimsounds(i); - i++; + if (!anim->numsounds && anim->sound_func) + anim->sound_func(i); + + framenum = i++; + + while (soundidx < anim->numsounds && anim->sounds[soundidx << 1] == framenum) + { + S_PlaySound(anim->sounds[(soundidx << 1) + 1]); + soundidx++; + } } while (i < numframes); end_anim_restore_gl: @@ -468,7 +322,7 @@ end_anim: I_ClearAllInput(); ANIM_FreeAnim(); walock[TILE_ANIM] = 1; - animlock[t-1] = 0; + anim->animlock = 0; return !running; } diff --git a/polymer/eduke32/source/anim.h b/polymer/eduke32/source/anim.h index 42564280b..670cf28b3 100644 --- a/polymer/eduke32/source/anim.h +++ b/polymer/eduke32/source/anim.h @@ -25,19 +25,21 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define NUM_HARDCODED_ANIMS 12 -# ifdef USE_LIBVPX -extern uint16_t anim_hi_numsounds[NUM_HARDCODED_ANIMS], *anim_hi_sounds[NUM_HARDCODED_ANIMS]; -# endif +typedef struct +{ + uint8_t* animbuf; + void (*sound_func)(int32_t); + uint16_t *sounds; + int16_t numsounds; + uint8_t framedelay; + char animlock; +} dukeanim_t; + +extern dukeanim_t * g_animPtr; +extern hashtable_t h_dukeanim; +extern dukeanim_t * G_FindAnim(const char *s); +extern dukeanim_t * G_DefineAnim(const char *fn, uint8_t framerate, void (*sound_func)(int32_t)); +int32_t G_PlayAnim(const char *fn); +void G_InitAnim(void); -int32_t G_PlayAnim(const char *fn,char t); -/* -void endanimvol43(int32_t fr); -void endanimvol42(int32_t fr); -void endanimvol41(int32_t fr); -void intro42animsounds(int32_t fr); -void first4animsounds(int32_t fr); -void intro4animsounds(int32_t fr); -void logoanimsounds(int32_t fr); -void endanimsounds(int32_t fr); -*/ #endif diff --git a/polymer/eduke32/source/animsounds.c b/polymer/eduke32/source/animsounds.c new file mode 100644 index 000000000..e9c6677b7 --- /dev/null +++ b/polymer/eduke32/source/animsounds.c @@ -0,0 +1,197 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 2015 EDuke32 developers and contributors + +This file is part of EDuke32. + +EDuke32 is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License version 2 +as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +//------------------------------------------------------------------------- + +#include "duke3d.h" +#include "animsounds.h" + +void endanimsounds(int32_t fr) +{ + switch (ud.volume_number) + { + case 0: + break; + case 1: + switch (fr) + { + case 1: + S_PlaySound(WIND_AMBIENCE); + break; + case 26: + S_PlaySound(ENDSEQVOL2SND1); + break; + case 36: + S_PlaySound(ENDSEQVOL2SND2); + break; + case 54: + S_PlaySound(THUD); + break; + case 62: + S_PlaySound(ENDSEQVOL2SND3); + break; + case 75: + S_PlaySound(ENDSEQVOL2SND4); + break; + case 81: + S_PlaySound(ENDSEQVOL2SND5); + break; + case 115: + S_PlaySound(ENDSEQVOL2SND6); + break; + case 124: + S_PlaySound(ENDSEQVOL2SND7); + break; + } + break; + case 2: + switch (fr) + { + case 1: + S_PlaySound(WIND_REPEAT); + break; + case 98: + S_PlaySound(DUKE_GRUNT); + break; + case 82+20: + S_PlaySound(THUD); + S_PlaySound(SQUISHED); + break; + case 104+20: + S_PlaySound(ENDSEQVOL3SND3); + break; + case 114+20: + S_PlaySound(ENDSEQVOL3SND2); + break; + case 158: + S_PlaySound(PIPEBOMB_EXPLODE); + break; + } + break; + } +} + +void logoanimsounds(int32_t fr) +{ + switch (fr) + { + case 1: + S_PlaySound(FLY_BY); + break; + case 19: + S_PlaySound(PIPEBOMB_EXPLODE); + break; + } +} + +void intro4animsounds(int32_t fr) +{ + switch (fr) + { + case 1: + S_PlaySound(INTRO4_B); + break; + case 12: + case 34: + S_PlaySound(SHORT_CIRCUIT); + break; + case 18: + S_PlaySound(INTRO4_5); + break; + } +} + +void first4animsounds(int32_t fr) +{ + switch (fr) + { + case 1: + S_PlaySound(INTRO4_1); + break; + case 12: + S_PlaySound(INTRO4_2); + break; + case 7: + S_PlaySound(INTRO4_3); + break; + case 26: + S_PlaySound(INTRO4_4); + break; + } +} + +void intro42animsounds(int32_t fr) +{ + switch (fr) + { + case 10: + S_PlaySound(INTRO4_6); + break; + } +} + +void endanimvol41(int32_t fr) +{ + switch (fr) + { + case 3: + S_PlaySound(DUKE_UNDERWATER); + break; + case 35: + S_PlaySound(VOL4ENDSND1); + break; + } +} + +void endanimvol42(int32_t fr) +{ + switch (fr) + { + case 11: + S_PlaySound(DUKE_UNDERWATER); + break; + case 20: + S_PlaySound(VOL4ENDSND1); + break; + case 39: + S_PlaySound(VOL4ENDSND2); + break; + case 50: + FX_StopAllSounds(); + break; + } +} + +void endanimvol43(int32_t fr) +{ + switch (fr) + { + case 1: + S_PlaySound(BOSS4_DEADSPEECH); + break; + case 40: + S_PlaySound(VOL4ENDSND1); + S_PlaySound(DUKE_UNDERWATER); + break; + case 50: + S_PlaySound(BIGBANG); + break; + } +} diff --git a/polymer/eduke32/source/animsounds.h b/polymer/eduke32/source/animsounds.h new file mode 100644 index 000000000..64b070887 --- /dev/null +++ b/polymer/eduke32/source/animsounds.h @@ -0,0 +1,33 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 2015 EDuke32 developers and contributors + +This file is part of EDuke32. + +EDuke32 is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License version 2 +as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +//------------------------------------------------------------------------- + +#ifndef animsounds_h__ +#define animsounds_h__ +void endanimsounds(int32_t fr); +void logoanimsounds(int32_t fr); +void intro4animsounds(int32_t fr); +void endanimvol43(int32_t fr); +void endanimvol42(int32_t fr); +void endanimvol41(int32_t fr); +void intro42animsounds(int32_t fr); +void first4animsounds(int32_t fr); +#endif // animsounds_h__ diff --git a/polymer/eduke32/source/events_defs.h b/polymer/eduke32/source/events_defs.h index 1a5c3158e..197ba9d27 100644 --- a/polymer/eduke32/source/events_defs.h +++ b/polymer/eduke32/source/events_defs.h @@ -104,6 +104,7 @@ enum GameEvent_t { EVENT_ACTIVATECHEAT, EVENT_DISPLAYINACTIVEMENU, EVENT_DISPLAYINACTIVEMENUREST, + EVENT_CUTSCENE, #ifdef LUNATIC EVENT_ANIMATEALLSPRITES, #endif diff --git a/polymer/eduke32/source/game.c b/polymer/eduke32/source/game.c index 2538200ee..8b3775c10 100644 --- a/polymer/eduke32/source/game.c +++ b/polymer/eduke32/source/game.c @@ -222,9 +222,11 @@ enum gametokens T_MUSIC, T_SOUND, T_FILE, + T_CUTSCENE, T_ANIMSOUNDS, T_NOFLOORPALRANGE, - T_ID + T_ID, + T_DELAY }; @@ -3767,13 +3769,13 @@ void G_DisplayRest(int32_t smoothratio) { int32_t a = VM_OnEvent(EVENT_DISPLAYCROSSHAIR, g_player[screenpeek].ps->i, screenpeek); - if (a == 0 || a > 1) + if ((unsigned)a < MAXTILES) { - vec2_t crosshairpos = { 160<<16, 100<<16 }; - if (a == 0) a = CROSSHAIR; + vec2_t crosshairpos = { 160<<16, 100<<16 }; + rotatesprite_win(crosshairpos.x-(g_player[myconnectindex].ps->look_ang<<15),crosshairpos.y,scale(65536,ud.crosshairscale,100), 0,a,0,CROSSHAIR_PAL,2+1); @@ -3809,13 +3811,8 @@ void G_DisplayRest(int32_t smoothratio) #endif #ifdef USE_OPENGL - { - extern int32_t mdpause; - - mdpause = 0; - if (ud.pause_on || (ud.recstat==2 && (g_demo_paused && g_demo_goalCnt==0)) || (g_player[myconnectindex].ps->gm&MODE_MENU && numplayers < 2)) - mdpause = 1; - } + extern int32_t mdpause; + mdpause = (ud.pause_on || (ud.recstat==2 && (g_demo_paused && g_demo_goalCnt==0)) || (g_player[myconnectindex].ps->gm&MODE_MENU && numplayers < 2)); #endif G_PrintFPS(); @@ -3823,7 +3820,7 @@ void G_DisplayRest(int32_t smoothratio) // JBF 20040124: display level stats in screen corner if ((ud.overhead_on != 2 && ud.levelstats) && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0) { - const DukePlayer_t *myps = g_player[myconnectindex].ps; + DukePlayer_t const * const myps = g_player[myconnectindex].ps; if (ud.screen_size == 4) { @@ -9366,9 +9363,8 @@ static int32_t parsedefinitions_game(scriptfile *script, int32_t preload) { "noautoload", T_NOAUTOLOAD }, { "music", T_MUSIC }, { "sound", T_SOUND }, -#ifdef USE_LIBVPX + { "cutscene", T_CUTSCENE }, { "animsounds", T_ANIMSOUNDS }, -#endif }; static const tokenlist sound_musictokens[] = @@ -9377,6 +9373,11 @@ static int32_t parsedefinitions_game(scriptfile *script, int32_t preload) { "file", T_FILE }, }; + static const tokenlist animtokens [] = + { + { "delay", T_DELAY }, + }; + while (1) { tokn = getatoken(script,tokens,ARRAY_SIZE(tokens)); @@ -9471,50 +9472,75 @@ static int32_t parsedefinitions_game(scriptfile *script, int32_t preload) } break; -#ifdef USE_LIBVPX + case T_CUTSCENE: + { + int32_t delay = 10; + char *animend; + dukeanim_t *anim = NULL; + char *animname = NULL; + + scriptfile_getstring(script, &animname); + + if (scriptfile_getbraces(script, &animend)) + break; + + while (script->textptr < animend) + { + switch (getatoken(script, animtokens, ARRAY_SIZE(animtokens))) + { + case T_DELAY: scriptfile_getnumber(script, &delay); break; + } + } + +// if (!preload) + { +/* + if (check_file_exist(animname)) + break; +*/ + + anim = G_FindAnim(animname); + + if (!anim) + anim = G_DefineAnim(animname, delay, NULL); + else + anim->framedelay = delay; + } + } + break; case T_ANIMSOUNDS: { char *otokptr = script->ltextptr; char *animsoundsend = NULL; - int32_t animnum, numpairs=0, allocsz=4, bad=1, lastframenum=INT32_MIN; + int32_t numpairs = 0, allocsz = 4, bad = 1, lastframenum = INT32_MIN; + dukeanim_t *anim = NULL; + char *animname = NULL; - static const tokenlist hardcoded_anim_tokens[] = + scriptfile_getstring(script, &animname); + + if (animname) + anim = G_FindAnim(animname); + + if (!anim) { - { "cineov2", 0 }, - { "cineov3", 1 }, - { "RADLOGO", 2 }, - { "DUKETEAM", 3 }, - { "logo", 4 }, - { "vol41a", 5 }, - { "vol42a", 6 }, - { "vol4e1", 7 }, - { "vol43a", 8 }, - { "vol4e2", 9 }, - { "vol4e3", 10 }, - { "3dr", 11 }, - // NUM_HARDCODED_ANIMS - }; - - EDUKE32_STATIC_ASSERT(ARRAY_SIZE(hardcoded_anim_tokens) == NUM_HARDCODED_ANIMS); - - animnum = getatoken(script, hardcoded_anim_tokens, NUM_HARDCODED_ANIMS); - if ((unsigned)animnum >= NUM_HARDCODED_ANIMS) initprintf("Error: expected a hardcoded anim file name (sans extension) on line %s:%d\n", script->filename, scriptfile_getlinum(script, otokptr)); + break; + } - if (scriptfile_getbraces(script, &animsoundsend)) break; + if (scriptfile_getbraces(script, &animsoundsend)) + break; - if (anim_hi_sounds[animnum]) + if (anim->sounds) { - initprintf("Warning: overwriting already defined hi-anim %s's sounds on line %s:%d\n", - hardcoded_anim_tokens[animnum].text, script->filename, - scriptfile_getlinum(script, otokptr)); - Bfree(anim_hi_sounds[animnum]); - anim_hi_numsounds[animnum] = 0; + initprintf("Warning: overwriting already defined hi-anim %s's sounds on line %s:%d\n", animname, + script->filename, scriptfile_getlinum(script, otokptr)); + Bfree(anim->sounds); + anim->numsounds = 0; } if (!preload) - anim_hi_sounds[animnum] = (uint16_t *)Xcalloc(allocsz, 2*sizeof(anim_hi_sounds[0])); + anim->sounds = (uint16_t *)Xcalloc(allocsz, 2 * sizeof(uint16_t)); while (script->textptr < animsoundsend) { int32_t framenum, soundnum; @@ -9522,7 +9548,10 @@ static int32_t parsedefinitions_game(scriptfile *script, int32_t preload) if (preload) { // dummy - getatoken(script, hardcoded_anim_tokens, NUM_HARDCODED_ANIMS); + scriptfile_getstring(script, &animname); + + if (animname) + anim = G_FindAnim(animname); continue; } @@ -9534,21 +9563,23 @@ static int32_t parsedefinitions_game(scriptfile *script, int32_t preload) // would produce error when it encounters the closing '}' // without the above hack - if (scriptfile_getnumber(script, &framenum)) break; - - bad=1; - - // TODO: look carefully at whether this can be removed. - if (anim_hi_sounds[animnum]==NULL) // Bcalloc check + if (scriptfile_getnumber(script, &framenum)) break; - if (scriptfile_getsymbol(script, &soundnum)) break; + bad = 1; + + // TODO: look carefully at whether this can be removed. + if (anim->sounds == NULL) // Bcalloc check + break; + + if (scriptfile_getsymbol(script, &soundnum)) + break; // frame numbers start at 1 for us if (framenum <= 0) { - initprintf("Error: frame number must be greater zero on line %s:%d\n", - script->filename, scriptfile_getlinum(script, script->ltextptr)); + initprintf("Error: frame number must be greater zero on line %s:%d\n", script->filename, + scriptfile_getlinum(script, script->ltextptr)); break; } @@ -9563,8 +9594,8 @@ static int32_t parsedefinitions_game(scriptfile *script, int32_t preload) if ((unsigned)soundnum >= MAXSOUNDS) { - initprintf("Error: sound number #%d invalid on line %s:%d\n", soundnum, - script->filename, scriptfile_getlinum(script, script->ltextptr)); + initprintf("Error: sound number #%d invalid on line %s:%d\n", soundnum, script->filename, + scriptfile_getlinum(script, script->ltextptr)); break; } @@ -9573,15 +9604,15 @@ static int32_t parsedefinitions_game(scriptfile *script, int32_t preload) void *newptr; allocsz *= 2; - newptr = Xrealloc(anim_hi_sounds[animnum], allocsz*2*sizeof(anim_hi_sounds[0])); + newptr = Xrealloc(anim->sounds, allocsz * 2 * sizeof(uint16_t)); - anim_hi_sounds[animnum] = (uint16_t *)newptr; + anim->sounds = (uint16_t *)newptr; } - bad=0; + bad = 0; - anim_hi_sounds[animnum][2*numpairs] = framenum; - anim_hi_sounds[animnum][2*numpairs+1] = soundnum; + anim->sounds[2 * numpairs] = framenum; + anim->sounds[2 * numpairs + 1] = soundnum; numpairs++; } @@ -9589,21 +9620,20 @@ static int32_t parsedefinitions_game(scriptfile *script, int32_t preload) { if (!bad) { - anim_hi_numsounds[animnum] = numpairs; + anim->numsounds = numpairs; // initprintf("Defined sound sequence for hi-anim \"%s\" with %d frame/sound pairs\n", // hardcoded_anim_tokens[animnum].text, numpairs); } else { - Bfree(anim_hi_sounds[animnum]); - anim_hi_sounds[animnum] = NULL; + DO_FREE_AND_NULL(anim->sounds); initprintf("Failed defining sound sequence for hi-anim \"%s\".\n", - hardcoded_anim_tokens[animnum].text); + animname); } } } break; -#endif // defined USE_LIBVPX + case T_SOUND: { char *tinttokptr = script->ltextptr; @@ -10443,7 +10473,7 @@ static void G_DisplayLogo(void) if (!I_CheckAllInput() && g_noLogoAnim == 0) { Net_GetPackets(); - G_PlayAnim("logo.anm",5); + G_PlayAnim("logo.anm"); G_FadePalette(0,0,0,63); I_ClearAllInput(); } @@ -10485,7 +10515,7 @@ static void G_DisplayLogo(void) if (i != -1) { kclose(i); - G_PlayAnim("3dr.anm", 12); + G_PlayAnim("3dr.anm"); G_FadePalette(0, 0, 0, 63); I_ClearAllInput(); } @@ -10682,6 +10712,8 @@ static void G_Cleanup(void) hash_free(&h_labels); hash_free(&h_gamefuncs); #endif + + hash_free(&h_dukeanim); // TODO: free the dukeanim_t structs the hash table entries point to } /* @@ -11476,15 +11508,15 @@ int32_t app_main(int32_t argc, const char **argv) if (quitevent) return 4; + G_InitAnim(); + + const char *defsfile = G_DefFile(); + uint32_t stime = getticks(); + if (!loaddefinitionsfile(defsfile)) { - const char *defsfile = G_DefFile(); - uint32_t stime = getticks(); - if (!loaddefinitionsfile(defsfile)) - { - uint32_t etime = getticks(); - initprintf("Definitions file \"%s\" loaded in %d ms.\n", defsfile, etime-stime); - loaddefinitions_game(defsfile, FALSE); - } + uint32_t etime = getticks(); + initprintf("Definitions file \"%s\" loaded in %d ms.\n", defsfile, etime-stime); + loaddefinitions_game(defsfile, FALSE); } for (i=0; i < g_defModulesNum; ++i) @@ -12211,7 +12243,7 @@ VOL1_END: if (ud.lockout == 0 && !(G_GetLogoFlags() & LOGO_NOE2BONUSSCENE)) { fadepal(0,0,0, 63,0,-1); - G_PlayAnim("cineov2.anm",1); + G_PlayAnim("cineov2.anm"); I_ClearAllInput(); clearallviews(0L); nextpage(); @@ -12247,19 +12279,19 @@ VOL1_END: fadepal(0,0,0, 63,0,-1); I_ClearAllInput(); - t = G_PlayAnim("vol4e1.anm",8); + t = G_PlayAnim("vol4e1.anm"); clearallviews(0L); nextpage(); if (t) goto end_vol4e; - t = G_PlayAnim("vol4e2.anm",10); + t = G_PlayAnim("vol4e2.anm"); clearallviews(0L); nextpage(); if (t) goto end_vol4e; - G_PlayAnim("vol4e3.anm",11); + G_PlayAnim("vol4e3.anm"); clearallviews(0L); nextpage(); } @@ -12300,7 +12332,7 @@ VOL4_DUKETEAM: clearallviews(0L); nextpage(); - G_PlayAnim("DUKETEAM.ANM",4); + G_PlayAnim("DUKETEAM.ANM"); I_ClearAllInput(); G_HandleEventsWhileNoInput(); @@ -12326,7 +12358,7 @@ VOL4_END: if (ud.lockout == 0 && !(G_GetLogoFlags() & LOGO_NOE3BONUSSCENE)) { fadepal(0,0,0, 63,0,-1); - G_PlayAnim("cineov3.anm",2); + G_PlayAnim("cineov3.anm"); I_ClearAllInput(); ototalclock = totalclock+200; while (totalclock < ototalclock) @@ -12341,7 +12373,7 @@ VOL4_END: if (G_GetLogoFlags() & LOGO_NOE3RADLOGO) goto ENDANM; - G_PlayAnim("RADLOGO.ANM",3); + G_PlayAnim("RADLOGO.ANM"); if (ud.lockout == 0 && !I_CheckAllInput()) { @@ -12377,7 +12409,7 @@ ENDANM: clearallviews(0L); nextpage(); - G_PlayAnim("DUKETEAM.ANM",4); + G_PlayAnim("DUKETEAM.ANM"); I_ClearAllInput(); G_HandleEventsWhileNoInput(); diff --git a/polymer/eduke32/source/gamedef.c b/polymer/eduke32/source/gamedef.c index 37ed22270..e481a4101 100644 --- a/polymer/eduke32/source/gamedef.c +++ b/polymer/eduke32/source/gamedef.c @@ -96,6 +96,8 @@ static struct { uint32_t keyw; uint32_t date; } g_keywdate[] = { CON_DYNAMICSOUNDREMAP, 20130530 }, { CON_SCREENSOUND, 20130628 }, { CON_SETMUSICPOSITION, 20150115 }, + { CON_CUTSCENE, 20150117 }, + { CON_IFCUTSCENE, 20150117 }, }; #endif @@ -555,6 +557,8 @@ const char *keyw[] = "undefinevolume", // 375 "undefineskill", // 376 "undefinelevel", // 377 + "cutscene", // 378 + "ifcutscene", // 379 "" }; #endif @@ -661,6 +665,7 @@ const char *EventNames[MAXEVENTS] = "EVENT_ACTIVATECHEAT", "EVENT_DISPLAYINACTIVEMENU", "EVENT_DISPLAYINACTIVEMENUREST", + "EVENT_CUTSCENE", #ifdef LUNATIC "EVENT_ANIMATEALLSPRITES", #endif @@ -4162,6 +4167,7 @@ static int32_t C_ParseCommand(int32_t loop) case CON_SETACTORANGLE: case CON_SETPLAYERANGLE: case CON_SETMUSICPOSITION: + case CON_CUTSCENE: C_GetNextVar(); continue; @@ -5124,6 +5130,7 @@ repeatcase: case CON_IFP: case CON_IFPINVENTORY: case CON_IFPLAYERSL: + case CON_IFCUTSCENE: { intptr_t offset; intptr_t lastScriptPtr = (g_scriptPtr-&script[0]-1); @@ -5132,6 +5139,9 @@ repeatcase: switch (tw) { + case CON_IFCUTSCENE: + C_GetNextVar(); + break; case CON_IFAI: C_GetNextValue(LABEL_AI); break; diff --git a/polymer/eduke32/source/gamedef.h b/polymer/eduke32/source/gamedef.h index 3e35fda6d..f1c50c079 100644 --- a/polymer/eduke32/source/gamedef.h +++ b/polymer/eduke32/source/gamedef.h @@ -982,6 +982,8 @@ enum ScriptKeywords_t CON_UNDEFINEVOLUME, // 375 CON_UNDEFINESKILL, // 376 CON_UNDEFINELEVEL, // 377 + CON_CUTSCENE, // 378 + CON_IFCUTSCENE, // 379 CON_END }; // KEEPINSYNC with the keyword list in lunatic/con_lang.lua diff --git a/polymer/eduke32/source/gameexec.c b/polymer/eduke32/source/gameexec.c index 6532e98cf..a9d09567d 100644 --- a/polymer/eduke32/source/gameexec.c +++ b/polymer/eduke32/source/gameexec.c @@ -38,6 +38,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "osd.h" #include "menus.h" #include "input.h" +#include "anim.h" #ifdef LUNATIC # include "lunatic_game.h" @@ -2712,6 +2713,31 @@ nullquote: } continue; + case CON_CUTSCENE: + case CON_IFCUTSCENE: + insptr++; + { + int32_t j = Gv_GetVarX(*insptr++); + + if (EDUKE32_PREDICT_FALSE((unsigned)j >= MAXQUOTES || ScriptQuotes[j] == NULL)) + { + CON_ERRPRINTF("invalid quote ID %d for anim!\n", j); + continue; + } + + if (tw == CON_IFCUTSCENE) + { + VM_CONDITIONAL(g_animPtr == G_FindAnim(ScriptQuotes[j])); + continue; + } + + tw = ps->palette; + G_PlayAnim(ScriptQuotes[j]); + P_SetGamePalette(ps, tw, 2 + 16); + continue; + } + continue; + case CON_GUNIQHUDID: insptr++; { diff --git a/polymer/eduke32/source/premap.c b/polymer/eduke32/source/premap.c index 21014a70d..2cf1e84aa 100644 --- a/polymer/eduke32/source/premap.c +++ b/polymer/eduke32/source/premap.c @@ -1363,19 +1363,19 @@ void G_NewGame(int32_t vn, int32_t ln, int32_t sk) clearview(0L); nextpage(); - i = G_PlayAnim("vol41a.anm",6); + i = G_PlayAnim("vol41a.anm"); clearview(0L); nextpage(); if (i) goto end_vol4a; - i = G_PlayAnim("vol42a.anm",7); + i = G_PlayAnim("vol42a.anm"); clearview(0L); nextpage(); if (i) goto end_vol4a; - G_PlayAnim("vol43a.anm",9); + G_PlayAnim("vol43a.anm"); clearview(0L); nextpage();