From a7dc20e7d2d53dad20f41884f382bfedf8f1d44e Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 29 Aug 2016 22:42:06 +0100 Subject: [PATCH 001/306] Upper Unpegged on an FOF's control linedef now enables skewing of walls with respect to slopes Skewing direction is decided per in-level wall by the Lower Unpegged flag on in-level linedefs themselves, since they already decide the stuff for FOF wall pegging as it is. That is unless Transfer Line is involved which moves everything to the control sector linedefs instead... --- src/r_segs.c | 73 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 9 deletions(-) diff --git a/src/r_segs.c b/src/r_segs.c index 502ff3304..fff98dbf2 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -743,6 +743,12 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // Render FOF sides kinda like normal sides, with the frac and step and everything // NOTE: INT64 instead of fixed_t because overflow concerns INT64 top_frac, top_step, bottom_frac, bottom_step; + // skew FOF walls with slopes? + boolean slopeskew = false; + fixed_t ffloortextureslide = 0; + INT32 oldx = -1; + fixed_t left_top, left_bottom; // needed here for slope skewing + pslope_t *skewslope = NULL; #endif void (*colfunc_2s) (column_t *); @@ -966,21 +972,68 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) mceilingclip = ds->sprtopclip; dc_texheight = textureheight[texnum]>>FRACBITS; +#ifdef ESLOPE + // calculate both left ends + if (*pfloor->t_slope) + left_top = P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y) - viewz; + else + left_top = *pfloor->topheight - viewz; + + if (*pfloor->b_slope) + left_bottom = P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y) - viewz; + else + left_bottom = *pfloor->bottomheight - viewz; + dc_texturemid = left_top; + skewslope = *pfloor->t_slope; // skew using top slope by default +#else dc_texturemid = *pfloor->topheight - viewz; +#endif if (newline) { offsetvalue = sides[newline->sidenum[0]].rowoffset; if (newline->flags & ML_DONTPEGBOTTOM) +#ifdef ESLOPE + { + dc_texturemid = left_bottom; + skewslope = *pfloor->b_slope; // skew using bottom slope + } +#else offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; +#endif +#ifdef ESLOPE + if (newline->flags & ML_DONTPEGTOP) + slopeskew = true; +#endif } else { offsetvalue = sides[pfloor->master->sidenum[0]].rowoffset; if (curline->linedef->flags & ML_DONTPEGBOTTOM) +#ifdef ESLOPE + { + dc_texturemid = left_bottom; + skewslope = *pfloor->b_slope; // skew using bottom slope + } +#else offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; +#endif +#ifdef ESLOPE + if (pfloor->master->flags & ML_DONTPEGTOP) // use control linedef's flags + slopeskew = true; +#endif } +#ifdef ESLOPE + if (slopeskew) + { + angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); + + if (skewslope) + ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT)); + } +#endif + dc_texturemid += offsetvalue; // Texture must be cached before setting colfunc_2s, @@ -999,23 +1052,18 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) #ifdef ESLOPE // Set heights according to plane, or slope, whichever { - fixed_t left_top, right_top, left_bottom, right_bottom; + fixed_t right_top, right_bottom; + // calculate right ends now if (*pfloor->t_slope) - { - left_top = P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y) - viewz; right_top = P_GetZAt(*pfloor->t_slope, ds->rightpos.x, ds->rightpos.y) - viewz; - } else - left_top = right_top = *pfloor->topheight - viewz; + right_top = *pfloor->topheight - viewz; if (*pfloor->b_slope) - { - left_bottom = P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y) - viewz; right_bottom = P_GetZAt(*pfloor->b_slope, ds->rightpos.x, ds->rightpos.y) - viewz; - } else - left_bottom = right_bottom = *pfloor->bottomheight - viewz; + right_bottom = *pfloor->bottomheight - viewz; // using INT64 to avoid 32bit overflow top_frac = (INT64)centeryfrac - (((INT64)left_top * ds->scale1) >> FRACBITS); @@ -1039,6 +1087,13 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { if (maskedtexturecol[dc_x] != INT16_MAX) { +#ifdef ESLOPE + if (ffloortextureslide) { // skew FOF walls + if (oldx != -1) + dc_texturemid += FixedMul(ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc_x])< Date: Mon, 29 Aug 2016 23:21:57 +0100 Subject: [PATCH 002/306] If NOT skewing FOF walls, make sure dc_texturemid reverts to using unsloped FOF topheight/bottomheight rather than actual left side top/bottom heights --- src/r_segs.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/r_segs.c b/src/r_segs.c index fff98dbf2..0d3a6430e 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -983,45 +983,45 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) left_bottom = P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y) - viewz; else left_bottom = *pfloor->bottomheight - viewz; - dc_texturemid = left_top; skewslope = *pfloor->t_slope; // skew using top slope by default -#else - dc_texturemid = *pfloor->topheight - viewz; + if (newline && newline->flags & ML_DONTPEGTOP) + slopeskew = true; + else if (pfloor->master->flags & ML_DONTPEGTOP) + slopeskew = true; + + if (slopeskew) + dc_texturemid = left_top; + else #endif + dc_texturemid = *pfloor->topheight - viewz; if (newline) { offsetvalue = sides[newline->sidenum[0]].rowoffset; if (newline->flags & ML_DONTPEGBOTTOM) -#ifdef ESLOPE { - dc_texturemid = left_bottom; - skewslope = *pfloor->b_slope; // skew using bottom slope - } -#else - offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; -#endif #ifdef ESLOPE - if (newline->flags & ML_DONTPEGTOP) - slopeskew = true; + skewslope = *pfloor->b_slope; // skew using bottom slope + if (slopeskew) + dc_texturemid = left_bottom; + else #endif + offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; + } } else { offsetvalue = sides[pfloor->master->sidenum[0]].rowoffset; if (curline->linedef->flags & ML_DONTPEGBOTTOM) -#ifdef ESLOPE { - dc_texturemid = left_bottom; - skewslope = *pfloor->b_slope; // skew using bottom slope - } -#else - offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; -#endif #ifdef ESLOPE - if (pfloor->master->flags & ML_DONTPEGTOP) // use control linedef's flags - slopeskew = true; + skewslope = *pfloor->b_slope; // skew using bottom slope + if (slopeskew) + dc_texturemid = left_bottom; + else #endif + offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; + } } #ifdef ESLOPE From 40cb22a130be5dc06b22a280b44588430f5a8610 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 29 Aug 2016 23:24:59 +0100 Subject: [PATCH 003/306] probably best if we did this instead actually --- src/r_segs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/r_segs.c b/src/r_segs.c index 0d3a6430e..b997c2a88 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -984,8 +984,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) else left_bottom = *pfloor->bottomheight - viewz; skewslope = *pfloor->t_slope; // skew using top slope by default - if (newline && newline->flags & ML_DONTPEGTOP) - slopeskew = true; + if (newline) + { + if (newline->flags & ML_DONTPEGTOP) + slopeskew = true; + } else if (pfloor->master->flags & ML_DONTPEGTOP) slopeskew = true; From 0fedd2e566553143d202fc1bbbece55fa6d85be9 Mon Sep 17 00:00:00 2001 From: Marco Z Date: Fri, 30 Mar 2018 15:27:37 -0400 Subject: [PATCH 004/306] Define fader thinker names --- src/p_saveg.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ src/p_spec.c | 33 +++++++++++++++++++++++++++++++++ src/p_spec.h | 16 ++++++++++++++++ 3 files changed, 98 insertions(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index 029df08f4..5542b3cda 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -988,6 +988,7 @@ typedef enum tc_noenemies, tc_eachtime, tc_disappear, + tc_fade, tc_planedisplace, #ifdef POLYOBJECTS tc_polyrotate, // haleyjd 03/26/06: polyobjects @@ -1552,6 +1553,25 @@ static void SaveDisappearThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->exists); } +// +// SaveFadeThinker +// +// Saves a fade_t thinker +// +static void SaveFadeThinker(const thinker_t *th, const UINT8 type) +{ + const fade_t *ht = (const void *)th; + // \todo fields + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, ht->appeartime); + WRITEUINT32(save_p, ht->disappeartime); + WRITEUINT32(save_p, ht->offset); + WRITEUINT32(save_p, ht->timer); + WRITEINT32(save_p, ht->affectee); + WRITEINT32(save_p, ht->sourceline); + WRITEINT32(save_p, ht->exists); +} + // // SavePlaneDisplaceThinker // @@ -1854,6 +1874,11 @@ static void P_NetArchiveThinkers(void) SaveDisappearThinker(th, tc_disappear); continue; } + else if (th->function.acp1 == (actionf_p1)T_Fade) + { + SaveFadeThinker(th, tc_fade); + continue; + } else if (th->function.acp1 == (actionf_p1)T_PlaneDisplace) { @@ -2530,6 +2555,26 @@ static inline void LoadDisappearThinker(actionf_p1 thinker) P_AddThinker(&ht->thinker); } +// +// LoadFadeThinker +// +// Loads a fade_t thinker +// +static inline void LoadFadeThinker(actionf_p1 thinker) +{ + fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + // \todo fields + ht->appeartime = READUINT32(save_p); + ht->disappeartime = READUINT32(save_p); + ht->offset = READUINT32(save_p); + ht->timer = READUINT32(save_p); + ht->affectee = READINT32(save_p); + ht->sourceline = READINT32(save_p); + ht->exists = READINT32(save_p); + P_AddThinker(&ht->thinker); +} + // // LoadPlaneDisplaceThinker // @@ -2833,6 +2878,10 @@ static void P_NetUnArchiveThinkers(void) LoadDisappearThinker((actionf_p1)T_Disappear); break; + case tc_fade: + LoadFadeThinker((actionf_p1)T_Fade); + break; + case tc_planedisplace: LoadPlaneDisplaceThinker((actionf_p1)T_PlaneDisplace); break; diff --git a/src/p_spec.c b/src/p_spec.c index 0b005baff..b1ede46d8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7056,6 +7056,39 @@ void T_Disappear(disappear_t *d) } } +/** Adds master fader thinker. + * + * \param appeartime tics to be existent + * \param disappeartime tics to be nonexistent + * \param sector pointer to control sector + */ +static void P_AddMasterFader(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline) +{ + fade_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); + + // \todo fields + d->thinker.function.acp1 = (actionf_p1)T_Disappear; + d->appeartime = appeartime; + d->disappeartime = disappeartime; + d->offset = offset; + d->affectee = line; + d->sourceline = sourceline; + d->exists = true; + d->timer = 1; + + P_AddThinker(&d->thinker); +} + +/** Makes a FOF fade + * + * \param d Fade thinker. + * \sa P_AddMasterFader + */ +void T_Fade(fade_t *d) +{ + // \todo everything +} + /* SoM: 3/8/2000: Friction functions start. Add_Friction, diff --git a/src/p_spec.h b/src/p_spec.h index c4e05e072..3ed66f149 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -449,6 +449,22 @@ typedef struct void T_Disappear(disappear_t *d); +// Model for fading FOFs +typedef struct +{ + // \todo fields + thinker_t thinker; ///< Thinker structure for effect. + tic_t appeartime; ///< Tics to be appeared for + tic_t disappeartime;///< Tics to be disappeared for + tic_t offset; ///< Time to wait until thinker starts + tic_t timer; ///< Timer between states + INT32 affectee; ///< Number of affected line + INT32 sourceline; ///< Number of source line + INT32 exists; ///< Exists toggle +} fade_t; + +void T_Fade(fade_t *d); + // Prototype functions for pushers void T_Pusher(pusher_t *p); mobj_t *P_GetPushThing(UINT32 s); From 44b25be69af83a02bed7d8a90274a60f9ea111cf Mon Sep 17 00:00:00 2001 From: Marco Z Date: Fri, 30 Mar 2018 16:17:35 -0400 Subject: [PATCH 005/306] fade_t fields --- src/p_saveg.c | 20 ++++++-------------- src/p_spec.c | 19 ++++++++----------- src/p_spec.h | 10 +++------- 3 files changed, 17 insertions(+), 32 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 5542b3cda..eb76fede5 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1561,15 +1561,11 @@ static void SaveDisappearThinker(const thinker_t *th, const UINT8 type) static void SaveFadeThinker(const thinker_t *th, const UINT8 type) { const fade_t *ht = (const void *)th; - // \todo fields WRITEUINT8(save_p, type); - WRITEUINT32(save_p, ht->appeartime); - WRITEUINT32(save_p, ht->disappeartime); - WRITEUINT32(save_p, ht->offset); - WRITEUINT32(save_p, ht->timer); WRITEINT32(save_p, ht->affectee); - WRITEINT32(save_p, ht->sourceline); - WRITEINT32(save_p, ht->exists); + WRITEINT32(save_p, ht->destvalue); + WRITEINT32(save_p, ht->speed); + WRITEUINT8(save_p, ht->ignoreflags); } // @@ -2564,14 +2560,10 @@ static inline void LoadFadeThinker(actionf_p1 thinker) { fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - // \todo fields - ht->appeartime = READUINT32(save_p); - ht->disappeartime = READUINT32(save_p); - ht->offset = READUINT32(save_p); - ht->timer = READUINT32(save_p); ht->affectee = READINT32(save_p); - ht->sourceline = READINT32(save_p); - ht->exists = READINT32(save_p); + ht->destvalue = READINT32(save_p); + ht->speed = READINT32(save_p); + ht->ignoreflags = READUINT8(save_p); P_AddThinker(&ht->thinker); } diff --git a/src/p_spec.c b/src/p_spec.c index b1ede46d8..43dba0dc3 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7058,23 +7058,20 @@ void T_Disappear(disappear_t *d) /** Adds master fader thinker. * - * \param appeartime tics to be existent - * \param disappeartime tics to be nonexistent - * \param sector pointer to control sector + * \param destvalue transparency value to fade to + * \param speed speed to fade by + * \param ignoreexists do not handle FF_EXISTS + * \param line line to target FOF */ -static void P_AddMasterFader(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline) +static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL ignoreflags, INT32 line) { fade_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); - // \todo fields d->thinker.function.acp1 = (actionf_p1)T_Disappear; - d->appeartime = appeartime; - d->disappeartime = disappeartime; - d->offset = offset; d->affectee = line; - d->sourceline = sourceline; - d->exists = true; - d->timer = 1; + d->destvalue = destvalue; + d->speed = speed; + d->ignoreflags = (UINT8)ignoreflags; P_AddThinker(&d->thinker); } diff --git a/src/p_spec.h b/src/p_spec.h index 3ed66f149..355f0c111 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -452,15 +452,11 @@ void T_Disappear(disappear_t *d); // Model for fading FOFs typedef struct { - // \todo fields thinker_t thinker; ///< Thinker structure for effect. - tic_t appeartime; ///< Tics to be appeared for - tic_t disappeartime;///< Tics to be disappeared for - tic_t offset; ///< Time to wait until thinker starts - tic_t timer; ///< Timer between states INT32 affectee; ///< Number of affected line - INT32 sourceline; ///< Number of source line - INT32 exists; ///< Exists toggle + INT32 destvalue; ///< Transparency value to fade to + INT32 speed; ///< Speed to fade by + UINT8 ignoreflags; ///< Do not handle FF_EXISTS } fade_t; void T_Fade(fade_t *d); From e617753d0011a16b9e79eaa29427e214cd4654c3 Mon Sep 17 00:00:00 2001 From: Marco Z Date: Fri, 30 Mar 2018 16:17:35 -0400 Subject: [PATCH 006/306] Initial logic attempt * Front X offset: ffloor alpha target (1-256) * Front Y offset: Speed, alpha per tic (1+) * MF_BLOCKMONSTERS: Do not handle FF_EXISTS --- src/p_spec.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 4 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 43dba0dc3..2c0418847 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -102,6 +102,7 @@ static void P_SpawnFriction(void); static void P_SpawnPushers(void); static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000 static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); +static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL ignoreflags, INT32 line); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); @@ -3092,6 +3093,20 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; } + case 452: // Fade FOF + { + //CONS_Printf("Hello! Found a Fade special!\n"); + INT32 s, j; + for (s = -1; (s = P_FindSectorFromLineTag(line, s)) >= 0 ;) + for (j = 0; (unsigned)j < sectors[s].linecount; j++) + if (sectors[s].lines[j]->special >= 100 && sectors[s].lines[j]->special < 300) + P_AddMasterFader(sides[line->sidenum[0]].textureoffset>>FRACBITS, sides[line->sidenum[0]].rowoffset>>FRACBITS, (line->flags & ML_BLOCKMONSTERS), (INT32)(sectors[s].lines[j]-lines)); + break; + } + + case 453: // Stop fading FOF + break; + #ifdef POLYOBJECTS case 480: // Polyobj_DoorSlide case 481: // Polyobj_DoorSwing @@ -7067,13 +7082,17 @@ static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL ignoreflags, INT { fade_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); - d->thinker.function.acp1 = (actionf_p1)T_Disappear; + //CONS_Printf("Adding fader | Dest %i | Speed %i | Ignore %i\n", destvalue, speed, ignoreflags); + + d->thinker.function.acp1 = (actionf_p1)T_Fade; d->affectee = line; - d->destvalue = destvalue; - d->speed = speed; + d->destvalue = max(1, min(256, destvalue)); // ffloor->alpha is 1-256 + d->speed = max(1, speed); // minimum speed 1/tic d->ignoreflags = (UINT8)ignoreflags; P_AddThinker(&d->thinker); + + //CONS_Printf("Added fader | Dest %i | Speed %i | Ignore %i\n", d->destvalue, d->speed, d->ignoreflags); } /** Makes a FOF fade @@ -7083,7 +7102,69 @@ static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL ignoreflags, INT */ void T_Fade(fade_t *d) { - // \todo everything + ffloor_t *rover; + register INT32 s; + INT32 affectedffloors = 0; + + for (s = -1; (s = P_FindSectorFromLineTag(&lines[d->affectee], s)) >= 0 ;) + { + for (rover = sectors[s].ffloors; rover; rover = rover->next) + { + if (rover->master != &lines[d->affectee]) + continue; + + // fade out + //CONS_Printf("Fading from %i to %i\n", rover->alpha, d->destvalue); + if (rover->alpha > d->destvalue) + { + // we'll reach our destvalue + if (rover->alpha - d->speed <= d->destvalue + d->speed) + { + //CONS_Printf("Finished fading out\n"); + rover->alpha = d->destvalue; + if (!d->ignoreflags && rover->alpha <= 1) + rover->flags &= ~FF_EXISTS; + else + rover->flags |= FF_EXISTS; + } + else + { + //CONS_Printf("Fading out...\n"); + rover->alpha -= d->speed; + if (!d->ignoreflags) + rover->flags |= FF_EXISTS; + affectedffloors++; + } + } + else // fade in + { + // we'll reach our destvalue + if (rover->alpha + d->speed >= d->destvalue - d->speed) + { + //CONS_Printf("Finished fading in\n"); + rover->alpha = d->destvalue; + if (!d->ignoreflags) + rover->flags |= FF_EXISTS; + } + else + { + //CONS_Printf("Fading in...\n"); + rover->alpha += d->speed; + if (!d->ignoreflags) + rover->flags |= FF_EXISTS; + affectedffloors++; + } + } + } + } + + // no more ffloors to fade? remove myself + if (affectedffloors == 0) + { + //CONS_Printf("No more FOFs to fade!\n"); + // \todo how to erase the fade_t struct? + P_RemoveThinker(&d->thinker); + } } /* From d449aae76d75c0da97c422eefdc5030ab0d7cb28 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 30 Mar 2018 14:36:49 -0400 Subject: [PATCH 007/306] Add predefined behaviors for fading FOF flags * ML_BLOCKMONSTERS: Handle FF_EXISTS * ML_NOCLIMB: Handle FF_SOLID * ML_EFFECT1: Don't handle FF_TRANSLUCENT --- src/p_saveg.c | 4 +- src/p_spec.c | 118 ++++++++++++++++++++++++++++++++++++++++++-------- src/p_spec.h | 2 +- 3 files changed, 102 insertions(+), 22 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index eb76fede5..aa48afde1 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1565,7 +1565,7 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->affectee); WRITEINT32(save_p, ht->destvalue); WRITEINT32(save_p, ht->speed); - WRITEUINT8(save_p, ht->ignoreflags); + WRITEUINT8(save_p, ht->handleflags); } // @@ -2563,7 +2563,7 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->affectee = READINT32(save_p); ht->destvalue = READINT32(save_p); ht->speed = READINT32(save_p); - ht->ignoreflags = READUINT8(save_p); + ht->handleflags = READUINT8(save_p); P_AddThinker(&ht->thinker); } diff --git a/src/p_spec.c b/src/p_spec.c index 2c0418847..6b9b9499f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -102,7 +102,7 @@ static void P_SpawnFriction(void); static void P_SpawnPushers(void); static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000 static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); -static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL ignoreflags, INT32 line); +static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOOL handlesolid, BOOL handletrans, INT32 line); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); @@ -3100,7 +3100,12 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) for (s = -1; (s = P_FindSectorFromLineTag(line, s)) >= 0 ;) for (j = 0; (unsigned)j < sectors[s].linecount; j++) if (sectors[s].lines[j]->special >= 100 && sectors[s].lines[j]->special < 300) - P_AddMasterFader(sides[line->sidenum[0]].textureoffset>>FRACBITS, sides[line->sidenum[0]].rowoffset>>FRACBITS, (line->flags & ML_BLOCKMONSTERS), (INT32)(sectors[s].lines[j]-lines)); + P_AddMasterFader(sides[line->sidenum[0]].textureoffset>>FRACBITS, + sides[line->sidenum[0]].rowoffset>>FRACBITS, + (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS + (line->flags & ML_NOCLIMB), // handle FF_SOLID + !(line->flags & ML_EFFECT1), // do not handle FF_TRANSLUCENT + (INT32)(sectors[s].lines[j]-lines)); break; } @@ -7075,24 +7080,37 @@ void T_Disappear(disappear_t *d) * * \param destvalue transparency value to fade to * \param speed speed to fade by - * \param ignoreexists do not handle FF_EXISTS + * \param handleexist handle FF_EXISTS + * \param handlesolid handle FF_SOLID + * \param handletrans do not handle FF_TRANSLUCENT * \param line line to target FOF */ -static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL ignoreflags, INT32 line) +static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOOL handlesolid, BOOL handletrans, INT32 line) { fade_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); - //CONS_Printf("Adding fader | Dest %i | Speed %i | Ignore %i\n", destvalue, speed, ignoreflags); + //CONS_Printf("Adding fader | Dest %i | Speed %i | Ignore %i\n", destvalue, speed, handleflags); d->thinker.function.acp1 = (actionf_p1)T_Fade; d->affectee = line; d->destvalue = max(1, min(256, destvalue)); // ffloor->alpha is 1-256 d->speed = max(1, speed); // minimum speed 1/tic - d->ignoreflags = (UINT8)ignoreflags; + + // combine the flags-to-handle, this is more convenient than separate BOOLS + d->handleflags = 0; + + if (handleexist) + d->handleflags |= FF_EXISTS; + + if (handlesolid) + d->handleflags |= FF_SOLID; + + if (handletrans) + d->handleflags |= FF_TRANSLUCENT; P_AddThinker(&d->thinker); - //CONS_Printf("Added fader | Dest %i | Speed %i | Ignore %i\n", d->destvalue, d->speed, d->ignoreflags); + //CONS_Printf("Added fader | Dest %i | Speed %i | Ignore %i\n", d->destvalue, d->speed, d->handleflags); } /** Makes a FOF fade @@ -7120,19 +7138,49 @@ void T_Fade(fade_t *d) // we'll reach our destvalue if (rover->alpha - d->speed <= d->destvalue + d->speed) { - //CONS_Printf("Finished fading out\n"); - rover->alpha = d->destvalue; - if (!d->ignoreflags && rover->alpha <= 1) - rover->flags &= ~FF_EXISTS; - else - rover->flags |= FF_EXISTS; + if (rover->alpha != d->destvalue) + { + //CONS_Printf("Finished fading out\n"); + rover->alpha = d->destvalue; + + if (d->handleflags & FF_EXISTS) + { + if (rover->alpha <= 1) + rover->flags &= ~FF_EXISTS; + else + rover->flags |= FF_EXISTS; + } + + if ((d->handleflags & FF_SOLID) + && !(rover->flags & FF_SWIMMABLE) + && !(rover->flags & FF_QUICKSAND)) + rover->flags &= ~FF_SOLID; // make intangible at end of fade-out + + if (d->handleflags & FF_TRANSLUCENT) + { + if (rover->alpha >= 256) + rover->flags &= ~FF_TRANSLUCENT; + else + rover->flags |= FF_TRANSLUCENT; + } + } } else { //CONS_Printf("Fading out...\n"); rover->alpha -= d->speed; - if (!d->ignoreflags) + + if (d->handleflags & FF_EXISTS) rover->flags |= FF_EXISTS; + + if ((d->handleflags & FF_SOLID) + && !(rover->flags & FF_SWIMMABLE) + && !(rover->flags & FF_QUICKSAND)) + rover->flags |= FF_SOLID; // keep solid during fade + + if (d->handleflags & FF_TRANSLUCENT) + rover->flags |= FF_TRANSLUCENT; // assume we're not completely opaque + affectedffloors++; } } @@ -7141,17 +7189,49 @@ void T_Fade(fade_t *d) // we'll reach our destvalue if (rover->alpha + d->speed >= d->destvalue - d->speed) { - //CONS_Printf("Finished fading in\n"); - rover->alpha = d->destvalue; - if (!d->ignoreflags) - rover->flags |= FF_EXISTS; + if (rover->alpha != d->destvalue) + { + //CONS_Printf("Finished fading in\n"); + rover->alpha = d->destvalue; + + if (d->handleflags & FF_EXISTS) + { + if (rover->alpha <= 1) + rover->flags &= ~FF_EXISTS; + else + rover->flags |= FF_EXISTS; + } + + if ((d->handleflags & FF_SOLID) + && !(rover->flags & FF_SWIMMABLE) + && !(rover->flags & FF_QUICKSAND)) + rover->flags |= FF_SOLID; // make solid at end of fade-in + + if (d->handleflags & FF_TRANSLUCENT) + { + if (rover->alpha >= 256) + rover->flags &= ~FF_TRANSLUCENT; + else + rover->flags |= FF_TRANSLUCENT; + } + } } else { //CONS_Printf("Fading in...\n"); rover->alpha += d->speed; - if (!d->ignoreflags) + + if (d->handleflags & FF_EXISTS) rover->flags |= FF_EXISTS; + + if ((d->handleflags & FF_SOLID) + && !(rover->flags & FF_SWIMMABLE) + && !(rover->flags & FF_QUICKSAND)) + rover->flags |= FF_SOLID; // keep solid during fade + + if (d->handleflags & FF_TRANSLUCENT) + rover->flags |= FF_TRANSLUCENT; // assume we're not completely opaque + affectedffloors++; } } diff --git a/src/p_spec.h b/src/p_spec.h index 355f0c111..9c0b3c2c5 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -456,7 +456,7 @@ typedef struct INT32 affectee; ///< Number of affected line INT32 destvalue; ///< Transparency value to fade to INT32 speed; ///< Speed to fade by - UINT8 ignoreflags; ///< Do not handle FF_EXISTS + UINT8 handleflags; ///< Do not handle FF_EXISTS } fade_t; void T_Fade(fade_t *d); From 73c7df6f5b6a719ea36ab9b06e5735fd6fc3f892 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 30 Mar 2018 22:56:43 -0400 Subject: [PATCH 008/306] Maybe let's not handle FF_TRANSLUCENT for fade FOF. Why: FF_TRANSLUCENT is often packaged with flags FF_EXTRA, FF_CUTEXTRA; for intangibles, FF_CUTSPIRTES; in some cases (?), FF_CUTLEVEL. I *think* the rules are consistent amongst predefined FOFs, but maybe there are exceptions? There's too much that can go wrong with assuming too many flags for an FOF. Just make it the modder's responsibility to tag this special to the proper translucent FOF. --- src/p_spec.c | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 6b9b9499f..249d50f7d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -102,7 +102,7 @@ static void P_SpawnFriction(void); static void P_SpawnPushers(void); static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000 static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); -static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOOL handlesolid, BOOL handletrans, INT32 line); +static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOOL handlesolid, INT32 line); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); @@ -3104,7 +3104,6 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) sides[line->sidenum[0]].rowoffset>>FRACBITS, (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS (line->flags & ML_NOCLIMB), // handle FF_SOLID - !(line->flags & ML_EFFECT1), // do not handle FF_TRANSLUCENT (INT32)(sectors[s].lines[j]-lines)); break; } @@ -7082,10 +7081,9 @@ void T_Disappear(disappear_t *d) * \param speed speed to fade by * \param handleexist handle FF_EXISTS * \param handlesolid handle FF_SOLID - * \param handletrans do not handle FF_TRANSLUCENT * \param line line to target FOF */ -static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOOL handlesolid, BOOL handletrans, INT32 line) +static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOOL handlesolid, INT32 line) { fade_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); @@ -7105,9 +7103,6 @@ static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOO if (handlesolid) d->handleflags |= FF_SOLID; - if (handletrans) - d->handleflags |= FF_TRANSLUCENT; - P_AddThinker(&d->thinker); //CONS_Printf("Added fader | Dest %i | Speed %i | Ignore %i\n", d->destvalue, d->speed, d->handleflags); @@ -7155,14 +7150,6 @@ void T_Fade(fade_t *d) && !(rover->flags & FF_SWIMMABLE) && !(rover->flags & FF_QUICKSAND)) rover->flags &= ~FF_SOLID; // make intangible at end of fade-out - - if (d->handleflags & FF_TRANSLUCENT) - { - if (rover->alpha >= 256) - rover->flags &= ~FF_TRANSLUCENT; - else - rover->flags |= FF_TRANSLUCENT; - } } } else @@ -7178,9 +7165,6 @@ void T_Fade(fade_t *d) && !(rover->flags & FF_QUICKSAND)) rover->flags |= FF_SOLID; // keep solid during fade - if (d->handleflags & FF_TRANSLUCENT) - rover->flags |= FF_TRANSLUCENT; // assume we're not completely opaque - affectedffloors++; } } @@ -7206,14 +7190,6 @@ void T_Fade(fade_t *d) && !(rover->flags & FF_SWIMMABLE) && !(rover->flags & FF_QUICKSAND)) rover->flags |= FF_SOLID; // make solid at end of fade-in - - if (d->handleflags & FF_TRANSLUCENT) - { - if (rover->alpha >= 256) - rover->flags &= ~FF_TRANSLUCENT; - else - rover->flags |= FF_TRANSLUCENT; - } } } else @@ -7229,9 +7205,6 @@ void T_Fade(fade_t *d) && !(rover->flags & FF_QUICKSAND)) rover->flags |= FF_SOLID; // keep solid during fade - if (d->handleflags & FF_TRANSLUCENT) - rover->flags |= FF_TRANSLUCENT; // assume we're not completely opaque - affectedffloors++; } } From 047fffb6da5d4dfb0d0caeab5cfc08eab09959e7 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 30 Mar 2018 22:59:33 -0400 Subject: [PATCH 009/306] Remove log comments for Fade FOF --- src/p_spec.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 2c0418847..a5c040892 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3095,7 +3095,6 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 452: // Fade FOF { - //CONS_Printf("Hello! Found a Fade special!\n"); INT32 s, j; for (s = -1; (s = P_FindSectorFromLineTag(line, s)) >= 0 ;) for (j = 0; (unsigned)j < sectors[s].linecount; j++) @@ -7082,8 +7081,6 @@ static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL ignoreflags, INT { fade_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); - //CONS_Printf("Adding fader | Dest %i | Speed %i | Ignore %i\n", destvalue, speed, ignoreflags); - d->thinker.function.acp1 = (actionf_p1)T_Fade; d->affectee = line; d->destvalue = max(1, min(256, destvalue)); // ffloor->alpha is 1-256 @@ -7091,8 +7088,6 @@ static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL ignoreflags, INT d->ignoreflags = (UINT8)ignoreflags; P_AddThinker(&d->thinker); - - //CONS_Printf("Added fader | Dest %i | Speed %i | Ignore %i\n", d->destvalue, d->speed, d->ignoreflags); } /** Makes a FOF fade @@ -7114,22 +7109,19 @@ void T_Fade(fade_t *d) continue; // fade out - //CONS_Printf("Fading from %i to %i\n", rover->alpha, d->destvalue); if (rover->alpha > d->destvalue) { // we'll reach our destvalue if (rover->alpha - d->speed <= d->destvalue + d->speed) { - //CONS_Printf("Finished fading out\n"); rover->alpha = d->destvalue; if (!d->ignoreflags && rover->alpha <= 1) rover->flags &= ~FF_EXISTS; else rover->flags |= FF_EXISTS; } - else + else // continue fading out { - //CONS_Printf("Fading out...\n"); rover->alpha -= d->speed; if (!d->ignoreflags) rover->flags |= FF_EXISTS; @@ -7141,14 +7133,12 @@ void T_Fade(fade_t *d) // we'll reach our destvalue if (rover->alpha + d->speed >= d->destvalue - d->speed) { - //CONS_Printf("Finished fading in\n"); rover->alpha = d->destvalue; if (!d->ignoreflags) rover->flags |= FF_EXISTS; } - else + else // continue fading in { - //CONS_Printf("Fading in...\n"); rover->alpha += d->speed; if (!d->ignoreflags) rover->flags |= FF_EXISTS; @@ -7161,7 +7151,6 @@ void T_Fade(fade_t *d) // no more ffloors to fade? remove myself if (affectedffloors == 0) { - //CONS_Printf("No more FOFs to fade!\n"); // \todo how to erase the fade_t struct? P_RemoveThinker(&d->thinker); } From bf0f24b16e88f9c63a12099640d10038fda1e10b Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 30 Mar 2018 23:29:41 -0400 Subject: [PATCH 010/306] Bring back FF_TRANSLUCENT processing for fade FOF The rules for accompanying flags are: * If FF_TRANSLUCENT, deflag FF_CUTLEVEL and flag FF_EXTRA | FF_CUTEXTRA. * If not FF_TRANSLUCENT, flag FF_CUTLEVEL and deflag FF_EXTRA | FF_CUTEXTRA * If FF_SOLID, deflag FF_CUTSPRITES * If not FF_SOLID, flag FF_CUTSPRITES This reverts commit 73c7df6f5b6a719ea36ab9b06e5735fd6fc3f892. --- src/p_spec.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 02233cf92..412ac6185 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -102,7 +102,7 @@ static void P_SpawnFriction(void); static void P_SpawnPushers(void); static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000 static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); -static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOOL handlesolid, INT32 line); +static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOOL handlesolid, BOOL handletrans, INT32 line); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); @@ -3103,6 +3103,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) sides[line->sidenum[0]].rowoffset>>FRACBITS, (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS (line->flags & ML_NOCLIMB), // handle FF_SOLID + !(line->flags & ML_EFFECT1), // do not handle FF_TRANSLUCENT (INT32)(sectors[s].lines[j]-lines)); break; } @@ -7080,9 +7081,10 @@ void T_Disappear(disappear_t *d) * \param speed speed to fade by * \param handleexist handle FF_EXISTS * \param handlesolid handle FF_SOLID + * \param handletrans do not handle FF_TRANSLUCENT * \param line line to target FOF */ -static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOOL handlesolid, INT32 line) +static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOOL handlesolid, BOOL handletrans, INT32 line) { fade_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); @@ -7100,6 +7102,9 @@ static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOO if (handlesolid) d->handleflags |= FF_SOLID; + if (handletrans) + d->handleflags |= FF_TRANSLUCENT; + P_AddThinker(&d->thinker); } @@ -7143,6 +7148,25 @@ void T_Fade(fade_t *d) && !(rover->flags & FF_SWIMMABLE) && !(rover->flags & FF_QUICKSAND)) rover->flags &= ~FF_SOLID; // make intangible at end of fade-out + + if (d->handleflags & FF_TRANSLUCENT) + { + if (rover->alpha >= 256) + { + rover->flags |= FF_CUTLEVEL; + rover->flags &= ~(FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA); + } + else + { + rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; + rover->flags &= ~FF_CUTLEVEL; + } + + if (rover->flags & FF_SOLID) + rover->flags &= ~FF_CUTSPRITES; + else + rover->flags |= FF_CUTSPRITES; + } } } else // continue fading out @@ -7157,6 +7181,17 @@ void T_Fade(fade_t *d) && !(rover->flags & FF_QUICKSAND)) rover->flags |= FF_SOLID; // keep solid during fade + if (d->handleflags & FF_TRANSLUCENT) + { + rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; + rover->flags &= ~FF_CUTLEVEL; + + if (rover->flags & FF_SOLID) + rover->flags &= ~FF_CUTSPRITES; + else + rover->flags |= FF_CUTSPRITES; + } + affectedffloors++; } } @@ -7181,6 +7216,25 @@ void T_Fade(fade_t *d) && !(rover->flags & FF_SWIMMABLE) && !(rover->flags & FF_QUICKSAND)) rover->flags |= FF_SOLID; // make solid at end of fade-in + + if (d->handleflags & FF_TRANSLUCENT) + { + if (rover->alpha >= 256) + { + rover->flags |= FF_CUTLEVEL; + rover->flags &= ~(FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA); + } + else + { + rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; + rover->flags &= ~FF_CUTLEVEL; + } + + if (rover->flags & FF_SOLID) + rover->flags &= ~FF_CUTSPRITES; + else + rover->flags |= FF_CUTSPRITES; + } } } else // continue fading in @@ -7195,6 +7249,17 @@ void T_Fade(fade_t *d) && !(rover->flags & FF_QUICKSAND)) rover->flags |= FF_SOLID; // keep solid during fade + if (d->handleflags & FF_TRANSLUCENT) + { + rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; + rover->flags &= ~FF_CUTLEVEL; + + if (rover->flags & FF_SOLID) + rover->flags &= ~FF_CUTSPRITES; + else + rover->flags |= FF_CUTSPRITES; + } + affectedffloors++; } } From c13f561b5026ffec8b444d3b3c57896628d3beed Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 31 Mar 2018 00:02:37 -0400 Subject: [PATCH 011/306] Fix fade_t handleflags to UINT32 --- src/p_saveg.c | 4 ++-- src/p_spec.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index aa48afde1..d07644c53 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1565,7 +1565,7 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->affectee); WRITEINT32(save_p, ht->destvalue); WRITEINT32(save_p, ht->speed); - WRITEUINT8(save_p, ht->handleflags); + WRITEUINT32(save_p, ht->handleflags); } // @@ -2563,7 +2563,7 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->affectee = READINT32(save_p); ht->destvalue = READINT32(save_p); ht->speed = READINT32(save_p); - ht->handleflags = READUINT8(save_p); + ht->handleflags = READUINT32(save_p); P_AddThinker(&ht->thinker); } diff --git a/src/p_spec.h b/src/p_spec.h index 9c0b3c2c5..e59e2ea0f 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -456,7 +456,7 @@ typedef struct INT32 affectee; ///< Number of affected line INT32 destvalue; ///< Transparency value to fade to INT32 speed; ///< Speed to fade by - UINT8 handleflags; ///< Do not handle FF_EXISTS + UINT32 handleflags; ///< FOF flags to handle } fade_t; void T_Fade(fade_t *d); From c1c6b4746fea8f680a08ef5c1e395fe0913f59ee Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 31 Mar 2018 00:10:46 -0400 Subject: [PATCH 012/306] Better fading comments --- src/p_spec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 412ac6185..de11369f9 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7129,7 +7129,7 @@ void T_Fade(fade_t *d) // fade out if (rover->alpha > d->destvalue) { - // we'll reach our destvalue + // finish fading out if (rover->alpha - d->speed <= d->destvalue + d->speed) { if (rover->alpha != d->destvalue) @@ -7197,7 +7197,7 @@ void T_Fade(fade_t *d) } else // fade in { - // we'll reach our destvalue + // finish fading in if (rover->alpha + d->speed >= d->destvalue - d->speed) { if (rover->alpha != d->destvalue) From 3e8d264a2d4b14ad6ed43f379e2af2ddc7d3965b Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 31 Mar 2018 00:40:41 -0400 Subject: [PATCH 013/306] Add fadingdata to sector_t --- src/p_saveg.c | 7 ++++++- src/p_setup.c | 1 + src/r_defs.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index d07644c53..b22b6495e 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2564,6 +2564,11 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->destvalue = READINT32(save_p); ht->speed = READINT32(save_p); ht->handleflags = READUINT32(save_p); + + sector_t *ffloorsector = LoadSector(ht->affectee); + if (ffloorsector) + ffloorsector->fadingdata = ht; + P_AddThinker(&ht->thinker); } @@ -2753,7 +2758,7 @@ static void P_NetUnArchiveThinkers(void) // clear sector thinker pointers so they don't point to non-existant thinkers for all of eternity for (i = 0; i < numsectors; i++) { - sectors[i].floordata = sectors[i].ceilingdata = sectors[i].lightingdata = NULL; + sectors[i].floordata = sectors[i].ceilingdata = sectors[i].lightingdata = sectors[i].fadingdata = NULL; } // read in saved thinkers diff --git a/src/p_setup.c b/src/p_setup.c index a9fc57652..3edae5655 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -693,6 +693,7 @@ static void P_LoadRawSectors(UINT8 *data, size_t i) ss->floordata = NULL; ss->ceilingdata = NULL; ss->lightingdata = NULL; + ss->fadingdata = NULL; ss->linecount = 0; ss->lines = NULL; diff --git a/src/r_defs.h b/src/r_defs.h index 7c8f2a73f..b4c7d2112 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -308,6 +308,7 @@ typedef struct sector_s void *floordata; // floor move thinker void *ceilingdata; // ceiling move thinker void *lightingdata; // lighting change thinker + void *fadingdata; // fading FOF thinker // floor and ceiling texture offsets fixed_t floor_xoffs, floor_yoffs; From cd7573550b99d76fbdf03d21f717bf7f7583e9ad Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 31 Mar 2018 01:15:24 -0400 Subject: [PATCH 014/306] Remove fader thinkers by stored pointers in fadingdata --- src/p_spec.c | 46 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index de11369f9..789ab6c43 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -102,6 +102,8 @@ static void P_SpawnFriction(void); static void P_SpawnPushers(void); static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000 static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); +static void P_ResetFading(line_t *line, fade_t *data); +#define P_RemoveFading(l) P_ResetFading(l, NULL); static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOOL handlesolid, BOOL handletrans, INT32 line); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); @@ -3109,7 +3111,14 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } case 453: // Stop fading FOF + { + INT32 s, j; + for (s = -1; (s = P_FindSectorFromLineTag(line, s)) >= 0 ;) + for (j = 0; (unsigned)j < sectors[s].linecount; j++) + if (sectors[s].lines[j]->special >= 100 && sectors[s].lines[j]->special < 300) + P_RemoveFading(&lines[(INT32)(sectors[s].lines[j]-lines)]); break; + } #ifdef POLYOBJECTS case 480: // Polyobj_DoorSlide @@ -7075,6 +7084,35 @@ void T_Disappear(disappear_t *d) } } +/** Removes fadingdata from FOF control sector + * + * \param line line to search for target faders + * \param data pointer to set new fadingdata to. Can be NULL to erase. + */ +static void P_ResetFading(line_t *line, fade_t *data) +{ + ffloor_t *rover; + register INT32 s; + + // find any existing thinkers and remove them, then replace with new data + for (s = -1; (s = P_FindSectorFromLineTag(line, s)) >= 0 ;) + { + for (rover = sectors[s].ffloors; rover; rover = rover->next) + { + if (rover->master != line) + continue; + + if(((fade_t *)rover->master->frontsector->fadingdata) != data) + { + if(&((fade_t *)rover->master->frontsector->fadingdata)->thinker) + P_RemoveThinker(&((fade_t *)rover->master->frontsector->fadingdata)->thinker); + + rover->master->frontsector->fadingdata = data; + } + } + } +} + /** Adds master fader thinker. * * \param destvalue transparency value to fade to @@ -7105,6 +7143,9 @@ static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOO if (handletrans) d->handleflags |= FF_TRANSLUCENT; + // find any existing thinkers and remove them, then replace with new data + P_ResetFading(&lines[d->affectee], d); + P_AddThinker(&d->thinker); } @@ -7268,10 +7309,7 @@ void T_Fade(fade_t *d) // no more ffloors to fade? remove myself if (affectedffloors == 0) - { - // \todo how to erase the fade_t struct? - P_RemoveThinker(&d->thinker); - } + P_RemoveFading(&lines[d->affectee]); } /* From 73e4cab1e48b84e5a31b45a69f1323feb126b234 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 6 Apr 2018 22:34:45 -0400 Subject: [PATCH 015/306] Little adjustments * Swap MF_NOCLIMB and MF_EFFECT1 * Implement if Front Y Offset < 1 (== 0), then set alpha immediately --- src/p_spec.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 0f0a2996d..c60771dbf 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3105,8 +3105,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_AddMasterFader(sides[line->sidenum[0]].textureoffset>>FRACBITS, sides[line->sidenum[0]].rowoffset>>FRACBITS, (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS - (line->flags & ML_NOCLIMB), // handle FF_SOLID - !(line->flags & ML_EFFECT1), // do not handle FF_TRANSLUCENT + (line->flags & ML_EFFECT1), // handle FF_SOLID + !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT (INT32)(sectors[s].lines[j]-lines)); break; } @@ -7130,7 +7130,7 @@ static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOO d->thinker.function.acp1 = (actionf_p1)T_Fade; d->affectee = line; d->destvalue = max(1, min(256, destvalue)); // ffloor->alpha is 1-256 - d->speed = max(1, speed); // minimum speed 1/tic + d->speed = speed; // minimum speed 1/tic // if speed < 1, alpha is set immediately in thinker // combine the flags-to-handle, this is more convenient than separate BOOLS d->handleflags = 0; @@ -7172,7 +7172,7 @@ void T_Fade(fade_t *d) if (rover->alpha > d->destvalue) { // finish fading out - if (rover->alpha - d->speed <= d->destvalue + d->speed) + if (d->speed < 1 || rover->alpha - d->speed <= d->destvalue + d->speed) { if (rover->alpha != d->destvalue) { @@ -7240,7 +7240,7 @@ void T_Fade(fade_t *d) else // fade in { // finish fading in - if (rover->alpha + d->speed >= d->destvalue - d->speed) + if (d->speed < 1 || rover->alpha + d->speed >= d->destvalue - d->speed) { if (rover->alpha != d->destvalue) { From afa0aae131ff2bfce85fa047b943d5990fbdcb30 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 6 Apr 2018 23:14:48 -0400 Subject: [PATCH 016/306] Refactor flag handling toggles --- src/p_saveg.c | 12 ++++++++-- src/p_spec.c | 61 ++++++++++++++++++++++++++------------------------- src/p_spec.h | 6 ++++- 3 files changed, 46 insertions(+), 33 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index b22b6495e..e8643b6b1 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1565,7 +1565,11 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->affectee); WRITEINT32(save_p, ht->destvalue); WRITEINT32(save_p, ht->speed); - WRITEUINT32(save_p, ht->handleflags); + WRITEUINT8(save_p, ht->doexists); + WRITEUINT8(save_p, ht->dotranslucent); + WRITEUINT8(save_p, ht->dosolid); + WRITEUINT8(save_p, ht->dospawnflags); + WRITEUINT8(save_p, ht->dofadeinonly); } // @@ -2563,7 +2567,11 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->affectee = READINT32(save_p); ht->destvalue = READINT32(save_p); ht->speed = READINT32(save_p); - ht->handleflags = READUINT32(save_p); + ht->doexists = READUINT8(save_p); + ht->dotranslucent = READUINT8(save_p); + ht->dosolid = READUINT8(save_p); + ht->dospawnflags = READUINT8(save_p); + ht->dofadeinonly = READUINT8(save_p); sector_t *ffloorsector = LoadSector(ht->affectee); if (ffloorsector) diff --git a/src/p_spec.c b/src/p_spec.c index c60771dbf..f1425d857 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -105,7 +105,9 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t * static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); static void P_ResetFading(line_t *line, fade_t *data); #define P_RemoveFading(l) P_ResetFading(l, NULL); -static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOOL handlesolid, BOOL handletrans, INT32 line); +static void P_AddMasterFader(INT32 destvalue, INT32 speed, + BOOL doexists, BOOL dotranslucent, BOOL dosolid, BOOL dospawnflags + , BOOL dofadeinonly, INT32 line); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); @@ -3105,8 +3107,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_AddMasterFader(sides[line->sidenum[0]].textureoffset>>FRACBITS, sides[line->sidenum[0]].rowoffset>>FRACBITS, (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS - (line->flags & ML_EFFECT1), // handle FF_SOLID !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT + (line->flags & ML_BOUNCY), // handle FF_SOLID + (line->flags & ML_EFFECT1), // handle spawnflags + (line->flags & ML_EFFECT2), // enable flags on fade-in finish only (INT32)(sectors[s].lines[j]-lines)); break; } @@ -7118,12 +7122,16 @@ static void P_ResetFading(line_t *line, fade_t *data) * * \param destvalue transparency value to fade to * \param speed speed to fade by - * \param handleexist handle FF_EXISTS - * \param handlesolid handle FF_SOLID - * \param handletrans do not handle FF_TRANSLUCENT + * \param doexists handle FF_EXISTS + * \param dotranslucent handle FF_TRANSLUCENT + * \param dosolid handle FF_SOLID + * \param dospawnflags handle spawnflags + * \param dofadeinonly enable flags when fade-in is finished; never on fade-out * \param line line to target FOF */ -static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOOL handlesolid, BOOL handletrans, INT32 line) +static void P_AddMasterFader(INT32 destvalue, INT32 speed, + BOOL doexists, BOOL dotranslucent, BOOL dosolid, BOOL dospawnflags + , BOOL dofadeinonly, INT32 line) { fade_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); @@ -7131,18 +7139,11 @@ static void P_AddMasterFader(INT32 destvalue, INT32 speed, BOOL handleexist, BOO d->affectee = line; d->destvalue = max(1, min(256, destvalue)); // ffloor->alpha is 1-256 d->speed = speed; // minimum speed 1/tic // if speed < 1, alpha is set immediately in thinker - - // combine the flags-to-handle, this is more convenient than separate BOOLS - d->handleflags = 0; - - if (handleexist) - d->handleflags |= FF_EXISTS; - - if (handlesolid) - d->handleflags |= FF_SOLID; - - if (handletrans) - d->handleflags |= FF_TRANSLUCENT; + d->doexists = doexists; + d->dotranslucent = dotranslucent; + d->dosolid = dosolid; + d->dospawnflags = dospawnflags; + d->dofadeinonly = dofadeinonly; // find any existing thinkers and remove them, then replace with new data P_ResetFading(&lines[d->affectee], d); @@ -7178,7 +7179,7 @@ void T_Fade(fade_t *d) { rover->alpha = d->destvalue; - if (d->handleflags & FF_EXISTS) + if (d->doexists) { if (rover->alpha <= 1) rover->flags &= ~FF_EXISTS; @@ -7186,12 +7187,12 @@ void T_Fade(fade_t *d) rover->flags |= FF_EXISTS; } - if ((d->handleflags & FF_SOLID) + if (d->dosolid && !(rover->flags & FF_SWIMMABLE) && !(rover->flags & FF_QUICKSAND)) rover->flags &= ~FF_SOLID; // make intangible at end of fade-out - if (d->handleflags & FF_TRANSLUCENT) + if (d->dotranslucent) { if (rover->alpha >= 256) { @@ -7215,15 +7216,15 @@ void T_Fade(fade_t *d) { rover->alpha -= d->speed; - if (d->handleflags & FF_EXISTS) + if (d->doexists) rover->flags |= FF_EXISTS; - if ((d->handleflags & FF_SOLID) + if (d->dosolid && !(rover->flags & FF_SWIMMABLE) && !(rover->flags & FF_QUICKSAND)) rover->flags |= FF_SOLID; // keep solid during fade - if (d->handleflags & FF_TRANSLUCENT) + if (d->dotranslucent) { rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; rover->flags &= ~FF_CUTLEVEL; @@ -7246,7 +7247,7 @@ void T_Fade(fade_t *d) { rover->alpha = d->destvalue; - if (d->handleflags & FF_EXISTS) + if (d->doexists) { if (rover->alpha <= 1) rover->flags &= ~FF_EXISTS; @@ -7254,12 +7255,12 @@ void T_Fade(fade_t *d) rover->flags |= FF_EXISTS; } - if ((d->handleflags & FF_SOLID) + if (d->dosolid && !(rover->flags & FF_SWIMMABLE) && !(rover->flags & FF_QUICKSAND)) rover->flags |= FF_SOLID; // make solid at end of fade-in - if (d->handleflags & FF_TRANSLUCENT) + if (d->dotranslucent) { if (rover->alpha >= 256) { @@ -7283,15 +7284,15 @@ void T_Fade(fade_t *d) { rover->alpha += d->speed; - if (d->handleflags & FF_EXISTS) + if (d->doexists) rover->flags |= FF_EXISTS; - if ((d->handleflags & FF_SOLID) + if (d->dosolid && !(rover->flags & FF_SWIMMABLE) && !(rover->flags & FF_QUICKSAND)) rover->flags |= FF_SOLID; // keep solid during fade - if (d->handleflags & FF_TRANSLUCENT) + if (d->dotranslucent) { rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; rover->flags &= ~FF_CUTLEVEL; diff --git a/src/p_spec.h b/src/p_spec.h index e59e2ea0f..670fe116e 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -456,7 +456,11 @@ typedef struct INT32 affectee; ///< Number of affected line INT32 destvalue; ///< Transparency value to fade to INT32 speed; ///< Speed to fade by - UINT32 handleflags; ///< FOF flags to handle + boolean doexists; ///< Handle FF_EXISTS handling + boolean dotranslucent; ///< Handle FF_TRANSLUCENT handling + boolean dosolid; ///< Handle FF_SOLID handling + boolean dospawnflags; ///< Enable spawnflags handling + boolean dofadeinonly; ///< Set flags only when fade-in is finished; never during fade-out } fade_t; void T_Fade(fade_t *d); From 27ca70d06968f4d6faf62c30472f0d3d00c90510 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 7 Apr 2018 05:52:01 -0400 Subject: [PATCH 017/306] checkpoint --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index f1425d857..66097740a 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7138,7 +7138,7 @@ static void P_AddMasterFader(INT32 destvalue, INT32 speed, d->thinker.function.acp1 = (actionf_p1)T_Fade; d->affectee = line; d->destvalue = max(1, min(256, destvalue)); // ffloor->alpha is 1-256 - d->speed = speed; // minimum speed 1/tic // if speed < 1, alpha is set immediately in thinker + d->speed = max(1, speed); // minimum speed 1/tic // if speed < 1, alpha is set immediately in thinker d->doexists = doexists; d->dotranslucent = dotranslucent; d->dosolid = dosolid; From bd6276a39ec2210776a80a333c897fbd46648561 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 7 Apr 2018 07:09:04 -0400 Subject: [PATCH 018/306] Allow immediate alpha setting when speed = 0; refactoring * Separate fade logic into P_FindFakeFloorsDoAlpha, P_DoFakeFloorAlpha * Change INT32 destvalue and speed to INT16 --- src/p_saveg.c | 8 +- src/p_spec.c | 364 +++++++++++++++++++++++++++----------------------- src/p_spec.h | 4 +- 3 files changed, 206 insertions(+), 170 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index e8643b6b1..e8e5b4eb6 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1563,8 +1563,8 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type) const fade_t *ht = (const void *)th; WRITEUINT8(save_p, type); WRITEINT32(save_p, ht->affectee); - WRITEINT32(save_p, ht->destvalue); - WRITEINT32(save_p, ht->speed); + WRITEINT16(save_p, ht->destvalue); + WRITEINT16(save_p, ht->speed); WRITEUINT8(save_p, ht->doexists); WRITEUINT8(save_p, ht->dotranslucent); WRITEUINT8(save_p, ht->dosolid); @@ -2565,8 +2565,8 @@ static inline void LoadFadeThinker(actionf_p1 thinker) fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; ht->affectee = READINT32(save_p); - ht->destvalue = READINT32(save_p); - ht->speed = READINT32(save_p); + ht->destvalue = READINT16(save_p); + ht->speed = READINT16(save_p); ht->doexists = READUINT8(save_p); ht->dotranslucent = READUINT8(save_p); ht->dosolid = READUINT8(save_p); diff --git a/src/p_spec.c b/src/p_spec.c index 66097740a..f3ea699d6 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -105,9 +105,12 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t * static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); static void P_ResetFading(line_t *line, fade_t *data); #define P_RemoveFading(l) P_ResetFading(l, NULL); -static void P_AddMasterFader(INT32 destvalue, INT32 speed, - BOOL doexists, BOOL dotranslucent, BOOL dosolid, BOOL dospawnflags - , BOOL dofadeinonly, INT32 line); +static INT32 P_FindFakeFloorsDoAlpha(INT16 destvalue, INT16 speed, + boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, + boolean dofadeinonly, INT32 line); +static void P_AddMasterFader(INT16 destvalue, INT16 speed, + boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, + boolean dofadeinonly, INT32 line); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); @@ -3104,14 +3107,29 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) for (s = -1; (s = P_FindSectorFromLineTag(line, s)) >= 0 ;) for (j = 0; (unsigned)j < sectors[s].linecount; j++) if (sectors[s].lines[j]->special >= 100 && sectors[s].lines[j]->special < 300) - P_AddMasterFader(sides[line->sidenum[0]].textureoffset>>FRACBITS, - sides[line->sidenum[0]].rowoffset>>FRACBITS, - (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS - !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT - (line->flags & ML_BOUNCY), // handle FF_SOLID - (line->flags & ML_EFFECT1), // handle spawnflags - (line->flags & ML_EFFECT2), // enable flags on fade-in finish only - (INT32)(sectors[s].lines[j]-lines)); + { + if (sides[line->sidenum[0]].rowoffset>>FRACBITS > 0) + P_AddMasterFader(sides[line->sidenum[0]].textureoffset>>FRACBITS, + sides[line->sidenum[0]].rowoffset>>FRACBITS, + (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS + !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT + (line->flags & ML_BOUNCY), // handle FF_SOLID + (line->flags & ML_EFFECT1), // handle spawnflags + (line->flags & ML_EFFECT2), // enable flags on fade-in finish only + (INT32)(sectors[s].lines[j]-lines)); + else + { + P_RemoveFading(&lines[(INT32)(sectors[s].lines[j]-lines)]); + P_FindFakeFloorsDoAlpha(sides[line->sidenum[0]].textureoffset>>FRACBITS, + 0, // set alpha immediately + (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS + !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT + (line->flags & ML_BOUNCY), // handle FF_SOLID + (line->flags & ML_EFFECT1), // handle spawnflags + (line->flags & ML_EFFECT2), // enable flags on fade-in finish only + (INT32)(sectors[s].lines[j]-lines)); + } + } break; } @@ -7118,6 +7136,171 @@ static void P_ResetFading(line_t *line, fade_t *data) } } +static boolean P_DoFakeFloorAlpha(ffloor_t *rover, INT16 destvalue, INT16 speed, + boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, + boolean dofadeinonly) +{ + boolean result = false; + + if (rover->alpha == destvalue) + return result; + // fade out + else if (rover->alpha > destvalue) + { + // finish fading out + if (speed < 1 || rover->alpha - speed <= destvalue + speed) + { + rover->alpha = destvalue; + + if (doexists) + { + if (rover->alpha <= 1) + rover->flags &= ~FF_EXISTS; + else + rover->flags |= FF_EXISTS; + } + + if (dosolid + && !(rover->flags & FF_SWIMMABLE) + && !(rover->flags & FF_QUICKSAND)) + rover->flags &= ~FF_SOLID; // make intangible at end of fade-out + + if (dotranslucent) + { + if (rover->alpha >= 256) + { + rover->flags |= FF_CUTLEVEL; + rover->flags &= ~(FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA); + } + else + { + rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; + rover->flags &= ~FF_CUTLEVEL; + } + + if (rover->flags & FF_SOLID) + rover->flags &= ~FF_CUTSPRITES; + else + rover->flags |= FF_CUTSPRITES; + } + } + else // continue fading out + { + rover->alpha -= speed; + + if (doexists) + rover->flags |= FF_EXISTS; + + if (dosolid + && !(rover->flags & FF_SWIMMABLE) + && !(rover->flags & FF_QUICKSAND)) + rover->flags |= FF_SOLID; // keep solid during fade + + if (dotranslucent) + { + rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; + rover->flags &= ~FF_CUTLEVEL; + + if (rover->flags & FF_SOLID) + rover->flags &= ~FF_CUTSPRITES; + else + rover->flags |= FF_CUTSPRITES; + } + + result = true; + } + } + else // fade in + { + // finish fading in + if (speed < 1 || rover->alpha + speed >= destvalue - speed) + { + rover->alpha = destvalue; + + if (doexists) + { + if (rover->alpha <= 1) + rover->flags &= ~FF_EXISTS; + else + rover->flags |= FF_EXISTS; + } + + if (dosolid + && !(rover->flags & FF_SWIMMABLE) + && !(rover->flags & FF_QUICKSAND)) + rover->flags |= FF_SOLID; // make solid at end of fade-in + + if (dotranslucent) + { + if (rover->alpha >= 256) + { + rover->flags |= FF_CUTLEVEL; + rover->flags &= ~(FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA); + } + else + { + rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; + rover->flags &= ~FF_CUTLEVEL; + } + + if (rover->flags & FF_SOLID) + rover->flags &= ~FF_CUTSPRITES; + else + rover->flags |= FF_CUTSPRITES; + } + } + else // continue fading in + { + rover->alpha += speed; + + if (doexists) + rover->flags |= FF_EXISTS; + + if (dosolid + && !(rover->flags & FF_SWIMMABLE) + && !(rover->flags & FF_QUICKSAND)) + rover->flags |= FF_SOLID; // keep solid during fade + + if (dotranslucent) + { + rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; + rover->flags &= ~FF_CUTLEVEL; + + if (rover->flags & FF_SOLID) + rover->flags &= ~FF_CUTSPRITES; + else + rover->flags |= FF_CUTSPRITES; + } + + result = true; + } + } + + return result; +} + +static INT32 P_FindFakeFloorsDoAlpha(INT16 destvalue, INT16 speed, + boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, + boolean dofadeinonly, INT32 line) +{ + ffloor_t *rover; + register INT32 s; + INT32 affectedffloors = 0; + + for (s = -1; (s = P_FindSectorFromLineTag(&lines[line], s)) >= 0 ;) + { + for (rover = sectors[s].ffloors; rover; rover = rover->next) + { + if (rover->master != &lines[line]) + continue; + + affectedffloors += (INT32)P_DoFakeFloorAlpha(rover, destvalue, speed, doexists, dotranslucent, dosolid, dospawnflags, dofadeinonly); + } + } + + return affectedffloors; +} + /** Adds master fader thinker. * * \param destvalue transparency value to fade to @@ -7129,9 +7312,9 @@ static void P_ResetFading(line_t *line, fade_t *data) * \param dofadeinonly enable flags when fade-in is finished; never on fade-out * \param line line to target FOF */ -static void P_AddMasterFader(INT32 destvalue, INT32 speed, - BOOL doexists, BOOL dotranslucent, BOOL dosolid, BOOL dospawnflags - , BOOL dofadeinonly, INT32 line) +static void P_AddMasterFader(INT16 destvalue, INT16 speed, + boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, + boolean dofadeinonly, INT32 line) { fade_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); @@ -7158,156 +7341,9 @@ static void P_AddMasterFader(INT32 destvalue, INT32 speed, */ void T_Fade(fade_t *d) { - ffloor_t *rover; - register INT32 s; - INT32 affectedffloors = 0; - - for (s = -1; (s = P_FindSectorFromLineTag(&lines[d->affectee], s)) >= 0 ;) - { - for (rover = sectors[s].ffloors; rover; rover = rover->next) - { - if (rover->master != &lines[d->affectee]) - continue; - - // fade out - if (rover->alpha > d->destvalue) - { - // finish fading out - if (d->speed < 1 || rover->alpha - d->speed <= d->destvalue + d->speed) - { - if (rover->alpha != d->destvalue) - { - rover->alpha = d->destvalue; - - if (d->doexists) - { - if (rover->alpha <= 1) - rover->flags &= ~FF_EXISTS; - else - rover->flags |= FF_EXISTS; - } - - if (d->dosolid - && !(rover->flags & FF_SWIMMABLE) - && !(rover->flags & FF_QUICKSAND)) - rover->flags &= ~FF_SOLID; // make intangible at end of fade-out - - if (d->dotranslucent) - { - if (rover->alpha >= 256) - { - rover->flags |= FF_CUTLEVEL; - rover->flags &= ~(FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA); - } - else - { - rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; - rover->flags &= ~FF_CUTLEVEL; - } - - if (rover->flags & FF_SOLID) - rover->flags &= ~FF_CUTSPRITES; - else - rover->flags |= FF_CUTSPRITES; - } - } - } - else // continue fading out - { - rover->alpha -= d->speed; - - if (d->doexists) - rover->flags |= FF_EXISTS; - - if (d->dosolid - && !(rover->flags & FF_SWIMMABLE) - && !(rover->flags & FF_QUICKSAND)) - rover->flags |= FF_SOLID; // keep solid during fade - - if (d->dotranslucent) - { - rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; - rover->flags &= ~FF_CUTLEVEL; - - if (rover->flags & FF_SOLID) - rover->flags &= ~FF_CUTSPRITES; - else - rover->flags |= FF_CUTSPRITES; - } - - affectedffloors++; - } - } - else // fade in - { - // finish fading in - if (d->speed < 1 || rover->alpha + d->speed >= d->destvalue - d->speed) - { - if (rover->alpha != d->destvalue) - { - rover->alpha = d->destvalue; - - if (d->doexists) - { - if (rover->alpha <= 1) - rover->flags &= ~FF_EXISTS; - else - rover->flags |= FF_EXISTS; - } - - if (d->dosolid - && !(rover->flags & FF_SWIMMABLE) - && !(rover->flags & FF_QUICKSAND)) - rover->flags |= FF_SOLID; // make solid at end of fade-in - - if (d->dotranslucent) - { - if (rover->alpha >= 256) - { - rover->flags |= FF_CUTLEVEL; - rover->flags &= ~(FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA); - } - else - { - rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; - rover->flags &= ~FF_CUTLEVEL; - } - - if (rover->flags & FF_SOLID) - rover->flags &= ~FF_CUTSPRITES; - else - rover->flags |= FF_CUTSPRITES; - } - } - } - else // continue fading in - { - rover->alpha += d->speed; - - if (d->doexists) - rover->flags |= FF_EXISTS; - - if (d->dosolid - && !(rover->flags & FF_SWIMMABLE) - && !(rover->flags & FF_QUICKSAND)) - rover->flags |= FF_SOLID; // keep solid during fade - - if (d->dotranslucent) - { - rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; - rover->flags &= ~FF_CUTLEVEL; - - if (rover->flags & FF_SOLID) - rover->flags &= ~FF_CUTSPRITES; - else - rover->flags |= FF_CUTSPRITES; - } - - affectedffloors++; - } - } - } - } + INT32 affectedffloors = P_FindFakeFloorsDoAlpha(d->destvalue, d->speed, + d->doexists, d->dotranslucent, d->dosolid, d->dospawnflags, + d->dofadeinonly, d->affectee); // no more ffloors to fade? remove myself if (affectedffloors == 0) diff --git a/src/p_spec.h b/src/p_spec.h index 670fe116e..c8607f868 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -454,8 +454,8 @@ typedef struct { thinker_t thinker; ///< Thinker structure for effect. INT32 affectee; ///< Number of affected line - INT32 destvalue; ///< Transparency value to fade to - INT32 speed; ///< Speed to fade by + INT16 destvalue; ///< Transparency value to fade to + INT16 speed; ///< Speed to fade by boolean doexists; ///< Handle FF_EXISTS handling boolean dotranslucent; ///< Handle FF_TRANSLUCENT handling boolean dosolid; ///< Handle FF_SOLID handling From 89478a7ba46eaa4932dc45bbfdaf520343e1e46d Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 14 Jun 2018 21:51:21 +0100 Subject: [PATCH 019/306] Added linedef 447 as the change colormap linedef exec special. IMPORTANT NOTE: UNTESTED --- src/p_setup.c | 1 + src/p_spec.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/src/p_setup.c b/src/p_setup.c index a5544c26b..052006a35 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1428,6 +1428,7 @@ static void P_LoadRawSideDefs2(void *data) { case 63: // variable colormap via 242 linedef case 606: //SoM: 4/4/2000: Just colormap transfer + case 447: // Change colormap of tagged sectors! -- Monster Iestyn 14/06/18 // SoM: R_CreateColormap will only create a colormap in software mode... // Perhaps we should just call it instead of doing the calculations here. if (rendermode == render_soft || rendermode == render_none) diff --git a/src/p_spec.c b/src/p_spec.c index 93b5c89ca..9d1e85366 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3033,6 +3033,15 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } break; + case 447: // Change colormap of tagged sectors! + // Basically this special applies a colormap to the tagged sectors, just like 606 (the colormap linedef) + // Except it is activated by linedef executor, not level load + // This could even override existing colormaps I believe + // -- Monster Iestyn 14/06/18 + for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;) + sectors[secnum].midmap = line->frontsector->midmap; + break; + case 448: // Change skybox viewpoint/centerpoint if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || (line->flags & ML_NOCLIMB)) { From 61999100e5c8a73e1d6304fc5add3979c1283f20 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 12 Aug 2018 19:19:41 -0400 Subject: [PATCH 020/306] totalmarescore player variable for NiGHTS scoring --- src/d_player.h | 1 + src/lua_playerlib.c | 4 ++++ src/p_saveg.c | 2 ++ src/p_setup.c | 4 ++-- src/p_user.c | 2 ++ 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 7bee5f337..bc6a171d9 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -465,6 +465,7 @@ typedef struct player_s INT16 finishedrings; // The rings/stars you had left upon finishing the mare UINT32 marescore; // score for this nights stage UINT32 lastmarescore; // score for the last mare + UINT32 totalmarescore; // score for all mares UINT8 lastmare; // previous mare INT32 maxlink; // maximum link obtained UINT8 texttimer; // nights_texttime should not be local diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index ff62f2459..504097558 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -304,6 +304,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->marescore); else if (fastcmp(field,"lastmarescore")) lua_pushinteger(L, plr->lastmarescore); + else if (fastcmp(field,"totalmarescore")) + lua_pushinteger(L, plr->totalmarescore); else if (fastcmp(field,"lastmare")) lua_pushinteger(L, plr->lastmare); else if (fastcmp(field,"maxlink")) @@ -584,6 +586,8 @@ static int player_set(lua_State *L) plr->marescore = (UINT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"lastmarescore")) plr->lastmarescore = (UINT32)luaL_checkinteger(L, 3); + else if (fastcmp(field,"totalmarescore")) + plr->totalmarescore = (UINT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"lastmare")) plr->lastmare = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"maxlink")) diff --git a/src/p_saveg.c b/src/p_saveg.c index 7cf437384..6b2b61048 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -206,6 +206,7 @@ static void P_NetArchivePlayers(void) WRITEINT16(save_p, players[i].finishedrings); WRITEUINT32(save_p, players[i].marescore); WRITEUINT32(save_p, players[i].lastmarescore); + WRITEUINT32(save_p, players[i].totalmarescore); WRITEUINT8(save_p, players[i].lastmare); WRITEINT32(save_p, players[i].maxlink); WRITEUINT8(save_p, players[i].texttimer); @@ -395,6 +396,7 @@ static void P_NetUnArchivePlayers(void) players[i].finishedrings = READINT16(save_p); players[i].marescore = READUINT32(save_p); players[i].lastmarescore = READUINT32(save_p); + players[i].totalmarescore = READUINT32(save_p); players[i].lastmare = READUINT8(save_p); players[i].maxlink = READINT32(save_p); players[i].texttimer = READUINT8(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index c62f281b3..285e4d22d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2385,8 +2385,8 @@ static void P_LevelInitStuff(void) players[i].texttimer = players[i].linkcount =\ players[i].linktimer = players[i].flyangle =\ players[i].anotherflyangle = players[i].nightstime =\ - players[i].mare = players[i].realtime =\ - players[i].exiting = 0; + players[i].mare = players[i].totalmarescore =\ + players[i].realtime = players[i].exiting = 0; // i guess this could be part of the above but i feel mildly uncomfortable implicitly casting players[i].gotcontinue = false; diff --git a/src/p_user.c b/src/p_user.c index fd09b0847..6728a3c54 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -725,6 +725,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) G_AddTempNightsRecords(players[i].marescore, leveltime - player->marebegunat, players[i].mare + 1); // transfer scores anyway + players[i].totalmarescore += players[i].marescore; players[i].lastmarescore = players[i].marescore; players[i].marescore = 0; @@ -748,6 +749,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) G_AddTempNightsRecords(player->marescore, leveltime - player->marebegunat, (UINT8)(oldmare + 1)); // Starting a new mare, transfer scores + player->totalmarescore += players[i].marescore; player->lastmarescore = player->marescore; player->marescore = 0; player->marebegunat = leveltime; From 30d57eac7912a7a99e506a4c975566ccefe444b0 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 12 Aug 2018 19:23:23 -0400 Subject: [PATCH 021/306] NiGHTS bonus implementation --- src/dehacked.c | 3 +++ src/y_inter.c | 30 +++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/dehacked.c b/src/dehacked.c index fb0f958c3..35b0ce4b1 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1196,6 +1196,9 @@ static void readlevelheader(MYFILE *f, INT32 num) else if (fastcmp(word2, "NORMAL")) i = 0; else if (fastcmp(word2, "BOSS")) i = 1; else if (fastcmp(word2, "ERZ3")) i = 2; + else if (fastcmp(word2, "NIGHTS")) i = 3; + else if (fastcmp(word2, "NIGHTSLINK")) i = 4; + else if (fastcmp(word2, "NIGHTSALL")) i = 5; if (i >= -1 && i <= 2) // -1 for no bonus. Max is 2. mapheaderinfo[num-1]->bonustype = (SINT8)i; diff --git a/src/y_inter.c b/src/y_inter.c index 68dda198c..b3603bb34 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1754,6 +1754,16 @@ static void Y_SetRingBonus(player_t *player, y_bonus_t *bstruct) bstruct->points = max(0, (player->rings) * 100); } +// +// Y_SetNightsBonus +// +static void Y_SetNightsBonus(player_t *player, y_bonus_t *bstruct) +{ + strncpy(bstruct->patch, "YB_NIGHT", sizeof(bstruct->patch)); + bstruct->display = true; + bstruct->points = player->totalmarescore; +} + // // Y_SetLinkBonus // @@ -1815,7 +1825,7 @@ static void Y_SetPerfectBonus(player_t *player, y_bonus_t *bstruct) // This list can be extended in the future with SOC/Lua, perhaps. typedef void (*bonus_f)(player_t *, y_bonus_t *); -bonus_f bonuses_list[4][4] = { +bonus_f bonuses_list[7][4] = { { Y_SetNullBonus, Y_SetNullBonus, @@ -1840,6 +1850,24 @@ bonus_f bonuses_list[4][4] = { Y_SetRingBonus, Y_SetPerfectBonus, }, + { + Y_SetNullBonus, + Y_SetNightsBonus, + Y_SetNullBonus, + Y_SetNullBonus, + }, + { + Y_SetNullBonus, + Y_SetLinkBonus, + Y_SetNullBonus, + Y_SetNullBonus, + }, + { + Y_SetNullBonus, + Y_SetNightsBonus, + Y_SetLinkBonus, + Y_SetNullBonus, + }, }; From 372fc540bccf12bc3df9659a18c51d0bf6610aaa Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 12 Aug 2018 19:26:18 -0400 Subject: [PATCH 022/306] Totalmarescore typo --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 6728a3c54..d8f096109 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -749,7 +749,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) G_AddTempNightsRecords(player->marescore, leveltime - player->marebegunat, (UINT8)(oldmare + 1)); // Starting a new mare, transfer scores - player->totalmarescore += players[i].marescore; + player->totalmarescore += player->marescore; player->lastmarescore = player->marescore; player->marescore = 0; player->marebegunat = leveltime; From feadcbfc949076caa74554e561f2464a0df32742 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 12 Aug 2018 19:29:35 -0400 Subject: [PATCH 023/306] BONUSTYPE typo; bonus alignment --- src/dehacked.c | 2 +- src/y_inter.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 35b0ce4b1..41d41405c 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1200,7 +1200,7 @@ static void readlevelheader(MYFILE *f, INT32 num) else if (fastcmp(word2, "NIGHTSLINK")) i = 4; else if (fastcmp(word2, "NIGHTSALL")) i = 5; - if (i >= -1 && i <= 2) // -1 for no bonus. Max is 2. + if (i >= -1 && i <= 5) // -1 for no bonus. Max is 2. mapheaderinfo[num-1]->bonustype = (SINT8)i; else deh_warning("Level header %d: invalid bonus type number %d", num, i); diff --git a/src/y_inter.c b/src/y_inter.c index b3603bb34..de0335523 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1852,14 +1852,14 @@ bonus_f bonuses_list[7][4] = { }, { Y_SetNullBonus, - Y_SetNightsBonus, Y_SetNullBonus, + Y_SetNightsBonus, Y_SetNullBonus, }, { Y_SetNullBonus, - Y_SetLinkBonus, Y_SetNullBonus, + Y_SetLinkBonus, Y_SetNullBonus, }, { From fe904b0eb28ba4d32280a86c5ee0364c67f14710 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 12 Aug 2018 19:45:34 -0400 Subject: [PATCH 024/306] NiGHTS lap score bonus --- src/dehacked.c | 6 ++++-- src/y_inter.c | 26 ++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 41d41405c..c672cbee4 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1198,9 +1198,11 @@ static void readlevelheader(MYFILE *f, INT32 num) else if (fastcmp(word2, "ERZ3")) i = 2; else if (fastcmp(word2, "NIGHTS")) i = 3; else if (fastcmp(word2, "NIGHTSLINK")) i = 4; - else if (fastcmp(word2, "NIGHTSALL")) i = 5; + else if (fastcmp(word2, "NIGHTSLAP")) i = 5; + else if (fastcmp(word2, "NIGHTSLINKLAP")) i = 6; + else if (fastcmp(word2, "NIGHTSALL")) i = 7; - if (i >= -1 && i <= 5) // -1 for no bonus. Max is 2. + if (i >= -1 && i <= 7) // -1 for no bonus. Max is 2. mapheaderinfo[num-1]->bonustype = (SINT8)i; else deh_warning("Level header %d: invalid bonus type number %d", num, i); diff --git a/src/y_inter.c b/src/y_inter.c index de0335523..f34bc06c0 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1764,6 +1764,16 @@ static void Y_SetNightsBonus(player_t *player, y_bonus_t *bstruct) bstruct->points = player->totalmarescore; } +// +// Y_SetLapBonus +// +static void Y_SetLapBonus(player_t *player, y_bonus_t *bstruct) +{ + strncpy(bstruct->patch, "YB_LAP", sizeof(bstruct->patch)); + bstruct->display = true; + bstruct->points = max(0, (player->totalmarebonuslap) * 100); +} + // // Y_SetLinkBonus // @@ -1825,7 +1835,7 @@ static void Y_SetPerfectBonus(player_t *player, y_bonus_t *bstruct) // This list can be extended in the future with SOC/Lua, perhaps. typedef void (*bonus_f)(player_t *, y_bonus_t *); -bonus_f bonuses_list[7][4] = { +bonus_f bonuses_list[9][4] = { { Y_SetNullBonus, Y_SetNullBonus, @@ -1862,11 +1872,23 @@ bonus_f bonuses_list[7][4] = { Y_SetLinkBonus, Y_SetNullBonus, }, + { + Y_SetNullBonus, + Y_SetNullBonus, + Y_SetLapBonus, + Y_SetNullBonus, + }, + { + Y_SetNullBonus, + Y_SetLinkBonus, + Y_SetLapBonus, + Y_SetNullBonus, + }, { Y_SetNullBonus, Y_SetNightsBonus, Y_SetLinkBonus, - Y_SetNullBonus, + Y_SetLapBonus, }, }; From fcd6b16646f9fa02dc439540790ae90b574fac11 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 12 Aug 2018 20:08:17 -0400 Subject: [PATCH 025/306] Make lap bonus more valuable --- src/y_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/y_inter.c b/src/y_inter.c index f34bc06c0..9c0cc758d 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1771,7 +1771,7 @@ static void Y_SetLapBonus(player_t *player, y_bonus_t *bstruct) { strncpy(bstruct->patch, "YB_LAP", sizeof(bstruct->patch)); bstruct->display = true; - bstruct->points = max(0, (player->totalmarebonuslap) * 100); + bstruct->points = max(0, player->totalmarebonuslap * 1000); } // From 89f57cb111a9fc6043a8db98ecf4ce728f863219 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 12 Aug 2018 20:25:35 -0400 Subject: [PATCH 026/306] Have just one NiGHTS bonus option: NIGHTS and LINK together --- src/dehacked.c | 4 +--- src/y_inter.c | 14 +------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 41d41405c..70a19eadc 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1197,10 +1197,8 @@ static void readlevelheader(MYFILE *f, INT32 num) else if (fastcmp(word2, "BOSS")) i = 1; else if (fastcmp(word2, "ERZ3")) i = 2; else if (fastcmp(word2, "NIGHTS")) i = 3; - else if (fastcmp(word2, "NIGHTSLINK")) i = 4; - else if (fastcmp(word2, "NIGHTSALL")) i = 5; - if (i >= -1 && i <= 5) // -1 for no bonus. Max is 2. + if (i >= -1 && i <= 3) // -1 for no bonus. Max is 3. mapheaderinfo[num-1]->bonustype = (SINT8)i; else deh_warning("Level header %d: invalid bonus type number %d", num, i); diff --git a/src/y_inter.c b/src/y_inter.c index de0335523..2cafed8ca 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1825,7 +1825,7 @@ static void Y_SetPerfectBonus(player_t *player, y_bonus_t *bstruct) // This list can be extended in the future with SOC/Lua, perhaps. typedef void (*bonus_f)(player_t *, y_bonus_t *); -bonus_f bonuses_list[7][4] = { +bonus_f bonuses_list[5][4] = { { Y_SetNullBonus, Y_SetNullBonus, @@ -1850,18 +1850,6 @@ bonus_f bonuses_list[7][4] = { Y_SetRingBonus, Y_SetPerfectBonus, }, - { - Y_SetNullBonus, - Y_SetNullBonus, - Y_SetNightsBonus, - Y_SetNullBonus, - }, - { - Y_SetNullBonus, - Y_SetNullBonus, - Y_SetLinkBonus, - Y_SetNullBonus, - }, { Y_SetNullBonus, Y_SetNightsBonus, From 54343bc05f257e236de6fc92f51f61e7688c5ae6 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 12 Aug 2018 20:36:53 -0400 Subject: [PATCH 027/306] Change special stage bonus to NiGHTS in-level score, per MB --- src/y_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/y_inter.c b/src/y_inter.c index 2cafed8ca..915d6b810 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1930,7 +1930,7 @@ static void Y_AwardSpecialStageBonus(void) if (!playeringame[i] || players[i].lives < 1) // not active or game over Y_SetNullBonus(&players[i], &localbonus); else if (maptol & TOL_NIGHTS) // Link instead of Rings - Y_SetLinkBonus(&players[i], &localbonus); + Y_SetNightsBonus(&players[i], &localbonus); else Y_SetRingBonus(&players[i], &localbonus); players[i].score += localbonus.points; From f1fc205b31248e40179b61b27ac8e634583fd247 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 13 Aug 2018 11:12:53 -0400 Subject: [PATCH 028/306] Deduct marescore when player hits ground * ~~For speedrunning~~: Land on the Drone, keep your points! --- src/p_inter.c | 10 ++++------ src/p_user.c | 17 ++++++++++++----- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index ce8bba6b6..120f17569 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3311,12 +3311,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } else if (player->powers[pw_carry] == CR_NIGHTSFALL) { - if (player->spheres > 0) - { - damage = player->spheres; - P_RingDamage(player, inflictor, source, damage, damagetype, true); - damage = 0; - } + // always damage so we can recoil upon losing points + damage = player->spheres; + P_RingDamage(player, inflictor, source, damage, damagetype, true); + damage = 0; } else if (player->rings > 0) // No shield but have rings. { diff --git a/src/p_user.c b/src/p_user.c index fd09b0847..140c60acd 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -590,10 +590,6 @@ static void P_DeNightserizePlayer(player_t *player) else if (player == &players[secondarydisplayplayer]) localaiming2 = 0; - // If you screwed up, kiss your score and ring bonus goodbye. - player->marescore = 0; - player->rings = 0; - P_SetPlayerMobjState(player->mo, S_PLAY_FALL); // If in a special stage, add some preliminary exit time. @@ -605,6 +601,11 @@ static void P_DeNightserizePlayer(player_t *player) players[i].nightstime = 1; // force everyone else to fall too. player->exiting = 3*TICRATE; stagefailed = true; // NIGHT OVER + + // If you screwed up, kiss your score and ring bonus goodbye. + // But don't do this yet if not in special stage! Wait til we hit the ground. + player->marescore = 0; + player->rings = 0; } // Check to see if the player should be killed. @@ -7030,8 +7031,14 @@ static void P_MovePlayer(player_t *player) if (playeringame[i]) players[i].exiting = (14*TICRATE)/5 + 1; } - else if (player->spheres > 0) + else { + // Damage whether or not we have spheres, as player should recoil upon losing points P_DamageMobj(player->mo, NULL, NULL, 1, 0); + + // Now deduct our mare score! + player->marescore = 0; + player->rings = 0; + } player->powers[pw_carry] = CR_NONE; } } From 004cbe6a3d90b6391d38537bb144da51c0818168 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 13 Aug 2018 22:10:16 -0400 Subject: [PATCH 029/306] Whitespace --- src/p_spec.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index ea09bfe04..06bc55c50 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -105,10 +105,10 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t * static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); static void P_ResetFading(line_t *line, fade_t *data); #define P_RemoveFading(l) P_ResetFading(l, NULL); -static INT32 P_FindFakeFloorsDoAlpha(INT16 destvalue, INT16 speed, +static INT32 P_FindFakeFloorsDoAlpha(INT16 destvalue, INT16 speed, boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, boolean dofadeinonly, INT32 line); -static void P_AddMasterFader(INT16 destvalue, INT16 speed, +static void P_AddMasterFader(INT16 destvalue, INT16 speed, boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, boolean dofadeinonly, INT32 line); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); @@ -3109,8 +3109,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (sectors[s].lines[j]->special >= 100 && sectors[s].lines[j]->special < 300) { if (sides[line->sidenum[0]].rowoffset>>FRACBITS > 0) - P_AddMasterFader(sides[line->sidenum[0]].textureoffset>>FRACBITS, - sides[line->sidenum[0]].rowoffset>>FRACBITS, + P_AddMasterFader(sides[line->sidenum[0]].textureoffset>>FRACBITS, + sides[line->sidenum[0]].rowoffset>>FRACBITS, (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT (line->flags & ML_BOUNCY), // handle FF_SOLID @@ -3120,8 +3120,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) else { P_RemoveFading(&lines[(INT32)(sectors[s].lines[j]-lines)]); - P_FindFakeFloorsDoAlpha(sides[line->sidenum[0]].textureoffset>>FRACBITS, - 0, // set alpha immediately + P_FindFakeFloorsDoAlpha(sides[line->sidenum[0]].textureoffset>>FRACBITS, + 0, // set alpha immediately (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT (line->flags & ML_BOUNCY), // handle FF_SOLID @@ -3132,7 +3132,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } break; } - + case 453: // Stop fading FOF { INT32 s, j; @@ -7145,7 +7145,7 @@ void T_Disappear(disappear_t *d) } /** Removes fadingdata from FOF control sector - * + * * \param line line to search for target faders * \param data pointer to set new fadingdata to. Can be NULL to erase. */ @@ -7161,7 +7161,7 @@ static void P_ResetFading(line_t *line, fade_t *data) { if (rover->master != line) continue; - + if(((fade_t *)rover->master->frontsector->fadingdata) != data) { if(&((fade_t *)rover->master->frontsector->fadingdata)->thinker) @@ -7253,7 +7253,7 @@ static boolean P_DoFakeFloorAlpha(ffloor_t *rover, INT16 destvalue, INT16 speed, if (speed < 1 || rover->alpha + speed >= destvalue - speed) { rover->alpha = destvalue; - + if (doexists) { if (rover->alpha <= 1) @@ -7289,7 +7289,7 @@ static boolean P_DoFakeFloorAlpha(ffloor_t *rover, INT16 destvalue, INT16 speed, else // continue fading in { rover->alpha += speed; - + if (doexists) rover->flags |= FF_EXISTS; @@ -7316,7 +7316,7 @@ static boolean P_DoFakeFloorAlpha(ffloor_t *rover, INT16 destvalue, INT16 speed, return result; } -static INT32 P_FindFakeFloorsDoAlpha(INT16 destvalue, INT16 speed, +static INT32 P_FindFakeFloorsDoAlpha(INT16 destvalue, INT16 speed, boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, boolean dofadeinonly, INT32 line) { @@ -7349,7 +7349,7 @@ static INT32 P_FindFakeFloorsDoAlpha(INT16 destvalue, INT16 speed, * \param dofadeinonly enable flags when fade-in is finished; never on fade-out * \param line line to target FOF */ -static void P_AddMasterFader(INT16 destvalue, INT16 speed, +static void P_AddMasterFader(INT16 destvalue, INT16 speed, boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, boolean dofadeinonly, INT32 line) { @@ -7378,7 +7378,7 @@ static void P_AddMasterFader(INT16 destvalue, INT16 speed, */ void T_Fade(fade_t *d) { - INT32 affectedffloors = P_FindFakeFloorsDoAlpha(d->destvalue, d->speed, + INT32 affectedffloors = P_FindFakeFloorsDoAlpha(d->destvalue, d->speed, d->doexists, d->dotranslucent, d->dosolid, d->dospawnflags, d->dofadeinonly, d->affectee); From 841c31a6ba9fc81a418abf14c0d00536b237d4e2 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 13 Aug 2018 22:17:58 -0400 Subject: [PATCH 030/306] Attach fade_t thinker to proper control sector upon savegame load --- src/p_saveg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 50d636280..a1ce9c4b5 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2577,9 +2577,9 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->dospawnflags = READUINT8(save_p); ht->dofadeinonly = READUINT8(save_p); - sector_t *ffloorsector = LoadSector(ht->affectee); - if (ffloorsector) - ffloorsector->fadingdata = ht; + line_t *ffloorline = LoadLine(ht->affectee); + if (ffloorline && ffloorline->frontsector) + ffloorline->frontsector->fadingdata = ht; P_AddThinker(&ht->thinker); } From d53582596febe96b8413fa498f0b1b80e84853ab Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 14 Aug 2018 10:20:56 -0400 Subject: [PATCH 031/306] Preproc comment out Y_SetLinkBonus because unused --- src/y_inter.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/y_inter.c b/src/y_inter.c index d2fa2e668..3fdf5f7a9 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1774,6 +1774,7 @@ static void Y_SetLapBonus(player_t *player, y_bonus_t *bstruct) bstruct->points = max(0, player->totalmarebonuslap * 1000); } +#if 0 // // Y_SetLinkBonus // @@ -1783,6 +1784,7 @@ static void Y_SetLinkBonus(player_t *player, y_bonus_t *bstruct) bstruct->display = true; bstruct->points = max(0, (player->maxlink - 1) * 100); } +#endif // // Y_SetGuardBonus From 931297e2d72d56f57d9179624f30f37f1606d3a9 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 14 Aug 2018 10:18:08 -0400 Subject: [PATCH 032/306] Rename dofadeinonly to doghostfade * Ghost fading: when transitioning to/from alpha=0, don't set solid/tangibility until fade is finished --- src/p_saveg.c | 4 ++-- src/p_spec.c | 18 +++++++++--------- src/p_spec.h | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index a1ce9c4b5..70c6b411e 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1573,7 +1573,7 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type) WRITEUINT8(save_p, ht->dotranslucent); WRITEUINT8(save_p, ht->dosolid); WRITEUINT8(save_p, ht->dospawnflags); - WRITEUINT8(save_p, ht->dofadeinonly); + WRITEUINT8(save_p, ht->doghostfade); } // @@ -2575,7 +2575,7 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->dotranslucent = READUINT8(save_p); ht->dosolid = READUINT8(save_p); ht->dospawnflags = READUINT8(save_p); - ht->dofadeinonly = READUINT8(save_p); + ht->doghostfade = READUINT8(save_p); line_t *ffloorline = LoadLine(ht->affectee); if (ffloorline && ffloorline->frontsector) diff --git a/src/p_spec.c b/src/p_spec.c index 06bc55c50..0fa16f9f4 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -107,10 +107,10 @@ static void P_ResetFading(line_t *line, fade_t *data); #define P_RemoveFading(l) P_ResetFading(l, NULL); static INT32 P_FindFakeFloorsDoAlpha(INT16 destvalue, INT16 speed, boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, - boolean dofadeinonly, INT32 line); + boolean doghostfade, INT32 line); static void P_AddMasterFader(INT16 destvalue, INT16 speed, boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, - boolean dofadeinonly, INT32 line); + boolean doghostfade, INT32 line); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); @@ -7175,7 +7175,7 @@ static void P_ResetFading(line_t *line, fade_t *data) static boolean P_DoFakeFloorAlpha(ffloor_t *rover, INT16 destvalue, INT16 speed, boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, - boolean dofadeinonly) + boolean doghostfade) { boolean result = false; @@ -7318,7 +7318,7 @@ static boolean P_DoFakeFloorAlpha(ffloor_t *rover, INT16 destvalue, INT16 speed, static INT32 P_FindFakeFloorsDoAlpha(INT16 destvalue, INT16 speed, boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, - boolean dofadeinonly, INT32 line) + boolean doghostfade, INT32 line) { ffloor_t *rover; register INT32 s; @@ -7331,7 +7331,7 @@ static INT32 P_FindFakeFloorsDoAlpha(INT16 destvalue, INT16 speed, if (rover->master != &lines[line]) continue; - affectedffloors += (INT32)P_DoFakeFloorAlpha(rover, destvalue, speed, doexists, dotranslucent, dosolid, dospawnflags, dofadeinonly); + affectedffloors += (INT32)P_DoFakeFloorAlpha(rover, destvalue, speed, doexists, dotranslucent, dosolid, dospawnflags, doghostfade); } } @@ -7346,12 +7346,12 @@ static INT32 P_FindFakeFloorsDoAlpha(INT16 destvalue, INT16 speed, * \param dotranslucent handle FF_TRANSLUCENT * \param dosolid handle FF_SOLID * \param dospawnflags handle spawnflags - * \param dofadeinonly enable flags when fade-in is finished; never on fade-out + * \param doghostfade enable flags when fade-in is finished; never on fade-out * \param line line to target FOF */ static void P_AddMasterFader(INT16 destvalue, INT16 speed, boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, - boolean dofadeinonly, INT32 line) + boolean doghostfade, INT32 line) { fade_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); @@ -7363,7 +7363,7 @@ static void P_AddMasterFader(INT16 destvalue, INT16 speed, d->dotranslucent = dotranslucent; d->dosolid = dosolid; d->dospawnflags = dospawnflags; - d->dofadeinonly = dofadeinonly; + d->doghostfade = doghostfade; // find any existing thinkers and remove them, then replace with new data P_ResetFading(&lines[d->affectee], d); @@ -7380,7 +7380,7 @@ void T_Fade(fade_t *d) { INT32 affectedffloors = P_FindFakeFloorsDoAlpha(d->destvalue, d->speed, d->doexists, d->dotranslucent, d->dosolid, d->dospawnflags, - d->dofadeinonly, d->affectee); + d->doghostfade, d->affectee); // no more ffloors to fade? remove myself if (affectedffloors == 0) diff --git a/src/p_spec.h b/src/p_spec.h index c8607f868..672b96f30 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -460,7 +460,7 @@ typedef struct boolean dotranslucent; ///< Handle FF_TRANSLUCENT handling boolean dosolid; ///< Handle FF_SOLID handling boolean dospawnflags; ///< Enable spawnflags handling - boolean dofadeinonly; ///< Set flags only when fade-in is finished; never during fade-out + boolean doghostfade; ///< Set flags only when fade-in is finished; never during fade-out } fade_t; void T_Fade(fade_t *d); From 52f5dbd52f1bec4eac3783c7b2a074989c4754b9 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 17 Aug 2018 00:32:20 -0400 Subject: [PATCH 033/306] Checkpoint: Move fadingdata to line_t (or ffloor_t?) --- src/p_saveg.c | 4 +- src/p_spec.c | 110 +++++++++++++++++++++++++++++++++++--------------- 2 files changed, 80 insertions(+), 34 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 70c6b411e..eeb05d328 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2578,8 +2578,8 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->doghostfade = READUINT8(save_p); line_t *ffloorline = LoadLine(ht->affectee); - if (ffloorline && ffloorline->frontsector) - ffloorline->frontsector->fadingdata = ht; + if (ffloorline) + ffloorline->fadingdata = ht; P_AddThinker(&ht->thinker); } diff --git a/src/p_spec.c b/src/p_spec.c index 0fa16f9f4..89caf41f3 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3103,43 +3103,89 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 452: // Fade FOF { - INT32 s, j; - for (s = -1; (s = P_FindSectorFromLineTag(line, s)) >= 0 ;) - for (j = 0; (unsigned)j < sectors[s].linecount; j++) - if (sectors[s].lines[j]->special >= 100 && sectors[s].lines[j]->special < 300) - { - if (sides[line->sidenum[0]].rowoffset>>FRACBITS > 0) - P_AddMasterFader(sides[line->sidenum[0]].textureoffset>>FRACBITS, - sides[line->sidenum[0]].rowoffset>>FRACBITS, - (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS - !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT - (line->flags & ML_BOUNCY), // handle FF_SOLID - (line->flags & ML_EFFECT1), // handle spawnflags - (line->flags & ML_EFFECT2), // enable flags on fade-in finish only - (INT32)(sectors[s].lines[j]-lines)); - else - { - P_RemoveFading(&lines[(INT32)(sectors[s].lines[j]-lines)]); - P_FindFakeFloorsDoAlpha(sides[line->sidenum[0]].textureoffset>>FRACBITS, - 0, // set alpha immediately - (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS - !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT - (line->flags & ML_BOUNCY), // handle FF_SOLID - (line->flags & ML_EFFECT1), // handle spawnflags - (line->flags & ML_EFFECT2), // enable flags on fade-in finish only - (INT32)(sectors[s].lines[j]-lines)); - } - } + INT16 destvalue = (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS); + INT16 speed = (INT16)(sides[line->sidenum[1]].rowoffset>>FRACBITS); + INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + sector_t *sec; // Sector that the FOF is visible in + ffloor_t *rover; // FOF that we are going to crumble + + for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) + { + sec = sectors + secnum; + + if (!sec->ffloors) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Target sector #%d has no FOFs.\n", secnum); + return; + } + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (rover->master->frontsector->tag == foftag) + break; + } + + if (!rover) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Can't find a FOF control sector with tag %d\n", foftag); + return; + } + + if (speed > 0) + P_AddMasterFader(destvalue, speed, + (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS + !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT + (line->flags & ML_BOUNCY), // handle FF_SOLID + (line->flags & ML_EFFECT1), // handle spawnflags + (line->flags & ML_EFFECT2), // enable flags on fade-in finish only + (INT32)(rover->master-lines)); + else + { + P_RemoveFading(&lines[(INT32)(sectors[s].lines[j]-lines)]); + P_FindFakeFloorsDoAlpha(destvalue, 0, // set alpha immediately + (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS + !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT + (line->flags & ML_BOUNCY), // handle FF_SOLID + (line->flags & ML_EFFECT1), // handle spawnflags + (line->flags & ML_EFFECT2), // enable flags on fade-in finish only + (INT32)(sectors[s].lines[j]-lines)); + } + } break; } case 453: // Stop fading FOF { - INT32 s, j; - for (s = -1; (s = P_FindSectorFromLineTag(line, s)) >= 0 ;) - for (j = 0; (unsigned)j < sectors[s].linecount; j++) - if (sectors[s].lines[j]->special >= 100 && sectors[s].lines[j]->special < 300) - P_RemoveFading(&lines[(INT32)(sectors[s].lines[j]-lines)]); + INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + sector_t *sec; // Sector that the FOF is visible in + ffloor_t *rover; // FOF that we are going to crumble + + for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) + { + sec = sectors + secnum; + + if (!sec->ffloors) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Target sector #%d has no FOFs.\n", secnum); + return; + } + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (rover->master->frontsector->tag == foftag) + break; + } + + if (!rover) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Can't find a FOF control sector with tag %d\n", foftag); + return; + } + + P_RemoveFading(&lines[(INT32)(sectors[s].lines[j]-lines)]); + } break; } From 2e252cb905c9e6db5c5537752e86f23fff26a5b8 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 17 Aug 2018 00:32:20 -0400 Subject: [PATCH 034/306] Move fadingdata (fade_t thinker) to line_t --- src/p_saveg.c | 12 +++-- src/p_setup.c | 3 +- src/p_spec.c | 132 ++++++++++++++++++++++++++++++++------------------ src/r_defs.h | 3 +- 4 files changed, 97 insertions(+), 53 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 70c6b411e..f30c52bda 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2578,8 +2578,8 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->doghostfade = READUINT8(save_p); line_t *ffloorline = LoadLine(ht->affectee); - if (ffloorline && ffloorline->frontsector) - ffloorline->frontsector->fadingdata = ht; + if (ffloorline) + ffloorline->fadingdata = ht; P_AddThinker(&ht->thinker); } @@ -2770,7 +2770,13 @@ static void P_NetUnArchiveThinkers(void) // clear sector thinker pointers so they don't point to non-existant thinkers for all of eternity for (i = 0; i < numsectors; i++) { - sectors[i].floordata = sectors[i].ceilingdata = sectors[i].lightingdata = sectors[i].fadingdata = NULL; + sectors[i].floordata = sectors[i].ceilingdata = sectors[i].lightingdata = NULL; + } + + // same for line thinker pointers + for (i = 0; i < numlines; i++) + { + lines[i].fadingdata = NULL; } // read in saved thinkers diff --git a/src/p_setup.c b/src/p_setup.c index 67dbb8db7..5259394ee 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -693,7 +693,6 @@ static void P_LoadRawSectors(UINT8 *data, size_t i) ss->floordata = NULL; ss->ceilingdata = NULL; ss->lightingdata = NULL; - ss->fadingdata = NULL; ss->linecount = 0; ss->lines = NULL; @@ -1311,6 +1310,8 @@ static void P_LoadRawLineDefs(UINT8 *data, size_t i) #ifdef POLYOBJECTS ld->polyobj = NULL; #endif + + ld->fadingdata = NULL; } } diff --git a/src/p_spec.c b/src/p_spec.c index 0fa16f9f4..6f392bbfe 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3103,43 +3103,91 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 452: // Fade FOF { - INT32 s, j; - for (s = -1; (s = P_FindSectorFromLineTag(line, s)) >= 0 ;) - for (j = 0; (unsigned)j < sectors[s].linecount; j++) - if (sectors[s].lines[j]->special >= 100 && sectors[s].lines[j]->special < 300) - { - if (sides[line->sidenum[0]].rowoffset>>FRACBITS > 0) - P_AddMasterFader(sides[line->sidenum[0]].textureoffset>>FRACBITS, - sides[line->sidenum[0]].rowoffset>>FRACBITS, - (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS - !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT - (line->flags & ML_BOUNCY), // handle FF_SOLID - (line->flags & ML_EFFECT1), // handle spawnflags - (line->flags & ML_EFFECT2), // enable flags on fade-in finish only - (INT32)(sectors[s].lines[j]-lines)); - else - { - P_RemoveFading(&lines[(INT32)(sectors[s].lines[j]-lines)]); - P_FindFakeFloorsDoAlpha(sides[line->sidenum[0]].textureoffset>>FRACBITS, - 0, // set alpha immediately - (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS - !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT - (line->flags & ML_BOUNCY), // handle FF_SOLID - (line->flags & ML_EFFECT1), // handle spawnflags - (line->flags & ML_EFFECT2), // enable flags on fade-in finish only - (INT32)(sectors[s].lines[j]-lines)); - } - } + INT16 destvalue = (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS); + INT16 speed = (INT16)(sides[line->sidenum[1]].rowoffset>>FRACBITS); + INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + sector_t *sec; // Sector that the FOF is visible in + ffloor_t *rover; // FOF that we are going to crumble + + for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) + { + sec = sectors + secnum; + + if (!sec->ffloors) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Target sector #%d has no FOFs.\n", secnum); + return; + } + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (rover->master->frontsector->tag == foftag) + break; + } + + if (!rover) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Can't find a FOF control sector with tag %d\n", foftag); + return; + } + + if (speed > 0) + P_AddMasterFader(destvalue, speed, + (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS + !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT + (line->flags & ML_BOUNCY), // handle FF_SOLID + (line->flags & ML_EFFECT1), // handle spawnflags + (line->flags & ML_EFFECT2), // enable flags on fade-in finish only + (INT32)(rover->master-lines)); + else + { + P_RemoveFading(&lines[(INT32)(rover->master-lines)]); + P_FindFakeFloorsDoAlpha(destvalue, 0, // set alpha immediately + (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS + !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT + (line->flags & ML_BOUNCY), // handle FF_SOLID + (line->flags & ML_EFFECT1), // handle spawnflags + (line->flags & ML_EFFECT2), // enable flags on fade-in finish only + (INT32)(rover->master-lines)); + } + break; + } break; } case 453: // Stop fading FOF { - INT32 s, j; - for (s = -1; (s = P_FindSectorFromLineTag(line, s)) >= 0 ;) - for (j = 0; (unsigned)j < sectors[s].linecount; j++) - if (sectors[s].lines[j]->special >= 100 && sectors[s].lines[j]->special < 300) - P_RemoveFading(&lines[(INT32)(sectors[s].lines[j]-lines)]); + INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + sector_t *sec; // Sector that the FOF is visible in + ffloor_t *rover; // FOF that we are going to crumble + + for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) + { + sec = sectors + secnum; + + if (!sec->ffloors) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Target sector #%d has no FOFs.\n", secnum); + return; + } + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (rover->master->frontsector->tag == foftag) + break; + } + + if (!rover) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Can't find a FOF control sector with tag %d\n", foftag); + return; + } + + P_RemoveFading(&lines[(INT32)(rover->master-lines)]); + break; + } break; } @@ -7151,25 +7199,13 @@ void T_Disappear(disappear_t *d) */ static void P_ResetFading(line_t *line, fade_t *data) { - ffloor_t *rover; - register INT32 s; - // find any existing thinkers and remove them, then replace with new data - for (s = -1; (s = P_FindSectorFromLineTag(line, s)) >= 0 ;) + if(((fade_t *)line->fadingdata) != data) { - for (rover = sectors[s].ffloors; rover; rover = rover->next) - { - if (rover->master != line) - continue; + if(&((fade_t *)line->fadingdata)->thinker) + P_RemoveThinker(&((fade_t *)line->fadingdata)->thinker); - if(((fade_t *)rover->master->frontsector->fadingdata) != data) - { - if(&((fade_t *)rover->master->frontsector->fadingdata)->thinker) - P_RemoveThinker(&((fade_t *)rover->master->frontsector->fadingdata)->thinker); - - rover->master->frontsector->fadingdata = data; - } - } + line->fadingdata = data; } } diff --git a/src/r_defs.h b/src/r_defs.h index b4c7d2112..c425f3a3b 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -308,7 +308,6 @@ typedef struct sector_s void *floordata; // floor move thinker void *ceilingdata; // ceiling move thinker void *lightingdata; // lighting change thinker - void *fadingdata; // fading FOF thinker // floor and ceiling texture offsets fixed_t floor_xoffs, floor_yoffs; @@ -444,6 +443,8 @@ typedef struct line_s char *text; // a concatination of all front and back texture names, for linedef specials that require a string. INT16 callcount; // no. of calls left before triggering, for the "X calls" linedef specials, defaults to 0 + + void *fadingdata; // fading FOF thinker } line_t; // From 677f19ede6680bffc5e97253b48e70d55fd403f4 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 17 Aug 2018 02:28:52 -0400 Subject: [PATCH 035/306] Move fading thinker to ffloor_t.fadingdata --- src/p_saveg.c | 31 ++++++++++------ src/p_setup.c | 2 - src/p_spec.c | 101 +++++++++++++++++++------------------------------- src/p_spec.h | 6 ++- src/r_defs.h | 4 +- 5 files changed, 65 insertions(+), 79 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index f30c52bda..daa6bb937 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1566,7 +1566,8 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type) { const fade_t *ht = (const void *)th; WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->affectee); + WRITEINT32(save_p, ht->sectornum); + WRITEINT32(save_p, ht->ffloornum); WRITEINT16(save_p, ht->destvalue); WRITEINT16(save_p, ht->speed); WRITEUINT8(save_p, ht->doexists); @@ -2568,7 +2569,8 @@ static inline void LoadFadeThinker(actionf_p1 thinker) { fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->affectee = READINT32(save_p); + ht->sectornum = READINT32(save_p); + ht->ffloornum = READINT32(save_p); ht->destvalue = READINT16(save_p); ht->speed = READINT16(save_p); ht->doexists = READUINT8(save_p); @@ -2577,9 +2579,22 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->dospawnflags = READUINT8(save_p); ht->doghostfade = READUINT8(save_p); - line_t *ffloorline = LoadLine(ht->affectee); - if (ffloorline) - ffloorline->fadingdata = ht; + sector_t *ss = LoadSector(ht->sectornum); + if (ss) + { + size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc + ffloor_t *rover; + for (rover = ss->ffloors; rover; rover = rover->next) + { + if (j == ht->ffloornum) + { + ht->rover = rover; + rover->fadingdata = ht; + break; + } + j++; + } + } P_AddThinker(&ht->thinker); } @@ -2773,12 +2788,6 @@ static void P_NetUnArchiveThinkers(void) sectors[i].floordata = sectors[i].ceilingdata = sectors[i].lightingdata = NULL; } - // same for line thinker pointers - for (i = 0; i < numlines; i++) - { - lines[i].fadingdata = NULL; - } - // read in saved thinkers for (;;) { diff --git a/src/p_setup.c b/src/p_setup.c index 5259394ee..c62f281b3 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1310,8 +1310,6 @@ static void P_LoadRawLineDefs(UINT8 *data, size_t i) #ifdef POLYOBJECTS ld->polyobj = NULL; #endif - - ld->fadingdata = NULL; } } diff --git a/src/p_spec.c b/src/p_spec.c index 6f392bbfe..20f034ac8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -103,14 +103,15 @@ static void P_SpawnFriction(void); static void P_SpawnPushers(void); static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000 static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); -static void P_ResetFading(line_t *line, fade_t *data); +static void P_ResetFading(ffloor_t *rover, fade_t *data); #define P_RemoveFading(l) P_ResetFading(l, NULL); -static INT32 P_FindFakeFloorsDoAlpha(INT16 destvalue, INT16 speed, +static boolean P_DoFakeFloorAlpha(ffloor_t *rover, INT16 destvalue, INT16 speed, boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, - boolean doghostfade, INT32 line); -static void P_AddMasterFader(INT16 destvalue, INT16 speed, + boolean doghostfade); +static void P_AddMasterFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, + INT16 destvalue, INT16 speed, boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, - boolean doghostfade, INT32 line); + boolean doghostfade); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); @@ -3109,6 +3110,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in ffloor_t *rover; // FOF that we are going to crumble + size_t j = 0; // sec->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) { @@ -3124,6 +3126,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { if (rover->master->frontsector->tag == foftag) break; + j++; } if (!rover) @@ -3133,25 +3136,24 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } if (speed > 0) - P_AddMasterFader(destvalue, speed, - (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS - !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT - (line->flags & ML_BOUNCY), // handle FF_SOLID - (line->flags & ML_EFFECT1), // handle spawnflags - (line->flags & ML_EFFECT2), // enable flags on fade-in finish only - (INT32)(rover->master-lines)); + P_AddMasterFader(rover, secnum, j, + destvalue, speed, + (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS + !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT + (line->flags & ML_BOUNCY), // handle FF_SOLID + (line->flags & ML_EFFECT1), // handle spawnflags + (line->flags & ML_EFFECT2)); // enable flags on fade-in finish only else { - P_RemoveFading(&lines[(INT32)(rover->master-lines)]); - P_FindFakeFloorsDoAlpha(destvalue, 0, // set alpha immediately - (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS - !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT - (line->flags & ML_BOUNCY), // handle FF_SOLID - (line->flags & ML_EFFECT1), // handle spawnflags - (line->flags & ML_EFFECT2), // enable flags on fade-in finish only - (INT32)(rover->master-lines)); + P_RemoveFading(rover); + P_DoFakeFloorAlpha(rover, + destvalue, 0, // set alpha immediately + (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS + !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT + (line->flags & ML_BOUNCY), // handle FF_SOLID + (line->flags & ML_EFFECT1), // handle spawnflags + (line->flags & ML_EFFECT2)); // enable flags on fade-in finish only } - break; } break; } @@ -3185,8 +3187,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) return; } - P_RemoveFading(&lines[(INT32)(rover->master-lines)]); - break; + P_RemoveFading(rover); } break; } @@ -5036,7 +5037,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f ffloor->spawnflags = ffloor->flags = flags; ffloor->master = master; ffloor->norender = INFTICS; - + ffloor->fadingdata = NULL; // Scan the thinkers to check for special conditions applying to this FOF. // If we have thinkers sorted by sector, just check the relevant ones; @@ -7197,15 +7198,15 @@ void T_Disappear(disappear_t *d) * \param line line to search for target faders * \param data pointer to set new fadingdata to. Can be NULL to erase. */ -static void P_ResetFading(line_t *line, fade_t *data) +static void P_ResetFading(ffloor_t *rover, fade_t *data) { // find any existing thinkers and remove them, then replace with new data - if(((fade_t *)line->fadingdata) != data) + if(((fade_t *)rover->fadingdata) != data) { - if(&((fade_t *)line->fadingdata)->thinker) - P_RemoveThinker(&((fade_t *)line->fadingdata)->thinker); + if(&((fade_t *)rover->fadingdata)->thinker) + P_RemoveThinker(&((fade_t *)rover->fadingdata)->thinker); - line->fadingdata = data; + rover->fadingdata = data; } } @@ -7352,28 +7353,6 @@ static boolean P_DoFakeFloorAlpha(ffloor_t *rover, INT16 destvalue, INT16 speed, return result; } -static INT32 P_FindFakeFloorsDoAlpha(INT16 destvalue, INT16 speed, - boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, - boolean doghostfade, INT32 line) -{ - ffloor_t *rover; - register INT32 s; - INT32 affectedffloors = 0; - - for (s = -1; (s = P_FindSectorFromLineTag(&lines[line], s)) >= 0 ;) - { - for (rover = sectors[s].ffloors; rover; rover = rover->next) - { - if (rover->master != &lines[line]) - continue; - - affectedffloors += (INT32)P_DoFakeFloorAlpha(rover, destvalue, speed, doexists, dotranslucent, dosolid, dospawnflags, doghostfade); - } - } - - return affectedffloors; -} - /** Adds master fader thinker. * * \param destvalue transparency value to fade to @@ -7385,14 +7364,17 @@ static INT32 P_FindFakeFloorsDoAlpha(INT16 destvalue, INT16 speed, * \param doghostfade enable flags when fade-in is finished; never on fade-out * \param line line to target FOF */ -static void P_AddMasterFader(INT16 destvalue, INT16 speed, +static void P_AddMasterFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, + INT16 destvalue, INT16 speed, boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, - boolean doghostfade, INT32 line) + boolean doghostfade) { fade_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); d->thinker.function.acp1 = (actionf_p1)T_Fade; - d->affectee = line; + d->rover = rover; + d->sectornum = (INT32)sectornum; + d->ffloornum = (INT32)ffloornum; d->destvalue = max(1, min(256, destvalue)); // ffloor->alpha is 1-256 d->speed = max(1, speed); // minimum speed 1/tic // if speed < 1, alpha is set immediately in thinker d->doexists = doexists; @@ -7402,7 +7384,7 @@ static void P_AddMasterFader(INT16 destvalue, INT16 speed, d->doghostfade = doghostfade; // find any existing thinkers and remove them, then replace with new data - P_ResetFading(&lines[d->affectee], d); + P_ResetFading(rover, d); P_AddThinker(&d->thinker); } @@ -7414,13 +7396,8 @@ static void P_AddMasterFader(INT16 destvalue, INT16 speed, */ void T_Fade(fade_t *d) { - INT32 affectedffloors = P_FindFakeFloorsDoAlpha(d->destvalue, d->speed, - d->doexists, d->dotranslucent, d->dosolid, d->dospawnflags, - d->doghostfade, d->affectee); - - // no more ffloors to fade? remove myself - if (affectedffloors == 0) - P_RemoveFading(&lines[d->affectee]); + if (d->rover && !P_DoFakeFloorAlpha(d->rover, d->destvalue, d->speed, d->doexists, d->dotranslucent, d->dosolid, d->dospawnflags, d->doghostfade)) + P_RemoveFading(d->rover); } /* diff --git a/src/p_spec.h b/src/p_spec.h index 672b96f30..fcced9cea 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -453,14 +453,16 @@ void T_Disappear(disappear_t *d); typedef struct { thinker_t thinker; ///< Thinker structure for effect. - INT32 affectee; ///< Number of affected line + ffloor_t *rover; ///< Target ffloor + INT32 sectornum; ///< Number of ffloor target sector + INT32 ffloornum; ///< Number of ffloor of target sector INT16 destvalue; ///< Transparency value to fade to INT16 speed; ///< Speed to fade by boolean doexists; ///< Handle FF_EXISTS handling boolean dotranslucent; ///< Handle FF_TRANSLUCENT handling boolean dosolid; ///< Handle FF_SOLID handling boolean dospawnflags; ///< Enable spawnflags handling - boolean doghostfade; ///< Set flags only when fade-in is finished; never during fade-out + boolean doghostfade; ///< Set flags only when fade-in is finished; never during fade-out } fade_t; void T_Fade(fade_t *d); diff --git a/src/r_defs.h b/src/r_defs.h index c425f3a3b..ea5db3947 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -177,6 +177,8 @@ typedef struct ffloor_s // these are saved for netgames, so do not let Lua touch these! ffloortype_e spawnflags; // flags the 3D floor spawned with INT32 spawnalpha; // alpha the 3D floor spawned with + + void *fadingdata; // fading FOF thinker } ffloor_t; @@ -443,8 +445,6 @@ typedef struct line_s char *text; // a concatination of all front and back texture names, for linedef specials that require a string. INT16 callcount; // no. of calls left before triggering, for the "X calls" linedef specials, defaults to 0 - - void *fadingdata; // fading FOF thinker } line_t; // From 020b18b84ba668e0ee371205d019c1695ec204f1 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 17 Aug 2018 14:49:33 -0400 Subject: [PATCH 036/306] Revised and re-organized P_DoFakeFloorAlpha fading procedure * dosolid routine now refers to spawnflags --- src/p_spec.c | 203 +++++++++++++++++++++++++-------------------------- 1 file changed, 98 insertions(+), 105 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 20f034ac8..9fe25bcba 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7214,74 +7214,34 @@ static boolean P_DoFakeFloorAlpha(ffloor_t *rover, INT16 destvalue, INT16 speed, boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, boolean doghostfade) { - boolean result = false; + boolean stillfading = false; + // routines specific to fade in and fade out if (rover->alpha == destvalue) - return result; - // fade out - else if (rover->alpha > destvalue) + return stillfading; + else if (rover->alpha > destvalue) // fade out { // finish fading out if (speed < 1 || rover->alpha - speed <= destvalue + speed) { rover->alpha = destvalue; - if (doexists) + if (dosolid) { - if (rover->alpha <= 1) - rover->flags &= ~FF_EXISTS; - else - rover->flags |= FF_EXISTS; - } - - if (dosolid - && !(rover->flags & FF_SWIMMABLE) - && !(rover->flags & FF_QUICKSAND)) - rover->flags &= ~FF_SOLID; // make intangible at end of fade-out - - if (dotranslucent) - { - if (rover->alpha >= 256) - { - rover->flags |= FF_CUTLEVEL; - rover->flags &= ~(FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA); - } - else - { - rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; - rover->flags &= ~FF_CUTLEVEL; - } - - if (rover->flags & FF_SOLID) - rover->flags &= ~FF_CUTSPRITES; - else - rover->flags |= FF_CUTSPRITES; + if (rover->spawnflags & FF_SOLID) + rover->flags &= ~FF_SOLID; + if (rover->spawnflags & FF_SWIMMABLE) + rover->flags &= ~FF_SWIMMABLE; + if (rover->spawnflags & FF_QUICKSAND) + rover->flags &= ~FF_QUICKSAND; + if (rover->spawnflags & FF_BUSTUP) + rover->flags &= ~FF_BUSTUP; } } else // continue fading out { rover->alpha -= speed; - - if (doexists) - rover->flags |= FF_EXISTS; - - if (dosolid - && !(rover->flags & FF_SWIMMABLE) - && !(rover->flags & FF_QUICKSAND)) - rover->flags |= FF_SOLID; // keep solid during fade - - if (dotranslucent) - { - rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; - rover->flags &= ~FF_CUTLEVEL; - - if (rover->flags & FF_SOLID) - rover->flags &= ~FF_CUTSPRITES; - else - rover->flags |= FF_CUTSPRITES; - } - - result = true; + stillfading = true; } } else // fade in @@ -7291,66 +7251,99 @@ static boolean P_DoFakeFloorAlpha(ffloor_t *rover, INT16 destvalue, INT16 speed, { rover->alpha = destvalue; - if (doexists) + if (dosolid) { - if (rover->alpha <= 1) - rover->flags &= ~FF_EXISTS; - else - rover->flags |= FF_EXISTS; - } - - if (dosolid - && !(rover->flags & FF_SWIMMABLE) - && !(rover->flags & FF_QUICKSAND)) - rover->flags |= FF_SOLID; // make solid at end of fade-in - - if (dotranslucent) - { - if (rover->alpha >= 256) - { - rover->flags |= FF_CUTLEVEL; - rover->flags &= ~(FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA); - } - else - { - rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; - rover->flags &= ~FF_CUTLEVEL; - } - - if (rover->flags & FF_SOLID) - rover->flags &= ~FF_CUTSPRITES; - else - rover->flags |= FF_CUTSPRITES; + if (rover->spawnflags & FF_SOLID) + rover->flags |= FF_SOLID; + if (rover->spawnflags & FF_SWIMMABLE) + rover->flags |= FF_SWIMMABLE; + if (rover->spawnflags & FF_QUICKSAND) + rover->flags |= FF_QUICKSAND; + if (rover->spawnflags & FF_BUSTUP) + rover->flags |= FF_BUSTUP; } } else // continue fading in { rover->alpha += speed; - - if (doexists) - rover->flags |= FF_EXISTS; - - if (dosolid - && !(rover->flags & FF_SWIMMABLE) - && !(rover->flags & FF_QUICKSAND)) - rover->flags |= FF_SOLID; // keep solid during fade - - if (dotranslucent) - { - rover->flags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; - rover->flags &= ~FF_CUTLEVEL; - - if (rover->flags & FF_SOLID) - rover->flags &= ~FF_CUTSPRITES; - else - rover->flags |= FF_CUTSPRITES; - } - - result = true; + stillfading = true; } } - return result; + // routines common to both fade in and fade out + if (!stillfading) + { + if (doexists) + { + if (rover->alpha <= 1) + rover->flags &= ~FF_EXISTS; + else + rover->flags |= FF_EXISTS; + } + + if (dotranslucent) + { + if (rover->alpha >= 256) + { + //rover->flags |= FF_CUTLEVEL; + rover->flags &= ~FF_TRANSLUCENT; + } + else + { + rover->flags |= FF_TRANSLUCENT; + //rover->flags &= ~FF_CUTLEVEL; + } + + // if (rover->flags & FF_SOLID) + // rover->flags &= ~FF_CUTSPRITES; + // else + // rover->flags |= FF_CUTSPRITES; + } + } + else + { + if (doexists) + rover->flags |= FF_EXISTS; + + if (dotranslucent) + { + rover->flags |= FF_TRANSLUCENT; + //rover->flags &= ~FF_CUTLEVEL; + + // if (rover->flags & FF_SOLID) + // rover->flags &= ~FF_CUTSPRITES; + // else + // rover->flags |= FF_CUTSPRITES; + } + + if (dosolid) + { + if (doghostfade) // remove interaction flags during fade + { + if (rover->spawnflags & FF_SOLID) + rover->flags &= ~FF_SOLID; + if (rover->spawnflags & FF_SWIMMABLE) + rover->flags &= ~FF_SWIMMABLE; + if (rover->spawnflags & FF_QUICKSAND) + rover->flags &= ~FF_QUICKSAND; + if (rover->spawnflags & FF_BUSTUP) + rover->flags &= ~FF_BUSTUP; + } + else // keep interaction during fade + { + if (rover->spawnflags & FF_SOLID) + rover->flags |= FF_SOLID; + if (rover->spawnflags & FF_SWIMMABLE) + rover->flags |= FF_SWIMMABLE; + if (rover->spawnflags & FF_QUICKSAND) + rover->flags |= FF_QUICKSAND; + if (rover->spawnflags & FF_BUSTUP) + rover->flags |= FF_BUSTUP; + } + } + } + + return stillfading; } /** Adds master fader thinker. From 45ae6efbadfc01d54d70081909573680472416a1 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 17 Aug 2018 15:13:05 -0400 Subject: [PATCH 037/306] Refactor function and variable names; change defaults for fake floor fader line flags --- src/p_saveg.c | 8 ++--- src/p_spec.c | 87 ++++++++++++++++++++++++--------------------------- src/p_spec.h | 10 +++--- 3 files changed, 50 insertions(+), 55 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index daa6bb937..c2158aa0d 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1572,9 +1572,9 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type) WRITEINT16(save_p, ht->speed); WRITEUINT8(save_p, ht->doexists); WRITEUINT8(save_p, ht->dotranslucent); - WRITEUINT8(save_p, ht->dosolid); - WRITEUINT8(save_p, ht->dospawnflags); + WRITEUINT8(save_p, ht->docollision); WRITEUINT8(save_p, ht->doghostfade); + WRITEUINT8(save_p, ht->exactalpha); } // @@ -2575,9 +2575,9 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->speed = READINT16(save_p); ht->doexists = READUINT8(save_p); ht->dotranslucent = READUINT8(save_p); - ht->dosolid = READUINT8(save_p); - ht->dospawnflags = READUINT8(save_p); + ht->docollision = READUINT8(save_p); ht->doghostfade = READUINT8(save_p); + ht->exactalpha = READUINT8(save_p); sector_t *ss = LoadSector(ht->sectornum); if (ss) diff --git a/src/p_spec.c b/src/p_spec.c index 9fe25bcba..4694eb015 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -103,15 +103,13 @@ static void P_SpawnFriction(void); static void P_SpawnPushers(void); static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000 static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); -static void P_ResetFading(ffloor_t *rover, fade_t *data); -#define P_RemoveFading(l) P_ResetFading(l, NULL); -static boolean P_DoFakeFloorAlpha(ffloor_t *rover, INT16 destvalue, INT16 speed, - boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, - boolean doghostfade); -static void P_AddMasterFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, +static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data); +#define P_RemoveFakeFloorFader(l) P_ResetFakeFloorFader(l, NULL); +static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, + boolean doexists, boolean dotranslucent, boolean docollision, boolean doghostfade, boolean exactalpha); +static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, INT16 destvalue, INT16 speed, - boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, - boolean doghostfade); + boolean doexists, boolean dotranslucent, boolean docollision, boolean doghostfade, boolean exactalpha); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); @@ -3136,23 +3134,23 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } if (speed > 0) - P_AddMasterFader(rover, secnum, j, + P_AddFakeFloorFader(rover, secnum, j, destvalue, speed, - (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS + !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT - (line->flags & ML_BOUNCY), // handle FF_SOLID - (line->flags & ML_EFFECT1), // handle spawnflags - (line->flags & ML_EFFECT2)); // enable flags on fade-in finish only + !(line->flags & ML_BOUNCY), // do not handle interactive flags + (line->flags & ML_EFFECT1), // do ghost fade (no interactive flags during fade) + (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) else { - P_RemoveFading(rover); - P_DoFakeFloorAlpha(rover, - destvalue, 0, // set alpha immediately - (line->flags & ML_BLOCKMONSTERS), // handle FF_EXISTS + P_RemoveFakeFloorFader(rover); + P_FadeFakeFloor(rover, + destvalue, 0, // set alpha immediately + !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT - (line->flags & ML_BOUNCY), // handle FF_SOLID - (line->flags & ML_EFFECT1), // handle spawnflags - (line->flags & ML_EFFECT2)); // enable flags on fade-in finish only + !(line->flags & ML_BOUNCY), // do not handle interactive flags + (line->flags & ML_EFFECT1), // do ghost fade (no interactive flags during fade) + (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) } } break; @@ -3187,7 +3185,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) return; } - P_RemoveFading(rover); + P_RemoveFakeFloorFader(rover); } break; } @@ -7198,7 +7196,7 @@ void T_Disappear(disappear_t *d) * \param line line to search for target faders * \param data pointer to set new fadingdata to. Can be NULL to erase. */ -static void P_ResetFading(ffloor_t *rover, fade_t *data) +static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data) { // find any existing thinkers and remove them, then replace with new data if(((fade_t *)rover->fadingdata) != data) @@ -7210,9 +7208,8 @@ static void P_ResetFading(ffloor_t *rover, fade_t *data) } } -static boolean P_DoFakeFloorAlpha(ffloor_t *rover, INT16 destvalue, INT16 speed, - boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, - boolean doghostfade) +static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, + boolean doexists, boolean dotranslucent, boolean docollision, boolean doghostfade, boolean exactalpha) { boolean stillfading = false; @@ -7226,7 +7223,7 @@ static boolean P_DoFakeFloorAlpha(ffloor_t *rover, INT16 destvalue, INT16 speed, { rover->alpha = destvalue; - if (dosolid) + if (docollision) { if (rover->spawnflags & FF_SOLID) rover->flags &= ~FF_SOLID; @@ -7251,7 +7248,7 @@ static boolean P_DoFakeFloorAlpha(ffloor_t *rover, INT16 destvalue, INT16 speed, { rover->alpha = destvalue; - if (dosolid) + if (docollision) { if (rover->spawnflags & FF_SOLID) rover->flags |= FF_SOLID; @@ -7316,7 +7313,7 @@ static boolean P_DoFakeFloorAlpha(ffloor_t *rover, INT16 destvalue, INT16 speed, // rover->flags |= FF_CUTSPRITES; } - if (dosolid) + if (docollision) { if (doghostfade) // remove interaction flags during fade { @@ -7346,21 +7343,19 @@ static boolean P_DoFakeFloorAlpha(ffloor_t *rover, INT16 destvalue, INT16 speed, return stillfading; } -/** Adds master fader thinker. +/** Adds fake floor fader thinker. * - * \param destvalue transparency value to fade to - * \param speed speed to fade by - * \param doexists handle FF_EXISTS - * \param dotranslucent handle FF_TRANSLUCENT - * \param dosolid handle FF_SOLID - * \param dospawnflags handle spawnflags - * \param doghostfade enable flags when fade-in is finished; never on fade-out - * \param line line to target FOF + * \param destvalue transparency value to fade to + * \param speed speed to fade by + * \param doexists handle FF_EXISTS + * \param dotranslucent handle FF_TRANSLUCENT + * \param docollision handle interactive flags + * \param doghostfade no interactive flags during fading + * \param exactalpha use exact alpha values (opengl) */ -static void P_AddMasterFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, +static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, INT16 destvalue, INT16 speed, - boolean doexists, boolean dotranslucent, boolean dosolid, boolean dospawnflags, - boolean doghostfade) + boolean doexists, boolean dotranslucent, boolean docollision, boolean doghostfade, boolean exactalpha) { fade_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); @@ -7372,12 +7367,12 @@ static void P_AddMasterFader(ffloor_t *rover, size_t sectornum, size_t ffloornum d->speed = max(1, speed); // minimum speed 1/tic // if speed < 1, alpha is set immediately in thinker d->doexists = doexists; d->dotranslucent = dotranslucent; - d->dosolid = dosolid; - d->dospawnflags = dospawnflags; + d->docollision = docollision; d->doghostfade = doghostfade; + d->exactalpha = exactalpha; // find any existing thinkers and remove them, then replace with new data - P_ResetFading(rover, d); + P_ResetFakeFloorFader(rover, d); P_AddThinker(&d->thinker); } @@ -7385,12 +7380,12 @@ static void P_AddMasterFader(ffloor_t *rover, size_t sectornum, size_t ffloornum /** Makes a FOF fade * * \param d Fade thinker. - * \sa P_AddMasterFader + * \sa P_AddFakeFloorFader */ void T_Fade(fade_t *d) { - if (d->rover && !P_DoFakeFloorAlpha(d->rover, d->destvalue, d->speed, d->doexists, d->dotranslucent, d->dosolid, d->dospawnflags, d->doghostfade)) - P_RemoveFading(d->rover); + if (d->rover && !P_FadeFakeFloor(d->rover, d->destvalue, d->speed, d->doexists, d->dotranslucent, d->docollision, d->doghostfade, d->exactalpha)) + P_RemoveFakeFloorFader(d->rover); } /* diff --git a/src/p_spec.h b/src/p_spec.h index fcced9cea..b4e9594d2 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -458,11 +458,11 @@ typedef struct INT32 ffloornum; ///< Number of ffloor of target sector INT16 destvalue; ///< Transparency value to fade to INT16 speed; ///< Speed to fade by - boolean doexists; ///< Handle FF_EXISTS handling - boolean dotranslucent; ///< Handle FF_TRANSLUCENT handling - boolean dosolid; ///< Handle FF_SOLID handling - boolean dospawnflags; ///< Enable spawnflags handling - boolean doghostfade; ///< Set flags only when fade-in is finished; never during fade-out + boolean doexists; ///< Handle FF_EXISTS + boolean dotranslucent; ///< Handle FF_TRANSLUCENT + boolean docollision; ///< Handle interactive flags + boolean doghostfade; ///< No interactive flags during fading + boolean exactalpha; ///< Use exact alpha values (opengl) } fade_t; void T_Fade(fade_t *d); From bf5efe645778f71a496a8f884f23b3514cc1ba74 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 17 Aug 2018 15:59:34 -0400 Subject: [PATCH 038/306] Cleanup fade fake floor code --- src/p_spec.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 4694eb015..ec07003bd 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7282,19 +7282,14 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, { if (rover->alpha >= 256) { - //rover->flags |= FF_CUTLEVEL; + //rover->flags |= (FF_CUTLEVEL | FF_CUTEXTRA); rover->flags &= ~FF_TRANSLUCENT; } else { rover->flags |= FF_TRANSLUCENT; - //rover->flags &= ~FF_CUTLEVEL; + //rover->flags &= ~(FF_CUTLEVEL | FF_CUTEXTRA); } - - // if (rover->flags & FF_SOLID) - // rover->flags &= ~FF_CUTSPRITES; - // else - // rover->flags |= FF_CUTSPRITES; } } else @@ -7305,17 +7300,12 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, if (dotranslucent) { rover->flags |= FF_TRANSLUCENT; - //rover->flags &= ~FF_CUTLEVEL; - - // if (rover->flags & FF_SOLID) - // rover->flags &= ~FF_CUTSPRITES; - // else - // rover->flags |= FF_CUTSPRITES; + //rover->flags &= ~(FF_CUTLEVEL | FF_CUTEXTRA); } if (docollision) { - if (doghostfade) // remove interaction flags during fade + if (doghostfade) // remove collision flags during fade { if (rover->spawnflags & FF_SOLID) rover->flags &= ~FF_SOLID; @@ -7326,7 +7316,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, if (rover->spawnflags & FF_BUSTUP) rover->flags &= ~FF_BUSTUP; } - else // keep interaction during fade + else // keep collision during fade { if (rover->spawnflags & FF_SOLID) rover->flags |= FF_SOLID; From d94608fa101f56a2b1e5a22d34b8ff7184154282 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 17 Aug 2018 16:27:32 -0400 Subject: [PATCH 039/306] Add alpha clamping so OpenGL conforms to Software's translucent levels --- src/p_saveg.c | 2 ++ src/p_spec.c | 59 ++++++++++++++++++++++++++++++++++++++++++--------- src/p_spec.h | 1 + 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index c2158aa0d..c1af4167b 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1568,6 +1568,7 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type) WRITEUINT8(save_p, type); WRITEINT32(save_p, ht->sectornum); WRITEINT32(save_p, ht->ffloornum); + WRITEINT32(save_p, ht->alpha); WRITEINT16(save_p, ht->destvalue); WRITEINT16(save_p, ht->speed); WRITEUINT8(save_p, ht->doexists); @@ -2571,6 +2572,7 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->thinker.function.acp1 = thinker; ht->sectornum = READINT32(save_p); ht->ffloornum = READINT32(save_p); + ht->alpha = READINT32(save_p); ht->destvalue = READINT16(save_p); ht->speed = READINT16(save_p); ht->doexists = READUINT8(save_p); diff --git a/src/p_spec.c b/src/p_spec.c index ec07003bd..50cf049ff 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7212,16 +7212,23 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, boolean doexists, boolean dotranslucent, boolean docollision, boolean doghostfade, boolean exactalpha) { boolean stillfading = false; + INT32 alpha; + fade_t *fadingdata = (fade_t *)rover->fadingdata; + + if (fadingdata) + alpha = fadingdata->alpha; + else + alpha = rover->alpha; // routines specific to fade in and fade out - if (rover->alpha == destvalue) + if (alpha == destvalue) return stillfading; - else if (rover->alpha > destvalue) // fade out + else if (alpha > destvalue) // fade out { // finish fading out - if (speed < 1 || rover->alpha - speed <= destvalue + speed) + if (speed < 1 || alpha - speed <= destvalue + speed) { - rover->alpha = destvalue; + alpha = destvalue; if (docollision) { @@ -7237,16 +7244,16 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, } else // continue fading out { - rover->alpha -= speed; + alpha -= speed; stillfading = true; } } else // fade in { // finish fading in - if (speed < 1 || rover->alpha + speed >= destvalue - speed) + if (speed < 1 || alpha + speed >= destvalue - speed) { - rover->alpha = destvalue; + alpha = destvalue; if (docollision) { @@ -7262,7 +7269,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, } else // continue fading in { - rover->alpha += speed; + alpha += speed; stillfading = true; } } @@ -7272,7 +7279,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, { if (doexists) { - if (rover->alpha <= 1) + if (alpha <= 1) rover->flags &= ~FF_EXISTS; else rover->flags |= FF_EXISTS; @@ -7280,7 +7287,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, if (dotranslucent) { - if (rover->alpha >= 256) + if (alpha >= 256) { //rover->flags |= (FF_CUTLEVEL | FF_CUTEXTRA); rover->flags &= ~FF_TRANSLUCENT; @@ -7330,6 +7337,37 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, } } + if (!stillfading || exactalpha) + rover->alpha = alpha; + else // clamp fadingdata->alpha to software's alpha levels + { + if (alpha < 12) + rover->alpha = destvalue < 12 ? destvalue : 1; // Don't even draw it + else if (alpha < 38) + rover->alpha = destvalue >= 12 && destvalue < 38 ? destvalue : 25; + else if (alpha < 64) + rover->alpha = destvalue >=38 && destvalue < 64 ? destvalue : 51; + else if (alpha < 89) + rover->alpha = destvalue >= 64 && destvalue < 89 ? destvalue : 76; + else if (alpha < 115) + rover->alpha = destvalue >= 89 && destvalue < 115 ? destvalue : 102; + else if (alpha < 140) + rover->alpha = destvalue >= 115 && destvalue < 140 ? destvalue : 128; + else if (alpha < 166) + rover->alpha = destvalue >= 140 && destvalue < 166 ? destvalue : 154; + else if (alpha < 192) + rover->alpha = destvalue >= 166 && destvalue < 192 ? destvalue : 179; + else if (alpha < 217) + rover->alpha = destvalue >= 192 && destvalue < 217 ? destvalue : 204; + else if (alpha < 243) + rover->alpha = destvalue >= 217 && destvalue < 243 ? destvalue : 230; + else // Opaque + rover->alpha = destvalue >= 243 ? destvalue : 256; + } + + if (fadingdata) + fadingdata->alpha = alpha; + return stillfading; } @@ -7353,6 +7391,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor d->rover = rover; d->sectornum = (INT32)sectornum; d->ffloornum = (INT32)ffloornum; + d->alpha = rover->alpha; d->destvalue = max(1, min(256, destvalue)); // ffloor->alpha is 1-256 d->speed = max(1, speed); // minimum speed 1/tic // if speed < 1, alpha is set immediately in thinker d->doexists = doexists; diff --git a/src/p_spec.h b/src/p_spec.h index b4e9594d2..dc2ab0e6a 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -456,6 +456,7 @@ typedef struct ffloor_t *rover; ///< Target ffloor INT32 sectornum; ///< Number of ffloor target sector INT32 ffloornum; ///< Number of ffloor of target sector + INT32 alpha; ///< Internal alpha counter INT16 destvalue; ///< Transparency value to fade to INT16 speed; ///< Speed to fade by boolean doexists; ///< Handle FF_EXISTS From 773d8bdb8d076d689fa4a3c662a849270ec3475a Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 05:31:41 -0400 Subject: [PATCH 040/306] P_ResetFakeFloorFader: Unclamp rover->alpha from software levels --- src/p_spec.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 50cf049ff..8ad69d872 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7199,10 +7199,13 @@ void T_Disappear(disappear_t *d) static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data) { // find any existing thinkers and remove them, then replace with new data - if(((fade_t *)rover->fadingdata) != data) + if (((fade_t *)rover->fadingdata) != data) { - if(&((fade_t *)rover->fadingdata)->thinker) + if (&((fade_t *)rover->fadingdata)->thinker) + { + rover->alpha = ((fade_t *)rover->fadingdata)->alpha; // unclamp from software levels P_RemoveThinker(&((fade_t *)rover->fadingdata)->thinker); + } rover->fadingdata = data; } From 4b07246565f4a9eca7efd304eccfb6daec430252 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 18 Aug 2018 05:55:49 -0400 Subject: [PATCH 041/306] Add "finalize" flag to Type 453 Stop Fade --- src/p_spec.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 8ad69d872..687ebdbba 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -103,8 +103,8 @@ static void P_SpawnFriction(void); static void P_SpawnPushers(void); static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000 static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); -static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data); -#define P_RemoveFakeFloorFader(l) P_ResetFakeFloorFader(l, NULL); +static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize); +#define P_RemoveFakeFloorFader(l) P_ResetFakeFloorFader(l, NULL, false); static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, boolean doexists, boolean dotranslucent, boolean docollision, boolean doghostfade, boolean exactalpha); static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, @@ -3107,7 +3107,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover; // FOF that we are going to crumble + ffloor_t *rover; // FOF that we are going to operate size_t j = 0; // sec->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) @@ -3161,7 +3161,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover; // FOF that we are going to crumble + ffloor_t *rover; // FOF that we are going to operate for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) { @@ -3185,7 +3185,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) return; } - P_RemoveFakeFloorFader(rover); + P_ResetFakeFloorFader(rover, NULL, + !(line->flags & ML_BLOCKMONSTERS)); // do not finalize collision flags } break; } @@ -7196,15 +7197,28 @@ void T_Disappear(disappear_t *d) * \param line line to search for target faders * \param data pointer to set new fadingdata to. Can be NULL to erase. */ -static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data) +static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize) { + fade_t *fadingdata = (fade_t *)rover->fadingdata; // find any existing thinkers and remove them, then replace with new data - if (((fade_t *)rover->fadingdata) != data) + if (fadingdata != data) { - if (&((fade_t *)rover->fadingdata)->thinker) + if (&fadingdata->thinker) { - rover->alpha = ((fade_t *)rover->fadingdata)->alpha; // unclamp from software levels - P_RemoveThinker(&((fade_t *)rover->fadingdata)->thinker); + if (finalize) + P_FadeFakeFloor(rover, + fadingdata->alpha >= fadingdata->destvalue ? + fadingdata->alpha - 1 : // trigger fade-out finish + fadingdata->alpha + 1, // trigger fade-in finish + 0, + fadingdata->doexists, + fadingdata->dotranslucent, + fadingdata->docollision, + fadingdata->doghostfade, + fadingdata->exactalpha); + rover->alpha = fadingdata->alpha; + + P_RemoveThinker(&fadingdata->thinker); } rover->fadingdata = data; @@ -7404,7 +7418,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor d->exactalpha = exactalpha; // find any existing thinkers and remove them, then replace with new data - P_ResetFakeFloorFader(rover, d); + P_ResetFakeFloorFader(rover, d, false); P_AddThinker(&d->thinker); } From 24aafa6dacaa03a73674ef049ceeae102693438f Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 3 Sep 2018 15:43:36 +0100 Subject: [PATCH 042/306] UDP_Socket: Add missing limit checks for s, for client and broadcast addresses --- src/i_tcp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index 6488e9845..5c6606668 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -1044,7 +1044,7 @@ static boolean UDP_Socket(void) if (gaie == 0) { runp = ai; - while (runp != NULL) + while (runp != NULL && s < MAXNETNODES+1) { memcpy(&clientaddress[s], runp->ai_addr, runp->ai_addrlen); s++; @@ -1064,7 +1064,7 @@ static boolean UDP_Socket(void) if (gaie == 0) { runp = ai; - while (runp != NULL) + while (runp != NULL && s < MAXNETNODES+1) { memcpy(&broadcastaddress[s], runp->ai_addr, runp->ai_addrlen); s++; @@ -1087,7 +1087,7 @@ static boolean UDP_Socket(void) if (gaie == 0) { runp = ai; - while (runp != NULL) + while (runp != NULL && s < MAXNETNODES+1) { memcpy(&broadcastaddress[s], runp->ai_addr, runp->ai_addrlen); s++; From 846bddfdcf9514e8164bd1157c58ab2ac614ae8a Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 3 Sep 2018 15:52:22 +0100 Subject: [PATCH 043/306] SOCK_Send: Fix what appears to be a mistaken use of i instead of j --- src/i_tcp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index 5c6606668..3b609914d 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -707,10 +707,10 @@ static void SOCK_Send(void) { if (myfamily[i] == broadcastaddress[j].any.sa_family) { - if (broadcastaddress[i].any.sa_family == AF_INET) + if (broadcastaddress[j].any.sa_family == AF_INET) d = d4; #ifdef HAVE_IPV6 - else if (broadcastaddress[i].any.sa_family == AF_INET6) + else if (broadcastaddress[j].any.sa_family == AF_INET6) d = d6; #endif else From 7b083f07cd306ca8790427b0257ca1f06f7d3a3e Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 3 Sep 2018 15:56:02 +0100 Subject: [PATCH 044/306] UDP_Socket: I doubt client addresses are meant to be included in the total for broadcast addresses --- src/i_tcp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/i_tcp.c b/src/i_tcp.c index 3b609914d..d11be4285 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -1059,6 +1059,9 @@ static boolean UDP_Socket(void) clientaddress[s].ip4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); //GetLocalAddress(); // my own ip s++; } + + s = 0; + // setup broadcast adress to BROADCASTADDR entry gaie = I_getaddrinfo("255.255.255.255", "0", &hints, &ai); if (gaie == 0) From ea06e8a62b42d4e85112742ca668a7a6495beaf9 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 3 Sep 2018 20:53:40 +0100 Subject: [PATCH 045/306] SOCK_Send: Split the actual sending data parts into a new function, SOCK_SendToAddr, to make everything look a bit neater in general --- src/i_tcp.c | 59 ++++++++++++++++++----------------------------------- 1 file changed, 20 insertions(+), 39 deletions(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index d11be4285..16e7bf2f6 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -686,14 +686,29 @@ static boolean SOCK_CanGet(void) #endif #ifndef NONET -static void SOCK_Send(void) +static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr) { - ssize_t c = ERRSOCKET; socklen_t d4 = (socklen_t)sizeof(struct sockaddr_in); #ifdef HAVE_IPV6 socklen_t d6 = (socklen_t)sizeof(struct sockaddr_in6); #endif socklen_t d, da = (socklen_t)sizeof(mysockaddr_t); + + switch (sockaddr->any.sa_family) + { + case AF_INET: d = d4; break; +#ifdef HAVE_IPV6 + case AF_INET6: d = d6; break; +#endif + default: d = da; break; + } + + return sendto(socket, (char *)&doomcom->data, doomcom->datalength, 0, &sockaddr->any, d); +} + +static void SOCK_Send(void) +{ + ssize_t c = ERRSOCKET; size_t i, j; if (!nodeconnected[doomcom->remotenode]) @@ -706,19 +721,7 @@ static void SOCK_Send(void) for (j = 0; j < broadcastaddresses; j++) { if (myfamily[i] == broadcastaddress[j].any.sa_family) - { - if (broadcastaddress[j].any.sa_family == AF_INET) - d = d4; -#ifdef HAVE_IPV6 - else if (broadcastaddress[j].any.sa_family == AF_INET6) - d = d6; -#endif - else - d = da; - - c = sendto(mysockets[i], (char *)&doomcom->data, doomcom->datalength, 0, - &broadcastaddress[j].any, d); - } + SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]); } } return; @@ -728,35 +731,13 @@ static void SOCK_Send(void) for (i = 0; i < mysocketses; i++) { if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family) - { - if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET) - d = d4; -#ifdef HAVE_IPV6 - else if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET6) - d = d6; -#endif - else - d = da; - - sendto(mysockets[i], (char *)&doomcom->data, doomcom->datalength, 0, - &clientaddress[doomcom->remotenode].any, d); - } + SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]); } return; } else { - if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET) - d = d4; -#ifdef HAVE_IPV6 - else if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET6) - d = d6; -#endif - else - d = da; - - c = sendto(nodesocket[doomcom->remotenode], (char *)&doomcom->data, doomcom->datalength, 0, - &clientaddress[doomcom->remotenode].any, d); + c = SOCK_SendToAddr(nodesocket[doomcom->remotenode], &clientaddress[doomcom->remotenode]); } if (c == ERRSOCKET && errno != ECONNREFUSED && errno != EWOULDBLOCK) From 49b27fc1243e1d663032c80f9f0adfd726d8fbd5 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 7 Sep 2018 08:19:22 -0400 Subject: [PATCH 046/306] Deduct marescore immediately on instakill * Deduct player->spheres too, missed that one --- src/p_user.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index e1480a47d..806fc5da0 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -609,9 +609,9 @@ static void P_DeNightserizePlayer(player_t *player) stagefailed = true; // NIGHT OVER // If you screwed up, kiss your score and ring bonus goodbye. - // But don't do this yet if not in special stage! Wait til we hit the ground. - player->marescore = 0; - player->rings = 0; + // But only do this in special stage (and instakill!) In regular stages, wait til we hit the ground. + player->marescore = player->spheres =\ + player->rings = 0; } // Check to see if the player should be killed. @@ -625,7 +625,11 @@ static void P_DeNightserizePlayer(player_t *player) continue; if (mo2->flags2 & MF2_AMBUSH) + { + player->marescore = player->spheres =\ + player->rings = 0; P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL); + } break; } @@ -7083,8 +7087,8 @@ static void P_MovePlayer(player_t *player) P_DamageMobj(player->mo, NULL, NULL, 1, 0); // Now deduct our mare score! - player->marescore = 0; - player->rings = 0; + player->marescore = player->spheres =\ + player->rings = 0; } player->powers[pw_carry] = CR_NONE; } From 0b365d0d08df2922d92512267f85462b08e97475 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 7 Sep 2018 15:27:18 -0400 Subject: [PATCH 047/306] Initial polyobj fade skeleton --- src/p_polyobj.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ src/p_polyobj.h | 17 +++++++++++++ src/p_saveg.c | 24 ++++++++++++++++++ src/p_spec.c | 32 ++++++++++++++++++++++++ 4 files changed, 138 insertions(+) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index fd3237c9d..d943a0bfe 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -2853,6 +2853,71 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata) return 1; } +void T_PolyObjFade(polyfade_t *th) +{ + polyobj_t *po = Polyobj_GetForNum(th->polyObjNum); + size_t i; + + if (!po) +#ifdef RANGECHECK + I_Error("T_PolyObjFade: thinker has invalid id %d\n", th->polyObjNum); +#else + { + CONS_Debug(DBG_POLYOBJ, "T_PolyObjFade: thinker with invalid id %d removed.\n", th->polyObjNum); + P_RemoveThinkerDelayed(&th->thinker); + return; + } +#endif + + // check for displacement due to override and reattach when possible + if (po->thinker == NULL) + po->thinker = &th->thinker; + + // \todo logic +} + +INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata) +{ + polyobj_t *po; + polyobj_t *oldpo; + polyfade_t *th; + INT32 start; + + if (!(po = Polyobj_GetForNum(prdata->polyObjNum))) + { + CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjRotate: bad polyobj %d\n", prdata->polyObjNum); + return 0; + } + + // don't allow line actions to affect bad polyobjects + if (po->isBad) + return 0; + + // create a new thinker + th = Z_Malloc(sizeof(polyfade_t), PU_LEVSPEC, NULL); + th->thinker.function.acp1 = (actionf_p1)T_PolyObjFade; + PolyObj_AddThinker(&th->thinker); + po->thinker = &th->thinker; + + // set fields + th->polyObjNum = pfdata->tag; + + // \todo polyfade fields + + oldpo = po; + + // apply action to mirroring polyobjects as well + start = 0; + while ((po = Polyobj_GetChild(oldpo, &start))) + { + pfdata->tag = po->id; + EV_DoPolyObjFade(pfdata); + } + + // action was successful + return 1; +} + #endif // ifdef POLYOBJECTS // EOF diff --git a/src/p_polyobj.h b/src/p_polyobj.h index c9838a922..0bd94a636 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -207,6 +207,15 @@ typedef struct polydisplace_s fixed_t oldHeights; } polydisplace_t; +typedef struct polyfade_s +{ + thinker_t thinker; // must be first + + INT32 polyObjNum; + + // \todo polyfade fields +} polyfade_t; + // // Line Activation Data Structures // @@ -266,6 +275,12 @@ typedef struct polydisplacedata_s fixed_t dy; } polydisplacedata_t; +typedef struct polyfadedata_s +{ + INT32 polyObjNum; + // \todo polyfadedata fields +} polyfadedata_t; + // // Functions // @@ -287,6 +302,7 @@ void T_PolyDoorSlide(polyslidedoor_t *); void T_PolyDoorSwing(polyswingdoor_t *); void T_PolyObjDisplace (polydisplace_t *); void T_PolyObjFlag (polymove_t *); +void T_PolyObjFade (polyfade_t *); INT32 EV_DoPolyDoor(polydoordata_t *); INT32 EV_DoPolyObjMove(polymovedata_t *); @@ -294,6 +310,7 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *); INT32 EV_DoPolyObjRotate(polyrotdata_t *); INT32 EV_DoPolyObjDisplace(polydisplacedata_t *); INT32 EV_DoPolyObjFlag(struct line_s *); +INT32 EV_DoPolyObjFade(polyfadedata_t *); // diff --git a/src/p_saveg.c b/src/p_saveg.c index 22d43f358..3cc061ebb 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1019,6 +1019,7 @@ typedef enum tc_polyswingdoor, tc_polyflag, tc_polydisplace, + tc_polyfade, #endif tc_end } specials_e; @@ -1918,6 +1919,11 @@ static void P_NetArchiveThinkers(void) SavePolydisplaceThinker(th, tc_polydisplace); continue; } + else if (th->function.acp1 == (actionf_p1)T_PolyObjFade) + { + SavePolyfadeThinker(th, tc_polyfade); + continue; + } #endif #ifdef PARANOIA else if (th->function.acv != P_RemoveThinkerDelayed) // wait garbage collection @@ -2689,6 +2695,20 @@ static inline void LoadPolydisplaceThinker(actionf_p1 thinker) ht->oldHeights = READFIXED(save_p); P_AddThinker(&ht->thinker); } + +// +// LoadPolyfadeThinker +// +// Loads a polyfadet_t thinker +// +static void LoadPolyfadeThinker(actionf_p1 thinker) +{ + polyfade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->polyObjNum = READINT32(save_p); + // \todo polyfade thinker fields + P_AddThinker(&ht->thinker); +} #endif /* @@ -2886,6 +2906,10 @@ static void P_NetUnArchiveThinkers(void) case tc_polydisplace: LoadPolydisplaceThinker((actionf_p1)T_PolyObjDisplace); break; + + case tc_polyfade: + LoadPolyfadeThinker((actionf_p1)T_PolyObjFade); + break; #endif case tc_scroll: LoadScrollThinker((actionf_p1)T_Scroll); diff --git a/src/p_spec.c b/src/p_spec.c index 6c359c9cc..fd2c312fb 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1245,6 +1245,35 @@ static void PolyTranslucency(line_t *line) po->translucency = (line->frontsector->floorheight >> FRACBITS) / 100; } +// +// PolyFade +// +// Makes a polyobject translucency fade and applies tangibility +// +static void PolyFade(line_t *line) +{ + INT32 polyObjNum = line->tag; + polyobj_t *po; + + if (!(po = Polyobj_GetForNum(polyObjNum))) + { + CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: bad polyobj %d\n", polyObjNum); + return; + } + + // don't allow line actions to affect bad polyobjects + if (po->isBad) + return; + + polyfadedata_t pfd; + + pfd.polyObjNum = line->tag; + + // \todo polyfadedata fields + + return EV_DoPolyObjFade(&pfd); +} + // // PolyWaypoint // @@ -3337,6 +3366,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 491: PolyTranslucency(line); break; + case 492: + PolyFade(line); + break; #endif default: From f52f72256bd7abbd36876f42a213ca2e02121634 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 7 Sep 2018 18:14:52 -0400 Subject: [PATCH 048/306] Thwomp fix: Don't trigger (look for players) when ~FF_EXISTS --- src/p_floor.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/src/p_floor.c b/src/p_floor.c index 0e28b831f..bb6bf8d16 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1839,6 +1839,7 @@ void T_ThwompSector(levelspecthink_t *thwomp) #define ceilingwasheight vars[5] fixed_t thwompx, thwompy; sector_t *actionsector; + ffloor_t *rover = NULL; INT32 secnum; // If you just crashed down, wait a second before coming back up. @@ -1853,7 +1854,16 @@ void T_ThwompSector(levelspecthink_t *thwomp) secnum = P_FindSectorFromTag((INT16)thwomp->vars[0], -1); if (secnum > 0) + { actionsector = §ors[secnum]; + + // Look for thwomp FFloor + for (rover = actionsector->ffloors; rover; rover = rover->next) + { + if (rover->master == thwomp->sourceline) + break; + } + } else return; // Bad bad bad! @@ -1942,10 +1952,13 @@ void T_ThwompSector(levelspecthink_t *thwomp) { mobj_t *mp = (void *)&actionsector->soundorg; - if (thwomp->sourceline->flags & ML_EFFECT4) - S_StartSound(mp, sides[thwomp->sourceline->sidenum[0]].textureoffset>>FRACBITS); - else - S_StartSound(mp, sfx_thwomp); + if (!rover || (rover->flags & FF_EXISTS)) + { + if (thwomp->sourceline->flags & ML_EFFECT4) + S_StartSound(mp, sides[thwomp->sourceline->sidenum[0]].textureoffset>>FRACBITS); + else + S_StartSound(mp, sfx_thwomp); + } thwomp->direction = 1; // start heading back up thwomp->distance = TICRATE; // but only after a small delay @@ -1959,18 +1972,21 @@ void T_ThwompSector(levelspecthink_t *thwomp) thinker_t *th; mobj_t *mo; - // scan the thinkers to find players! - for (th = thinkercap.next; th != &thinkercap; th = th->next) + if (!rover || (rover->flags & FF_EXISTS)) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo = (mobj_t *)th; - if (mo->type == MT_PLAYER && mo->health && mo->z <= thwomp->sector->ceilingheight - && P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT) + // scan the thinkers to find players! + for (th = thinkercap.next; th != &thinkercap; th = th->next) { - thwomp->direction = -1; - break; + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo = (mobj_t *)th; + if (mo->type == MT_PLAYER && mo->health && mo->z <= thwomp->sector->ceilingheight + && P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT) + { + thwomp->direction = -1; + break; + } } } From 76d7a54b2b5e1c4a125f3bfbfb5b4336cf50688c Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 8 Sep 2018 00:34:56 -0400 Subject: [PATCH 049/306] Fix player Z snap to floor on moving platform ~FF_EXISTS * Track player's old floorz by mo->floor_sectornum and floor_ffloornum * Track tmfloorz by tmfloorrover, tmfloor_sectornum, tmfloor_rovernum * Ceiling variants of the above --- src/p_map.c | 100 +++++++++++++++++++++++++++++++++++++++++++++----- src/p_mobj.h | 4 ++ src/p_saveg.c | 13 +++++++ 3 files changed, 108 insertions(+), 9 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index f951621e2..8d0a7aeb1 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -52,6 +52,8 @@ fixed_t tmfloorz, tmceilingz; static fixed_t tmdropoffz, tmdrpoffceilz; // drop-off floor/ceiling heights mobj_t *tmfloorthing; // the thing corresponding to tmfloorz or NULL if tmfloorz is from a sector mobj_t *tmhitthing; // the solid thing you bumped into (for collisions) +ffloor_t *tmfloorrover, *tmceilingrover; +size_t tmfloor_sectornum, tmfloor_rovernum, tmceiling_sectornum, tmceiling_rovernum; #ifdef ESLOPE pslope_t *tmfloorslope, *tmceilingslope; #endif @@ -1417,6 +1419,8 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->z + thing->height > tmfloorz) { tmfloorz = thing->z + thing->height; + tmfloorrover = NULL; + tmfloor_sectornum = tmfloor_rovernum = 0; #ifdef ESLOPE tmfloorslope = NULL; #endif @@ -1437,6 +1441,8 @@ static boolean PIT_CheckThing(mobj_t *thing) return false; tmfloorz = tmceilingz = topz; // block while in air + tmceilingrover = NULL; + tmceiling_sectornum = tmceiling_rovernum = 0; #ifdef ESLOPE tmceilingslope = NULL; #endif @@ -1445,6 +1451,8 @@ static boolean PIT_CheckThing(mobj_t *thing) else if (topz < tmceilingz && tmthing->z <= thing->z+thing->height) { tmceilingz = topz; + tmceilingrover = NULL; + tmceiling_sectornum = tmceiling_rovernum = 0; #ifdef ESLOPE tmceilingslope = NULL; #endif @@ -1461,6 +1469,8 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->z < tmceilingz) { tmceilingz = thing->z; + tmceilingrover = NULL; + tmceiling_sectornum = tmceiling_rovernum = 0; #ifdef ESLOPE tmceilingslope = NULL; #endif @@ -1481,6 +1491,8 @@ static boolean PIT_CheckThing(mobj_t *thing) return false; tmfloorz = tmceilingz = topz; // block while in air + tmfloorrover = NULL; + tmfloor_sectornum = tmfloor_rovernum = 0; #ifdef ESLOPE tmfloorslope = NULL; #endif @@ -1489,6 +1501,8 @@ static boolean PIT_CheckThing(mobj_t *thing) else if (topz > tmfloorz && tmthing->z+tmthing->height >= thing->z) { tmfloorz = topz; + tmfloorrover = NULL; + tmfloor_sectornum = tmfloor_rovernum = 0; #ifdef ESLOPE tmfloorslope = NULL; #endif @@ -1640,6 +1654,8 @@ static boolean PIT_CheckLine(line_t *ld) { tmceilingz = opentop; ceilingline = ld; + tmceilingrover = NULL; + tmceiling_sectornum = tmceiling_rovernum = 0; #ifdef ESLOPE tmceilingslope = opentopslope; #endif @@ -1648,6 +1664,8 @@ static boolean PIT_CheckLine(line_t *ld) if (openbottom > tmfloorz) { tmfloorz = openbottom; + tmfloorrover = NULL; + tmfloor_sectornum = tmfloor_rovernum = 0; #ifdef ESLOPE tmfloorslope = openbottomslope; #endif @@ -1729,6 +1747,10 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) // will adjust them. tmfloorz = tmdropoffz = P_GetFloorZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->floorheight; tmceilingz = P_GetCeilingZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->ceilingheight; + tmfloorrover = NULL; + tmfloor_sectornum = tmfloor_rovernum = 0; + tmceilingrover = NULL; + tmceiling_sectornum = tmceiling_rovernum = 0; #ifdef ESLOPE tmfloorslope = newsubsec->sector->f_slope; tmceilingslope = newsubsec->sector->c_slope; @@ -1738,6 +1760,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) if (newsubsec->sector->ffloors) { ffloor_t *rover; + size_t rovernum = 0; fixed_t delta1, delta2; INT32 thingtop = thing->z + thing->height; @@ -1746,7 +1769,10 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) fixed_t topheight, bottomheight; if (!(rover->flags & FF_EXISTS)) + { + rovernum++; continue; + } topheight = P_GetFOFTopZ(thing, newsubsec->sector, rover, x, y, NULL); bottomheight = P_GetFOFBottomZ(thing, newsubsec->sector, rover, x, y, NULL); @@ -1772,6 +1798,9 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) { if (tmfloorz < topheight - sinklevel) { tmfloorz = topheight - sinklevel; + tmfloorrover = rover; + tmfloor_sectornum = newsubsec->sector - sectors; + tmfloor_rovernum = rovernum; #ifdef ESLOPE tmfloorslope = *rover->t_slope; #endif @@ -1781,12 +1810,16 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) { if (tmceilingz > bottomheight + sinklevel) { tmceilingz = bottomheight + sinklevel; + tmceilingrover = rover; + tmceiling_sectornum = newsubsec->sector - sectors; + tmceiling_rovernum = rovernum; #ifdef ESLOPE tmceilingslope = *rover->b_slope; #endif } } } + rovernum++; continue; } @@ -1797,7 +1830,10 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) else if (!((rover->flags & FF_BLOCKPLAYER && thing->player) || (rover->flags & FF_BLOCKOTHERS && !thing->player) || rover->flags & FF_QUICKSAND)) + { + rovernum++; continue; + } if (rover->flags & FF_QUICKSAND) { @@ -1805,12 +1841,16 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) { if (tmfloorz < thing->z) { tmfloorz = thing->z; + tmfloorrover = rover; + tmfloor_sectornum = newsubsec->sector - sectors; + tmfloor_rovernum = rovernum; #ifdef ESLOPE tmfloorslope = NULL; #endif } } // Quicksand blocks never change heights otherwise. + rovernum++; continue; } @@ -1823,6 +1863,9 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) && !(rover->flags & FF_REVERSEPLATFORM)) { tmfloorz = tmdropoffz = topheight; + tmfloorrover = rover; + tmfloor_sectornum = newsubsec->sector - sectors; + tmfloor_rovernum = rovernum; #ifdef ESLOPE tmfloorslope = *rover->t_slope; #endif @@ -1832,10 +1875,14 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) && !(thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE))) { tmceilingz = tmdrpoffceilz = bottomheight; + tmceilingrover = rover; + tmceiling_sectornum = newsubsec->sector - sectors; + tmceiling_rovernum = rovernum; #ifdef ESLOPE tmceilingslope = *rover->b_slope; #endif } + rovernum++; } } @@ -2328,6 +2375,12 @@ boolean PIT_PushableMoved(mobj_t *thing) mobj_t *oldthing = tmthing; line_t *oldceilline = ceilingline; line_t *oldblockline = blockingline; + ffloor_t *oldflrrover = tmfloorrover; + ffloor_t *oldceilrover = tmceilingrover; + size_t oldflrrover_sectornum = tmfloor_sectornum; + size_t oldflrrover_ffloornum = tmfloor_rovernum; + size_t oldceilrover_sectornum = tmceiling_sectornum; + size_t oldceilrover_ffloornum = tmceiling_rovernum; #ifdef ESLOPE pslope_t *oldfslope = tmfloorslope; pslope_t *oldcslope = tmceilingslope; @@ -2344,6 +2397,12 @@ boolean PIT_PushableMoved(mobj_t *thing) P_SetTarget(&tmthing, oldthing); ceilingline = oldceilline; blockingline = oldblockline; + tmfloorrover = oldflrrover; + tmceilingrover = oldceilrover; + tmfloor_sectornum = oldflrrover_sectornum; + tmfloor_rovernum = oldflrrover_ffloornum; + tmceiling_sectornum = oldceilrover_sectornum; + tmceiling_rovernum = oldceilrover_ffloornum; #ifdef ESLOPE tmfloorslope = oldfslope; tmceilingslope = oldcslope; @@ -2663,7 +2722,9 @@ static boolean P_ThingHeightClip(mobj_t *thing) { boolean floormoved; fixed_t oldfloorz = thing->floorz; + size_t oldfloor_sectornum = thing->floor_sectornum, oldfloor_rovernum = thing->floor_rovernum; boolean onfloor = P_IsObjectOnGround(thing);//(thing->z <= thing->floorz); + ffloor_t *rover = NULL; if (thing->flags & MF_NOCLIPHEIGHT) return true; @@ -2678,6 +2739,10 @@ static boolean P_ThingHeightClip(mobj_t *thing) thing->floorz = tmfloorz; thing->ceilingz = tmceilingz; + thing->floor_sectornum = tmfloor_sectornum; + thing->floor_rovernum = tmfloor_rovernum; + thing->ceiling_sectornum = tmceiling_sectornum; + thing->ceiling_rovernum = tmceiling_rovernum; // Ugly hack?!?! As long as just ceilingz is the lowest, // you'll still get crushed, right? @@ -2686,16 +2751,33 @@ static boolean P_ThingHeightClip(mobj_t *thing) if (onfloor && !(thing->flags & MF_NOGRAVITY) && floormoved) { - if (thing->eflags & MFE_VERTICALFLIP) - thing->pmomz = thing->ceilingz - (thing->z + thing->height); - else - thing->pmomz = thing->floorz - thing->z; - thing->eflags |= MFE_APPLYPMOMZ; + // Find FOF referenced by floorz + if (oldfloor_sectornum) + { + size_t rovernum = 0; + for (rover = sectors[oldfloor_sectornum].ffloors; rover; rover = rover->next) + { + if (rovernum == oldfloor_rovernum) + break; + rovernum++; + } + } - if (thing->eflags & MFE_VERTICALFLIP) - thing->z = thing->ceilingz - thing->height; - else - thing->z = thing->floorz; + // Match the Thing's old floorz to an FOF and check for FF_EXISTS + // If ~FF_EXISTS, don't set mobj Z. + if (!rover || (rover->flags & FF_EXISTS)) + { + if (thing->eflags & MFE_VERTICALFLIP) + thing->pmomz = thing->ceilingz - (thing->z + thing->height); + else + thing->pmomz = thing->floorz - thing->z; + thing->eflags |= MFE_APPLYPMOMZ; + + if (thing->eflags & MFE_VERTICALFLIP) + thing->z = thing->ceilingz - thing->height; + else + thing->z = thing->floorz; + } } else if (!tmfloorthing) { diff --git a/src/p_mobj.h b/src/p_mobj.h index afab6fda6..3a83a0f58 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -282,6 +282,10 @@ typedef struct mobj_s // The closest interval over all contacted sectors (or things). fixed_t floorz; // Nearest floor below. fixed_t ceilingz; // Nearest ceiling above. + size_t floor_sectornum; // FOF referred by floorz + size_t floor_rovernum; // FOF referred by floorz + size_t ceiling_sectornum; // FOF referred by ceilingz + size_t ceiling_rovernum; // FOF referred by ceilingz // For movement checking. fixed_t radius; diff --git a/src/p_saveg.c b/src/p_saveg.c index 22d43f358..33dfd1424 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1192,6 +1192,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, mobj->z); // Force this so 3dfloor problems don't arise. WRITEFIXED(save_p, mobj->floorz); WRITEFIXED(save_p, mobj->ceilingz); + WRITEUINT32(save_p, (UINT32)mobj->floor_sectornum); + WRITEUINT32(save_p, (UINT32)mobj->floor_rovernum); + WRITEUINT32(save_p, (UINT32)mobj->ceiling_sectornum); + WRITEUINT32(save_p, (UINT32)mobj->ceiling_rovernum); if (diff & MD_SPAWNPOINT) { @@ -1989,6 +1993,7 @@ static void LoadMobjThinker(actionf_p1 thinker) UINT16 diff2; INT32 i; fixed_t z, floorz, ceilingz; + size_t floor_sectornum, floor_rovernum, ceiling_sectornum, ceiling_rovernum; diff = READUINT32(save_p); if (diff & MD_MORE) @@ -2001,6 +2006,10 @@ static void LoadMobjThinker(actionf_p1 thinker) z = READFIXED(save_p); // Force this so 3dfloor problems don't arise. floorz = READFIXED(save_p); ceilingz = READFIXED(save_p); + floor_sectornum = (size_t)READUINT32(save_p); + floor_rovernum = (size_t)READUINT32(save_p); + ceiling_sectornum = (size_t)READUINT32(save_p); + ceiling_rovernum = (size_t)READUINT32(save_p); if (diff & MD_SPAWNPOINT) { @@ -2026,6 +2035,10 @@ static void LoadMobjThinker(actionf_p1 thinker) mobj->z = z; mobj->floorz = floorz; mobj->ceilingz = ceilingz; + mobj->floor_sectornum = floor_sectornum; + mobj->floor_rovernum = floor_rovernum; + mobj->ceiling_sectornum = ceiling_sectornum; + mobj->ceiling_rovernum = ceiling_rovernum; if (diff & MD_TYPE) mobj->type = READUINT32(save_p); From 7e3d5cd3734c5b2194dca7fb8875c9cfeca97dc4 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 8 Sep 2018 00:36:43 -0400 Subject: [PATCH 050/306] Comment out tmfloorrover and tmceilingrover because unused --- src/p_map.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 8d0a7aeb1..62f64922c 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -52,7 +52,7 @@ fixed_t tmfloorz, tmceilingz; static fixed_t tmdropoffz, tmdrpoffceilz; // drop-off floor/ceiling heights mobj_t *tmfloorthing; // the thing corresponding to tmfloorz or NULL if tmfloorz is from a sector mobj_t *tmhitthing; // the solid thing you bumped into (for collisions) -ffloor_t *tmfloorrover, *tmceilingrover; +//ffloor_t *tmfloorrover, *tmceilingrover; // unused for now size_t tmfloor_sectornum, tmfloor_rovernum, tmceiling_sectornum, tmceiling_rovernum; #ifdef ESLOPE pslope_t *tmfloorslope, *tmceilingslope; @@ -1419,7 +1419,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->z + thing->height > tmfloorz) { tmfloorz = thing->z + thing->height; - tmfloorrover = NULL; + // tmfloorrover = NULL; tmfloor_sectornum = tmfloor_rovernum = 0; #ifdef ESLOPE tmfloorslope = NULL; @@ -1441,7 +1441,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return false; tmfloorz = tmceilingz = topz; // block while in air - tmceilingrover = NULL; + // tmceilingrover = NULL; tmceiling_sectornum = tmceiling_rovernum = 0; #ifdef ESLOPE tmceilingslope = NULL; @@ -1451,7 +1451,7 @@ static boolean PIT_CheckThing(mobj_t *thing) else if (topz < tmceilingz && tmthing->z <= thing->z+thing->height) { tmceilingz = topz; - tmceilingrover = NULL; + // tmceilingrover = NULL; tmceiling_sectornum = tmceiling_rovernum = 0; #ifdef ESLOPE tmceilingslope = NULL; @@ -1469,7 +1469,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->z < tmceilingz) { tmceilingz = thing->z; - tmceilingrover = NULL; + // tmceilingrover = NULL; tmceiling_sectornum = tmceiling_rovernum = 0; #ifdef ESLOPE tmceilingslope = NULL; @@ -1491,7 +1491,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return false; tmfloorz = tmceilingz = topz; // block while in air - tmfloorrover = NULL; + // tmfloorrover = NULL; tmfloor_sectornum = tmfloor_rovernum = 0; #ifdef ESLOPE tmfloorslope = NULL; @@ -1501,7 +1501,7 @@ static boolean PIT_CheckThing(mobj_t *thing) else if (topz > tmfloorz && tmthing->z+tmthing->height >= thing->z) { tmfloorz = topz; - tmfloorrover = NULL; + // tmfloorrover = NULL; tmfloor_sectornum = tmfloor_rovernum = 0; #ifdef ESLOPE tmfloorslope = NULL; @@ -1654,7 +1654,7 @@ static boolean PIT_CheckLine(line_t *ld) { tmceilingz = opentop; ceilingline = ld; - tmceilingrover = NULL; + // tmceilingrover = NULL; tmceiling_sectornum = tmceiling_rovernum = 0; #ifdef ESLOPE tmceilingslope = opentopslope; @@ -1664,7 +1664,7 @@ static boolean PIT_CheckLine(line_t *ld) if (openbottom > tmfloorz) { tmfloorz = openbottom; - tmfloorrover = NULL; + // tmfloorrover = NULL; tmfloor_sectornum = tmfloor_rovernum = 0; #ifdef ESLOPE tmfloorslope = openbottomslope; @@ -1747,9 +1747,9 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) // will adjust them. tmfloorz = tmdropoffz = P_GetFloorZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->floorheight; tmceilingz = P_GetCeilingZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->ceilingheight; - tmfloorrover = NULL; + // tmfloorrover = NULL; tmfloor_sectornum = tmfloor_rovernum = 0; - tmceilingrover = NULL; + // tmceilingrover = NULL; tmceiling_sectornum = tmceiling_rovernum = 0; #ifdef ESLOPE tmfloorslope = newsubsec->sector->f_slope; @@ -1798,7 +1798,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) { if (tmfloorz < topheight - sinklevel) { tmfloorz = topheight - sinklevel; - tmfloorrover = rover; + // tmfloorrover = rover; tmfloor_sectornum = newsubsec->sector - sectors; tmfloor_rovernum = rovernum; #ifdef ESLOPE @@ -1810,7 +1810,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) { if (tmceilingz > bottomheight + sinklevel) { tmceilingz = bottomheight + sinklevel; - tmceilingrover = rover; + // tmceilingrover = rover; tmceiling_sectornum = newsubsec->sector - sectors; tmceiling_rovernum = rovernum; #ifdef ESLOPE @@ -1841,7 +1841,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) { if (tmfloorz < thing->z) { tmfloorz = thing->z; - tmfloorrover = rover; + // tmfloorrover = rover; tmfloor_sectornum = newsubsec->sector - sectors; tmfloor_rovernum = rovernum; #ifdef ESLOPE @@ -1863,7 +1863,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) && !(rover->flags & FF_REVERSEPLATFORM)) { tmfloorz = tmdropoffz = topheight; - tmfloorrover = rover; + // tmfloorrover = rover; tmfloor_sectornum = newsubsec->sector - sectors; tmfloor_rovernum = rovernum; #ifdef ESLOPE @@ -1875,7 +1875,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) && !(thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE))) { tmceilingz = tmdrpoffceilz = bottomheight; - tmceilingrover = rover; + // tmceilingrover = rover; tmceiling_sectornum = newsubsec->sector - sectors; tmceiling_rovernum = rovernum; #ifdef ESLOPE @@ -2375,8 +2375,8 @@ boolean PIT_PushableMoved(mobj_t *thing) mobj_t *oldthing = tmthing; line_t *oldceilline = ceilingline; line_t *oldblockline = blockingline; - ffloor_t *oldflrrover = tmfloorrover; - ffloor_t *oldceilrover = tmceilingrover; + // ffloor_t *oldflrrover = tmfloorrover; + // ffloor_t *oldceilrover = tmceilingrover; size_t oldflrrover_sectornum = tmfloor_sectornum; size_t oldflrrover_ffloornum = tmfloor_rovernum; size_t oldceilrover_sectornum = tmceiling_sectornum; @@ -2397,8 +2397,8 @@ boolean PIT_PushableMoved(mobj_t *thing) P_SetTarget(&tmthing, oldthing); ceilingline = oldceilline; blockingline = oldblockline; - tmfloorrover = oldflrrover; - tmceilingrover = oldceilrover; + // tmfloorrover = oldflrrover; + // tmceilingrover = oldceilrover; tmfloor_sectornum = oldflrrover_sectornum; tmfloor_rovernum = oldflrrover_ffloornum; tmceiling_sectornum = oldceilrover_sectornum; From b629104197ada81d27c84c023430749965ed5dc6 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 8 Sep 2018 01:02:17 -0400 Subject: [PATCH 051/306] Also check for FF_SOLID --- src/p_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_map.c b/src/p_map.c index 62f64922c..c275ba0be 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2765,7 +2765,7 @@ static boolean P_ThingHeightClip(mobj_t *thing) // Match the Thing's old floorz to an FOF and check for FF_EXISTS // If ~FF_EXISTS, don't set mobj Z. - if (!rover || (rover->flags & FF_EXISTS)) + if (!rover || ((rover->flags & FF_EXISTS) && (rover->flags & FF_SOLID))) { if (thing->eflags & MFE_VERTICALFLIP) thing->pmomz = thing->ceilingz - (thing->z + thing->height); From 66dc84509a2d16c44cad27d74bb185532484df85 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 8 Sep 2018 01:12:34 -0400 Subject: [PATCH 052/306] Fix Mario block triggering during ghost fade --- src/p_spec.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/p_spec.c b/src/p_spec.c index 6ba73f98d..1a0fa91b0 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7485,6 +7485,8 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, rover->flags &= ~FF_QUICKSAND; if (rover->spawnflags & FF_BUSTUP) rover->flags &= ~FF_BUSTUP; + if (rover->spawnflags & FF_MARIO) + rover->flags &= ~FF_MARIO; } } else // continue fading out @@ -7510,6 +7512,8 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, rover->flags |= FF_QUICKSAND; if (rover->spawnflags & FF_BUSTUP) rover->flags |= FF_BUSTUP; + if (rover->spawnflags & FF_MARIO) + rover->flags |= FF_MARIO; } } else // continue fading in @@ -7567,6 +7571,8 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, rover->flags &= ~FF_QUICKSAND; if (rover->spawnflags & FF_BUSTUP) rover->flags &= ~FF_BUSTUP; + if (rover->spawnflags & FF_MARIO) + rover->flags &= ~FF_MARIO; } else // keep collision during fade { @@ -7578,6 +7584,8 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, rover->flags |= FF_QUICKSAND; if (rover->spawnflags & FF_BUSTUP) rover->flags |= FF_BUSTUP; + if (rover->spawnflags & FF_MARIO) + rover->flags |= FF_MARIO; } } } From dc964738eb8939888c5a988cdf41a294a029e505 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 8 Sep 2018 01:23:15 -0400 Subject: [PATCH 053/306] Never handle FF_EXISTS if FF_BUSTUP --- src/p_spec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 1a0fa91b0..9a1ed4e9f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7526,7 +7526,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, // routines common to both fade in and fade out if (!stillfading) { - if (doexists) + if (doexists && !(rover->spawnflags & FF_BUSTUP)) { if (alpha <= 1) rover->flags &= ~FF_EXISTS; @@ -7550,7 +7550,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, } else { - if (doexists) + if (doexists && !(rover->spawnflags & FF_BUSTUP)) rover->flags |= FF_EXISTS; if (dotranslucent) From 47c9bf2ebc9e7b95af4b3c1731c2c6999e994501 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 8 Sep 2018 01:33:12 -0400 Subject: [PATCH 054/306] Disable FadeFakeFloor for laser block --- src/p_spec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_spec.c b/src/p_spec.c index 9a1ed4e9f..307cca05f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7460,6 +7460,9 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, INT32 alpha; fade_t *fadingdata = (fade_t *)rover->fadingdata; + if (rover->master->special == 258) // Laser block + return false; + if (fadingdata) alpha = fadingdata->alpha; else From fcc7180d5c01c22026aee2f1c26a82b32717b449 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 8 Sep 2018 08:46:56 -0400 Subject: [PATCH 055/306] Enable FF_CUTSOLIDS handling and updating by sector->moved --- src/p_spec.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 307cca05f..78c78d5e0 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7541,13 +7541,23 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, { if (alpha >= 256) { - //rover->flags |= (FF_CUTLEVEL | FF_CUTEXTRA); + if (!(rover->flags & FF_CUTSOLIDS) && + (rover->spawnflags & FF_CUTSOLIDS)) + { + rover->flags |= FF_CUTSOLIDS; + rover->target->moved = true; + } rover->flags &= ~FF_TRANSLUCENT; } else { rover->flags |= FF_TRANSLUCENT; - //rover->flags &= ~(FF_CUTLEVEL | FF_CUTEXTRA); + if ((rover->flags & FF_CUTSOLIDS) && + (rover->spawnflags & FF_CUTSOLIDS)) + { + rover->flags &= ~FF_CUTSOLIDS; + rover->target->moved = true; + } } } } @@ -7559,7 +7569,12 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, if (dotranslucent) { rover->flags |= FF_TRANSLUCENT; - //rover->flags &= ~(FF_CUTLEVEL | FF_CUTEXTRA); + if ((rover->flags & FF_CUTSOLIDS) && + (rover->spawnflags & FF_CUTSOLIDS)) + { + rover->flags &= ~FF_CUTSOLIDS; + rover->target->moved = true; + } } if (docollision) From fa0918c2f150ea77b322dd3e22d181c5c9fbe1e0 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 8 Sep 2018 09:08:32 -0400 Subject: [PATCH 056/306] Handle rendering flags for invisible FOFs --- src/p_spec.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/p_spec.c b/src/p_spec.c index 78c78d5e0..62959dcce 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7547,11 +7547,13 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, rover->flags |= FF_CUTSOLIDS; rover->target->moved = true; } + rover->flags &= ~FF_TRANSLUCENT; } else { rover->flags |= FF_TRANSLUCENT; + if ((rover->flags & FF_CUTSOLIDS) && (rover->spawnflags & FF_CUTSOLIDS)) { @@ -7559,6 +7561,15 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, rover->target->moved = true; } } + + if (!(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES)) + { + if (rover->alpha > 1) + rover->flags |= FF_RENDERALL; + else + rover->flags &= ~FF_RENDERALL; + } } } else @@ -7569,12 +7580,17 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, if (dotranslucent) { rover->flags |= FF_TRANSLUCENT; + if ((rover->flags & FF_CUTSOLIDS) && (rover->spawnflags & FF_CUTSOLIDS)) { rover->flags &= ~FF_CUTSOLIDS; rover->target->moved = true; } + + if (!(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES)) + rover->flags |= FF_RENDERALL; } if (docollision) From 3858a93cfadaa9c6807998a4a35c20eefd8bfe95 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 8 Sep 2018 09:31:23 -0400 Subject: [PATCH 057/306] Initialize invisible FOF alpha to 1 on first fade --- src/p_spec.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/p_spec.c b/src/p_spec.c index 62959dcce..88506f0fe 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7463,6 +7463,14 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, if (rover->master->special == 258) // Laser block return false; + // If fading an invisible FOF whose render flags we did not yet set, + // initialize its alpha to 1 + if (dotranslucent && + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES) && + !(rover->flags & FF_RENDERALL)) + rover->alpha = 1; + if (fadingdata) alpha = fadingdata->alpha; else @@ -7678,6 +7686,15 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor d->rover = rover; d->sectornum = (INT32)sectornum; d->ffloornum = (INT32)ffloornum; + + // If fading an invisible FOF whose render flags we did not yet set, + // initialize its alpha to 1 + if (dotranslucent && + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES) && + !(rover->flags & FF_RENDERALL)) + rover->alpha = 1; + d->alpha = rover->alpha; d->destvalue = max(1, min(256, destvalue)); // ffloor->alpha is 1-256 d->speed = max(1, speed); // minimum speed 1/tic // if speed < 1, alpha is set immediately in thinker From 3eb7c3931e93c4cd4d39c71867bf85f8d7dae5c8 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 8 Sep 2018 20:06:48 -0400 Subject: [PATCH 058/306] When detecting invisible FOFs, don't include light blocks --- src/p_spec.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 88506f0fe..bf3f58697 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7466,6 +7466,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, // If fading an invisible FOF whose render flags we did not yet set, // initialize its alpha to 1 if (dotranslucent && + (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE !(rover->spawnflags & FF_RENDERSIDES) && !(rover->spawnflags & FF_RENDERPLANES) && !(rover->flags & FF_RENDERALL)) @@ -7570,7 +7571,8 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, } } - if (!(rover->spawnflags & FF_RENDERSIDES) && + if ((rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->spawnflags & FF_RENDERSIDES) && !(rover->spawnflags & FF_RENDERPLANES)) { if (rover->alpha > 1) @@ -7596,7 +7598,8 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, rover->target->moved = true; } - if (!(rover->spawnflags & FF_RENDERSIDES) && + if ((rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->spawnflags & FF_RENDERSIDES) && !(rover->spawnflags & FF_RENDERPLANES)) rover->flags |= FF_RENDERALL; } @@ -7690,6 +7693,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor // If fading an invisible FOF whose render flags we did not yet set, // initialize its alpha to 1 if (dotranslucent && + (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE !(rover->spawnflags & FF_RENDERSIDES) && !(rover->spawnflags & FF_RENDERPLANES) && !(rover->flags & FF_RENDERALL)) From 069cc480c1f217968ef7ebe58503527092323148 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 8 Sep 2018 20:41:45 -0400 Subject: [PATCH 059/306] Add dolighting flag to FadeFakeFloor thinker --- src/p_saveg.c | 2 ++ src/p_spec.c | 14 +++++++++----- src/p_spec.h | 1 + 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 3b726b97d..05501ccc0 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1592,6 +1592,7 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type) WRITEUINT8(save_p, ht->doexists); WRITEUINT8(save_p, ht->dotranslucent); WRITEUINT8(save_p, ht->docollision); + WRITEUINT8(save_p, ht->dolighting); WRITEUINT8(save_p, ht->doghostfade); WRITEUINT8(save_p, ht->exactalpha); } @@ -2596,6 +2597,7 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->doexists = READUINT8(save_p); ht->dotranslucent = READUINT8(save_p); ht->docollision = READUINT8(save_p); + ht->dolighting = READUINT8(save_p); ht->doghostfade = READUINT8(save_p); ht->exactalpha = READUINT8(save_p); diff --git a/src/p_spec.c b/src/p_spec.c index bf3f58697..c73118515 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -106,10 +106,10 @@ static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t o static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize); #define P_RemoveFakeFloorFader(l) P_ResetFakeFloorFader(l, NULL, false); static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, - boolean doexists, boolean dotranslucent, boolean docollision, boolean doghostfade, boolean exactalpha); + boolean doexists, boolean dotranslucent, boolean docollision, boolean dolighting, boolean doghostfade, boolean exactalpha); static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, INT16 destvalue, INT16 speed, - boolean doexists, boolean dotranslucent, boolean docollision, boolean doghostfade, boolean exactalpha); + boolean doexists, boolean dotranslucent, boolean docollision, boolean dolighting, boolean doghostfade, boolean exactalpha); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); @@ -3356,6 +3356,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT !(line->flags & ML_BOUNCY), // do not handle interactive flags + !(line->flags & ML_EFFECT2), // do not handle lighting (line->flags & ML_EFFECT1), // do ghost fade (no interactive flags during fade) (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) else @@ -3366,6 +3367,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT !(line->flags & ML_BOUNCY), // do not handle interactive flags + !(line->flags & ML_EFFECT2), // do not handle lighting (line->flags & ML_EFFECT1), // do ghost fade (no interactive flags during fade) (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) } @@ -7442,6 +7444,7 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz fadingdata->doexists, fadingdata->dotranslucent, fadingdata->docollision, + fadingdata->dolighting, fadingdata->doghostfade, fadingdata->exactalpha); rover->alpha = fadingdata->alpha; @@ -7454,7 +7457,7 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz } static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, - boolean doexists, boolean dotranslucent, boolean docollision, boolean doghostfade, boolean exactalpha) + boolean doexists, boolean dotranslucent, boolean docollision, boolean dolighting, boolean doghostfade, boolean exactalpha) { boolean stillfading = false; INT32 alpha; @@ -7681,7 +7684,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, */ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, INT16 destvalue, INT16 speed, - boolean doexists, boolean dotranslucent, boolean docollision, boolean doghostfade, boolean exactalpha) + boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha) { fade_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); @@ -7705,6 +7708,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor d->doexists = doexists; d->dotranslucent = dotranslucent; d->docollision = docollision; + d->dolighting = dolighting; d->doghostfade = doghostfade; d->exactalpha = exactalpha; @@ -7721,7 +7725,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor */ void T_Fade(fade_t *d) { - if (d->rover && !P_FadeFakeFloor(d->rover, d->destvalue, d->speed, d->doexists, d->dotranslucent, d->docollision, d->doghostfade, d->exactalpha)) + if (d->rover && !P_FadeFakeFloor(d->rover, d->destvalue, d->speed, d->doexists, d->dotranslucent, d->docollision, d->dolighting, d->doghostfade, d->exactalpha)) P_RemoveFakeFloorFader(d->rover); } diff --git a/src/p_spec.h b/src/p_spec.h index f00a1cdbd..df400fac1 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -466,6 +466,7 @@ typedef struct boolean doexists; ///< Handle FF_EXISTS boolean dotranslucent; ///< Handle FF_TRANSLUCENT boolean docollision; ///< Handle interactive flags + boolean dolighting; ///< Handle shadows and light blocks boolean doghostfade; ///< No interactive flags during fading boolean exactalpha; ///< Use exact alpha values (opengl) } fade_t; From 81acf82e99a6112f4c4fe34c5528219b234f3960 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 8 Sep 2018 20:49:32 -0400 Subject: [PATCH 060/306] Re-render lighting when setting FF_EXISTS --- src/p_spec.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/p_spec.c b/src/p_spec.c index c73118515..7ee047afb 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7547,6 +7547,10 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, rover->flags &= ~FF_EXISTS; else rover->flags |= FF_EXISTS; + + // Re-render lighting at end of fade + if (dolighting && !(rover->spawnflags & FF_NOSHADE) && !(rover->flags & FF_EXISTS)) + rover->target->moved = true; } if (dotranslucent) @@ -7588,7 +7592,13 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, else { if (doexists && !(rover->spawnflags & FF_BUSTUP)) + { + // Re-render lighting if we haven't yet set FF_EXISTS (beginning of fade) + if (dolighting && !(rover->spawnflags & FF_NOSHADE) && !(rover->flags & FF_EXISTS)) + rover->target->moved = true; + rover->flags |= FF_EXISTS; + } if (dotranslucent) { From 1e1b01c1572f8dcb941e06ba0e914ef881ed1643 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 8 Sep 2018 22:10:51 -0400 Subject: [PATCH 061/306] Implemented tic-based light fading * ML_BLOCKMONSTERS specifies destvalue and speed by texture offsets * ML_NOCLIMB toggles tic-based logic * Added props `duration`, `interval`, and `firsttic` to `lightlevel_t` --- src/lua_baselib.c | 3 ++- src/p_lights.c | 47 ++++++++++++++++++++++++++++++++++++++++++----- src/p_saveg.c | 6 ++++++ src/p_spec.c | 5 ++++- src/p_spec.h | 7 ++++++- 5 files changed, 60 insertions(+), 8 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index c1fd87af3..840863eb0 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1809,9 +1809,10 @@ static int lib_pFadeLight(lua_State *L) INT16 tag = (INT16)luaL_checkinteger(L, 1); INT32 destvalue = (INT32)luaL_checkinteger(L, 2); INT32 speed = (INT32)luaL_checkinteger(L, 3); + boolean ticbased = lua_optboolean(L, 4); NOHUD INLEVEL - P_FadeLight(tag, destvalue, speed); + P_FadeLight(tag, destvalue, speed, ticbased); return 0; } diff --git a/src/p_lights.c b/src/p_lights.c index 8aa2eedca..e37eda5fb 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -13,6 +13,7 @@ /// Fire flicker, light flash, strobe flash, lightning flash, glow, and fade. #include "doomdef.h" +#include "doomstat.h" // gametic #include "p_local.h" #include "r_state.h" #include "z_zone.h" @@ -329,12 +330,10 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, * \param destvalue The final light value in these sectors. * \param speed Speed of the fade; the change to the ligh * level in each sector per tic. - * \todo Calculate speed better so that it is possible to specify - * the time for completion of the fade, and all lights fade - * in this time regardless of initial values. + * \param ticbased Use a specific duration for the fade, defined by speed * \sa T_LightFade */ -void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed) +void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased) { INT32 i; lightlevel_t *ll; @@ -346,6 +345,13 @@ void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed) sector = §ors[i]; P_RemoveLighting(sector); // remove the old lighting effect first + + if ((ticbased && !speed) || sector->lightlevel == destvalue) // set immediately + { + sector->lightlevel = destvalue; + continue; + } + ll = Z_Calloc(sizeof (*ll), PU_LEVSPEC, NULL); ll->thinker.function.acp1 = (actionf_p1)T_LightFade; sector->lightingdata = ll; // set it to the lightlevel_t @@ -354,7 +360,21 @@ void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed) ll->sector = sector; ll->destlevel = destvalue; - ll->speed = speed; + + if (ticbased) + { + ll->duration = abs(speed); + ll->speed = FixedFloor(FixedDiv(destvalue - sector->lightlevel, ll->duration))/FRACUNIT; + if (!ll->speed) + ll->speed = (destvalue < sector->lightlevel) ? -1 : 1; + ll->interval = max(FixedFloor(FixedDiv(ll->duration, abs(destvalue - sector->lightlevel)))/FRACUNIT, 1); + ll->firsttic = gametic; + } + else + { + ll->duration = -1; + ll->speed = abs(speed); + } } } @@ -365,6 +385,23 @@ void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed) */ void T_LightFade(lightlevel_t *ll) { + if (ll->duration >= 0) // tic-based + { + if (gametic - ll->firsttic >= ll->duration) + { + ll->sector->lightlevel = (INT16)ll->destlevel; // set to dest lightlevel + P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker + } + else if (!((gametic - ll->firsttic) % ll->interval)) + { + if (ll->speed < 0) + ll->sector->lightlevel = max(ll->sector->lightlevel + (INT16)ll->speed, (INT16)ll->destlevel); + else + ll->sector->lightlevel = min(ll->sector->lightlevel + (INT16)ll->speed, (INT16)ll->destlevel); + } + return; + } + if (ll->sector->lightlevel < ll->destlevel) { // increase the lightlevel diff --git a/src/p_saveg.c b/src/p_saveg.c index 22d43f358..8ec5b5ea8 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1539,6 +1539,9 @@ static void SaveLightlevelThinker(const thinker_t *th, const UINT8 type) WRITEUINT32(save_p, SaveSector(ht->sector)); WRITEINT32(save_p, ht->destlevel); WRITEINT32(save_p, ht->speed); + WRITEINT32(save_p, ht->duration); + WRITEUINT32(save_p, ht->interval); + WRITEUINT32(save_p, (UINT32)ht->firsttic); } // @@ -2512,6 +2515,9 @@ static inline void LoadLightlevelThinker(actionf_p1 thinker) ht->sector = LoadSector(READUINT32(save_p)); ht->destlevel = READINT32(save_p); ht->speed = READINT32(save_p); + ht->duration = READINT32(save_p); + ht->interval = READUINT32(save_p); + ht->firsttic = (tic_t)READUINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; P_AddThinker(&ht->thinker); diff --git a/src/p_spec.c b/src/p_spec.c index 6c359c9cc..a894dcbfb 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2778,7 +2778,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 420: // Fade light levels in tagged sectors to new value - P_FadeLight(line->tag, line->frontsector->lightlevel, P_AproxDistance(line->dx, line->dy)>>FRACBITS); + P_FadeLight(line->tag, + (line->flags & ML_BLOCKMONSTERS) ? max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 255), 0) : line->frontsector->lightlevel, + (line->flags & ML_BLOCKMONSTERS) ? max(sides[line->sidenum[0]].rowoffset>>FRACBITS, 0) : P_AproxDistance(line->dx, line->dy)>>FRACBITS, + (line->flags & ML_NOCLIMB)); break; case 421: // Stop lighting effect in tagged sectors diff --git a/src/p_spec.h b/src/p_spec.h index e0bcc18eb..8e296891b 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -138,6 +138,11 @@ typedef struct sector_t *sector; ///< Sector where action is taking place. INT32 destlevel; ///< Light level we're fading to. INT32 speed; ///< Speed at which to change light level. + + // Tic-based behavior + INT32 duration; ///< If <0, do not use tic-based behavior. If 0, set instantly. If >0, fade lasts this duration. + UINT32 interval; ///< Interval to deduct light level + tic_t firsttic; ///< First gametic to count from } lightlevel_t; #define GLOWSPEED 8 @@ -156,7 +161,7 @@ strobe_t * P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector void T_Glow(glow_t *g); glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, INT32 length); -void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed); +void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased); void T_LightFade(lightlevel_t *ll); typedef enum From 68e67917f1b345633151e3315ffd061d4fde5837 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 8 Sep 2018 22:14:49 -0400 Subject: [PATCH 062/306] Split P_FadeLight into P_FadeLightBySector --- src/p_lights.c | 80 +++++++++++++++++++++++++------------------------- src/p_spec.h | 1 + 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/src/p_lights.c b/src/p_lights.c index e37eda5fb..8be3d793c 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -323,59 +323,59 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, return g; } -/** Fades all the lights in sectors with a particular tag to a new +/** Fades all the lights in specified sector to a new * value. * - * \param tag Tag to look for sectors by. + * \param sector Target sector * \param destvalue The final light value in these sectors. * \param speed Speed of the fade; the change to the ligh * level in each sector per tic. * \param ticbased Use a specific duration for the fade, defined by speed * \sa T_LightFade */ +void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ticbased) +{ + lightlevel_t *ll; + + P_RemoveLighting(sector); // remove the old lighting effect first + + if ((ticbased && !speed) || sector->lightlevel == destvalue) // set immediately + { + sector->lightlevel = destvalue; + return; + } + + ll = Z_Calloc(sizeof (*ll), PU_LEVSPEC, NULL); + ll->thinker.function.acp1 = (actionf_p1)T_LightFade; + sector->lightingdata = ll; // set it to the lightlevel_t + + P_AddThinker(&ll->thinker); // add thinker + + ll->sector = sector; + ll->destlevel = destvalue; + + if (ticbased) + { + ll->duration = abs(speed); + ll->speed = FixedFloor(FixedDiv(destvalue - sector->lightlevel, ll->duration))/FRACUNIT; + if (!ll->speed) + ll->speed = (destvalue < sector->lightlevel) ? -1 : 1; + ll->interval = max(FixedFloor(FixedDiv(ll->duration, abs(destvalue - sector->lightlevel)))/FRACUNIT, 1); + ll->firsttic = gametic; + } + else + { + ll->duration = -1; + ll->speed = abs(speed); + } +} + void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased) { INT32 i; - lightlevel_t *ll; - sector_t *sector; - // search all sectors for ones with tag for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0 ;) - { - sector = §ors[i]; - - P_RemoveLighting(sector); // remove the old lighting effect first - - if ((ticbased && !speed) || sector->lightlevel == destvalue) // set immediately - { - sector->lightlevel = destvalue; - continue; - } - - ll = Z_Calloc(sizeof (*ll), PU_LEVSPEC, NULL); - ll->thinker.function.acp1 = (actionf_p1)T_LightFade; - sector->lightingdata = ll; // set it to the lightlevel_t - - P_AddThinker(&ll->thinker); // add thinker - - ll->sector = sector; - ll->destlevel = destvalue; - - if (ticbased) - { - ll->duration = abs(speed); - ll->speed = FixedFloor(FixedDiv(destvalue - sector->lightlevel, ll->duration))/FRACUNIT; - if (!ll->speed) - ll->speed = (destvalue < sector->lightlevel) ? -1 : 1; - ll->interval = max(FixedFloor(FixedDiv(ll->duration, abs(destvalue - sector->lightlevel)))/FRACUNIT, 1); - ll->firsttic = gametic; - } - else - { - ll->duration = -1; - ll->speed = abs(speed); - } - } + P_FadeLightBySector(§ors[i], destvalue, speed, ticbased); } /** Fades the light level in a sector to a new value. diff --git a/src/p_spec.h b/src/p_spec.h index 8e296891b..c2c4c8976 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -161,6 +161,7 @@ strobe_t * P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector void T_Glow(glow_t *g); glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, INT32 length); +void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ticbased); void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased); void T_LightFade(lightlevel_t *ll); From cc26d03c93c91d6209b2b51acc63758c837b2cf4 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 8 Sep 2018 23:01:35 -0400 Subject: [PATCH 063/306] Snap light level to software values (32 levels) * New properties `exactlightlevel` and `lightlevel` in `lightlevel_t` --- src/lua_baselib.c | 3 +- src/p_lights.c | 75 +++++++++++++++++++++++++++++++---------------- src/p_saveg.c | 4 +++ src/p_spec.c | 3 +- src/p_spec.h | 8 +++-- 5 files changed, 63 insertions(+), 30 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 840863eb0..74b842e2a 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1810,9 +1810,10 @@ static int lib_pFadeLight(lua_State *L) INT32 destvalue = (INT32)luaL_checkinteger(L, 2); INT32 speed = (INT32)luaL_checkinteger(L, 3); boolean ticbased = lua_optboolean(L, 4); + boolean exactlightlevel = lua_optboolean(L, 5); NOHUD INLEVEL - P_FadeLight(tag, destvalue, speed, ticbased); + P_FadeLight(tag, destvalue, speed, ticbased, exactlightlevel); return 0; } diff --git a/src/p_lights.c b/src/p_lights.c index 8be3d793c..b2934b792 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -15,6 +15,7 @@ #include "doomdef.h" #include "doomstat.h" // gametic #include "p_local.h" +#include "r_main.h" // LIGHTSEGSHIFT #include "r_state.h" #include "z_zone.h" #include "m_random.h" @@ -331,9 +332,10 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, * \param speed Speed of the fade; the change to the ligh * level in each sector per tic. * \param ticbased Use a specific duration for the fade, defined by speed + * \param exactlightlevel Do not snap to software values (for OpenGL) * \sa T_LightFade */ -void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ticbased) +void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ticbased, boolean exactlightlevel) { lightlevel_t *ll; @@ -353,6 +355,8 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ll->sector = sector; ll->destlevel = destvalue; + ll->exactlightlevel = exactlightlevel; + ll->lightlevel = sector->lightlevel; if (ticbased) { @@ -370,12 +374,12 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean } } -void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased) +void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean exactlightlevel) { INT32 i; // search all sectors for ones with tag for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0 ;) - P_FadeLightBySector(§ors[i], destvalue, speed, ticbased); + P_FadeLightBySector(§ors[i], destvalue, speed, ticbased, exactlightlevel); } /** Fades the light level in a sector to a new value. @@ -385,47 +389,66 @@ void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased) */ void T_LightFade(lightlevel_t *ll) { + boolean stillfading = false; + INT16 lightlevel = ll->lightlevel; + if (ll->duration >= 0) // tic-based { + stillfading = !(gametic - ll->firsttic >= ll->duration); if (gametic - ll->firsttic >= ll->duration) { - ll->sector->lightlevel = (INT16)ll->destlevel; // set to dest lightlevel + lightlevel = (INT16)ll->destlevel; // set to dest lightlevel P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker } else if (!((gametic - ll->firsttic) % ll->interval)) { if (ll->speed < 0) - ll->sector->lightlevel = max(ll->sector->lightlevel + (INT16)ll->speed, (INT16)ll->destlevel); + lightlevel = max(lightlevel + (INT16)ll->speed, (INT16)ll->destlevel); else - ll->sector->lightlevel = min(ll->sector->lightlevel + (INT16)ll->speed, (INT16)ll->destlevel); + lightlevel = min(lightlevel + (INT16)ll->speed, (INT16)ll->destlevel); } - return; } - - if (ll->sector->lightlevel < ll->destlevel) + else // x/tic speed-based { - // increase the lightlevel - if (ll->sector->lightlevel + ll->speed >= ll->destlevel) + if (lightlevel < ll->destlevel) { - // stop changing light level - ll->sector->lightlevel = (INT16)ll->destlevel; // set to dest lightlevel + // increase the lightlevel + if (lightlevel + ll->speed >= ll->destlevel) + { + // stop changing light level + lightlevel = (INT16)ll->destlevel; // set to dest lightlevel - P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker + P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker + } + else + { + stillfading = true; + lightlevel = (INT16)(lightlevel + (INT16)ll->speed); // move lightlevel + } } else - ll->sector->lightlevel = (INT16)(ll->sector->lightlevel + (INT16)ll->speed); // move lightlevel + { + // decrease lightlevel + if (lightlevel - ll->speed <= ll->destlevel) + { + // stop changing light level + lightlevel = (INT16)ll->destlevel; // set to dest lightlevel + + P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker + } + else + { + stillfading = true; + lightlevel = (INT16)(lightlevel - (INT16)ll->speed); // move lightlevel + } + } } + + // Snap light level to software values + if (!stillfading || ll->exactlightlevel) + ll->sector->lightlevel = lightlevel; else - { - // decrease lightlevel - if (ll->sector->lightlevel - ll->speed <= ll->destlevel) - { - // stop changing light level - ll->sector->lightlevel = (INT16)ll->destlevel; // set to dest lightlevel + ll->sector->lightlevel = (lightlevel >> LIGHTSEGSHIFT) << LIGHTSEGSHIFT; - P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker - } - else - ll->sector->lightlevel = (INT16)(ll->sector->lightlevel - (INT16)ll->speed); // move lightlevel - } + ll->lightlevel = lightlevel; } diff --git a/src/p_saveg.c b/src/p_saveg.c index 8ec5b5ea8..95d073fc9 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1542,6 +1542,8 @@ static void SaveLightlevelThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->duration); WRITEUINT32(save_p, ht->interval); WRITEUINT32(save_p, (UINT32)ht->firsttic); + WRITEUINT8(save_p, (UINT8)ht->exactlightlevel); + WRITEINT16(save_p, ht->lightlevel); } // @@ -2518,6 +2520,8 @@ static inline void LoadLightlevelThinker(actionf_p1 thinker) ht->duration = READINT32(save_p); ht->interval = READUINT32(save_p); ht->firsttic = (tic_t)READUINT32(save_p); + ht->exactlightlevel = (boolean)READUINT8(save_p); + ht->lightlevel = READINT16(save_p); if (ht->sector) ht->sector->lightingdata = ht; P_AddThinker(&ht->thinker); diff --git a/src/p_spec.c b/src/p_spec.c index a894dcbfb..707e19f08 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2781,7 +2781,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_FadeLight(line->tag, (line->flags & ML_BLOCKMONSTERS) ? max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 255), 0) : line->frontsector->lightlevel, (line->flags & ML_BLOCKMONSTERS) ? max(sides[line->sidenum[0]].rowoffset>>FRACBITS, 0) : P_AproxDistance(line->dx, line->dy)>>FRACBITS, - (line->flags & ML_NOCLIMB)); + (line->flags & ML_NOCLIMB), + (line->flags & ML_TFERLINE)); break; case 421: // Stop lighting effect in tagged sectors diff --git a/src/p_spec.h b/src/p_spec.h index c2c4c8976..b354e6772 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -143,6 +143,10 @@ typedef struct INT32 duration; ///< If <0, do not use tic-based behavior. If 0, set instantly. If >0, fade lasts this duration. UINT32 interval; ///< Interval to deduct light level tic_t firsttic; ///< First gametic to count from + + // Snap to software values + boolean exactlightlevel; ///< Use exact values for OpenGL + INT16 lightlevel; ///< Internal counter for fading } lightlevel_t; #define GLOWSPEED 8 @@ -161,8 +165,8 @@ strobe_t * P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector void T_Glow(glow_t *g); glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, INT32 length); -void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ticbased); -void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased); +void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ticbased, boolean exactlightlevel); +void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean exactlightlevel); void T_LightFade(lightlevel_t *ll); typedef enum From 0049f904c09dc3b87c8e7ed8f317219dd80d12a5 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 8 Sep 2018 23:44:29 -0400 Subject: [PATCH 064/306] Add light fading to FadeFakeFloor * Declare P_RemoveLighting in header for p_spec.c use --- src/p_lights.c | 2 +- src/p_spec.c | 13 +++++++++++++ src/p_spec.h | 2 ++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/p_lights.c b/src/p_lights.c index b2934b792..02221d197 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -25,7 +25,7 @@ * * \param sector The sector to remove effects from. */ -static void P_RemoveLighting(sector_t *sector) +void P_RemoveLighting(sector_t *sector) { if (sector->lightingdata) { diff --git a/src/p_spec.c b/src/p_spec.c index 1f8f1c2b0..a1465b0e7 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7453,6 +7453,12 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz fadingdata->exactalpha); rover->alpha = fadingdata->alpha; + if (fadingdata->dolighting) + { + P_RemoveLighting(§ors[rover->secnum]); + §ors[rover->secnum].lightlevel = rover->target->lightlevel; // \todo get fade light level destvalue + } + P_RemoveThinker(&fadingdata->thinker); } @@ -7729,6 +7735,13 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor // find any existing thinkers and remove them, then replace with new data P_ResetFakeFloorFader(rover, d, false); + // Set a separate thinker for shadow fading + if (dolighting && !(rover->flags & FF_NOSHADE)) + P_FadeLightBySector(§ors[rover->secnum], + rover->target->lightlevel, // (shadowlight - targetlight) * destvalue/256 // \todo get fade light level destvalue + FixedFloor(FixedDiv(abs(d->destvalue - d->alpha), d->speed))/FRACUNIT, + true, exactalpha); + P_AddThinker(&d->thinker); } diff --git a/src/p_spec.h b/src/p_spec.h index ec1911df3..0d118168b 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -154,6 +154,8 @@ typedef struct #define FASTDARK 15 #define SLOWDARK 35 +void P_RemoveLighting(sector_t *sector); + void T_FireFlicker(fireflicker_t *flick); fireflicker_t *P_SpawnAdjustableFireFlicker(sector_t *minsector, sector_t *maxsector, INT32 length); void T_LightningFlash(lightflash_t *flash); From eb590910b2ee7f1678c4699235d5f1076d5764a1 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 01:13:02 -0400 Subject: [PATCH 065/306] Added NIGHTSLINK bonus type for the 2.1 Link Bonus --- src/dehacked.c | 3 ++- src/y_inter.c | 10 +++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 70a19eadc..1f56210ac 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1197,8 +1197,9 @@ static void readlevelheader(MYFILE *f, INT32 num) else if (fastcmp(word2, "BOSS")) i = 1; else if (fastcmp(word2, "ERZ3")) i = 2; else if (fastcmp(word2, "NIGHTS")) i = 3; + else if (fastcmp(word2, "NIGHTSLINK")) i = 4; - if (i >= -1 && i <= 3) // -1 for no bonus. Max is 3. + if (i >= -1 && i <= 4) // -1 for no bonus. Max is 3. mapheaderinfo[num-1]->bonustype = (SINT8)i; else deh_warning("Level header %d: invalid bonus type number %d", num, i); diff --git a/src/y_inter.c b/src/y_inter.c index 3fdf5f7a9..2c77a577a 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1774,7 +1774,6 @@ static void Y_SetLapBonus(player_t *player, y_bonus_t *bstruct) bstruct->points = max(0, player->totalmarebonuslap * 1000); } -#if 0 // // Y_SetLinkBonus // @@ -1784,7 +1783,6 @@ static void Y_SetLinkBonus(player_t *player, y_bonus_t *bstruct) bstruct->display = true; bstruct->points = max(0, (player->maxlink - 1) * 100); } -#endif // // Y_SetGuardBonus @@ -1837,7 +1835,7 @@ static void Y_SetPerfectBonus(player_t *player, y_bonus_t *bstruct) // This list can be extended in the future with SOC/Lua, perhaps. typedef void (*bonus_f)(player_t *, y_bonus_t *); -bonus_f bonuses_list[5][4] = { +bonus_f bonuses_list[6][4] = { { Y_SetNullBonus, Y_SetNullBonus, @@ -1868,6 +1866,12 @@ bonus_f bonuses_list[5][4] = { Y_SetLapBonus, Y_SetNullBonus, }, + { + Y_SetNullBonus, + Y_SetLinkBonus, + Y_SetLapBonus, + Y_SetNullBonus, + }, }; From 3f4656e57ee2f97b6dc86e9e817eabc449cfb515 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 01:08:02 -0400 Subject: [PATCH 066/306] Polyobject Fade logic --- src/p_polyobj.c | 85 ++++++++++++++++++++++++++++++++++++++++++++----- src/p_polyobj.h | 17 ++++++++-- src/p_saveg.c | 22 ++++++++++++- src/p_spec.c | 22 ++++++++++--- 4 files changed, 129 insertions(+), 17 deletions(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index d943a0bfe..9e5cdf90e 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -2855,8 +2855,8 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata) void T_PolyObjFade(polyfade_t *th) { + boolean stillfading = false; polyobj_t *po = Polyobj_GetForNum(th->polyObjNum); - size_t i; if (!po) #ifdef RANGECHECK @@ -2873,7 +2873,67 @@ void T_PolyObjFade(polyfade_t *th) if (po->thinker == NULL) po->thinker = &th->thinker; - // \todo logic + stillfading = !(gametic - th->firsttic >= th->duration); + + if (gametic - th->firsttic >= th->duration) + { + po->translucency = th->destvalue; // set to dest translucency + + // remove thinker + if (po->thinker == &th->thinker) + po->thinker = NULL; + P_RemoveThinker(&th->thinker); + } + else if (!((gametic - th->firsttic) % th->interval)) + { + if (th->speed <= 0) + po->translucency = max(po->translucency + th->speed, th->destvalue); + else + po->translucency = min(po->translucency + th->speed, th->destvalue); + } + + if (!stillfading) + { + // set render flags + if (po->translucency >= NUMTRANSMAPS) // invisible + po->flags &= ~POF_RENDERALL; + else + po->flags |= POF_RENDERALL; + + // set collision + if (th->docollision && th->speed) + { + if (th->speed > 0) // faded out + { + po->flags &= ~POF_SOLID; + po->flags |= POF_NOSPECIALS; + } + else + { + po->flags |= POF_SOLID; + po->flags &= ~POF_NOSPECIALS; + } + } + } + else + { + po->flags |= POF_RENDERALL; + + // set collision + if (th->docollision && th->speed) + { + if (th->doghostfade) + { + po->flags &= ~POF_SOLID; + po->flags |= POF_NOSPECIALS; + } + else + { + po->flags |= POF_SOLID; + po->flags &= ~POF_NOSPECIALS; + } + } + } } INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata) @@ -2883,9 +2943,9 @@ INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata) polyfade_t *th; INT32 start; - if (!(po = Polyobj_GetForNum(prdata->polyObjNum))) + if (!(po = Polyobj_GetForNum(pfdata->polyObjNum))) { - CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjRotate: bad polyobj %d\n", prdata->polyObjNum); + CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjFade: bad polyobj %d\n", pfdata->polyObjNum); return 0; } @@ -2893,6 +2953,10 @@ INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata) if (po->isBad) return 0; + // already equal, nothing to do + if (po->translucency == pfdata->destvalue) + return 1; + // create a new thinker th = Z_Malloc(sizeof(polyfade_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyObjFade; @@ -2900,9 +2964,14 @@ INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata) po->thinker = &th->thinker; // set fields - th->polyObjNum = pfdata->tag; - - // \todo polyfade fields + th->polyObjNum = pfdata->polyObjNum; + th->destvalue = pfdata->destvalue; + th->docollision = pfdata->docollision; + th->doghostfade = pfdata->doghostfade; + th->duration = pfdata->duration; + th->speed = pfdata->speed; + th->interval = pfdata->interval; + th->firsttic = pfdata->firsttic; oldpo = po; @@ -2910,7 +2979,7 @@ INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata) start = 0; while ((po = Polyobj_GetChild(oldpo, &start))) { - pfdata->tag = po->id; + pfdata->polyObjNum = po->id; EV_DoPolyObjFade(pfdata); } diff --git a/src/p_polyobj.h b/src/p_polyobj.h index 0bd94a636..cf00d64ba 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -212,8 +212,13 @@ typedef struct polyfade_s thinker_t thinker; // must be first INT32 polyObjNum; - - // \todo polyfade fields + INT32 destvalue; + boolean docollision; + boolean doghostfade; + UINT32 duration; + INT32 speed; + UINT32 interval; + tic_t firsttic; } polyfade_t; // @@ -278,7 +283,13 @@ typedef struct polydisplacedata_s typedef struct polyfadedata_s { INT32 polyObjNum; - // \todo polyfadedata fields + INT32 destvalue; + boolean docollision; + boolean doghostfade; + UINT32 duration; + INT32 speed; + UINT32 interval; + tic_t firsttic; } polyfadedata_t; // diff --git a/src/p_saveg.c b/src/p_saveg.c index 3cc061ebb..fc9382233 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1700,6 +1700,20 @@ static void SavePolydisplaceThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, ht->oldHeights); } +static void SavePolyfadeThinker(const thinker_t *th, const UINT8 type) +{ + const polyfade_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEINT32(save_p, ht->polyObjNum); + WRITEINT32(save_p, ht->destvalue); + WRITEUINT8(save_p, (UINT8)ht->docollision); + WRITEUINT8(save_p, (UINT8)ht->doghostfade); + WRITEUINT32(save_p, ht->duration); + WRITEINT32(save_p, ht->speed); + WRITEUINT32(save_p, ht->interval); + WRITEUINT32(save_p, (UINT32)ht->firsttic); +} + #endif /* // @@ -2706,7 +2720,13 @@ static void LoadPolyfadeThinker(actionf_p1 thinker) polyfade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; ht->polyObjNum = READINT32(save_p); - // \todo polyfade thinker fields + ht->destvalue = READINT32(save_p); + ht->docollision = (boolean)READUINT8(save_p); + ht->doghostfade = (boolean)READUINT8(save_p); + ht->duration = READUINT32(save_p); + ht->speed = READINT32(save_p); + ht->interval = READUINT32(save_p); + ht->firsttic = (tic_t)READUINT32(save_p); P_AddThinker(&ht->thinker); } #endif diff --git a/src/p_spec.c b/src/p_spec.c index fd2c312fb..6d746f670 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1250,7 +1250,7 @@ static void PolyTranslucency(line_t *line) // // Makes a polyobject translucency fade and applies tangibility // -static void PolyFade(line_t *line) +static boolean PolyFade(line_t *line) { INT32 polyObjNum = line->tag; polyobj_t *po; @@ -1258,18 +1258,30 @@ static void PolyFade(line_t *line) if (!(po = Polyobj_GetForNum(polyObjNum))) { CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: bad polyobj %d\n", polyObjNum); - return; + return 0; } // don't allow line actions to affect bad polyobjects if (po->isBad) - return; + return 0; + + // already equal, nothing to do + if (po->translucency == max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), 0)) + return 1; polyfadedata_t pfd; - pfd.polyObjNum = line->tag; + pfd.polyObjNum = polyObjNum; + pfd.destvalue = max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), 0); + pfd.docollision = !(line->flags & ML_BOUNCY), // do not handle collision flags + pfd.doghostfade = (line->flags & ML_EFFECT1), // do ghost fade (no collision flags during fade) - // \todo polyfadedata fields + pfd.duration = abs(sides[line->sidenum[0]].rowoffset>>FRACBITS); + pfd.speed = FixedFloor(FixedDiv(pfd.destvalue - po->translucency, pfd.duration))/FRACUNIT; + if (!pfd.speed) + pfd.speed = (pfd.destvalue < po->translucency) ? -1 : 1; + pfd.interval = max(FixedFloor(FixedDiv(pfd.duration, abs(pfd.destvalue - po->translucency)))/FRACUNIT, 1); + pfd.firsttic = gametic; return EV_DoPolyObjFade(&pfd); } From 5032f783d783fefacbe694dc120065bb22e20f13 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 08:10:45 -0400 Subject: [PATCH 067/306] Don't add a thinker if alpha is already equal --- src/p_spec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/p_spec.c b/src/p_spec.c index a1465b0e7..d33ad873c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7706,6 +7706,10 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor INT16 destvalue, INT16 speed, boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha) { + // already equal, nothing to do + if (rover->alpha == max(1, min(256, destvalue))) + return; + fade_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); d->thinker.function.acp1 = (actionf_p1)T_Fade; From 675f69afea115c284383dde25d54fac17b9c81c8 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 09:29:18 -0400 Subject: [PATCH 068/306] Flag re-organization * Change alternate param flag from BLOCKMONSTERS to DONTPEGBOTTOM * Change tic-based flag from NOCLIMB to EFFECT5 --- src/p_spec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 707e19f08..87f5676bb 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2779,9 +2779,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 420: // Fade light levels in tagged sectors to new value P_FadeLight(line->tag, - (line->flags & ML_BLOCKMONSTERS) ? max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 255), 0) : line->frontsector->lightlevel, - (line->flags & ML_BLOCKMONSTERS) ? max(sides[line->sidenum[0]].rowoffset>>FRACBITS, 0) : P_AproxDistance(line->dx, line->dy)>>FRACBITS, - (line->flags & ML_NOCLIMB), + (line->flags & ML_DONTPEGBOTTOM) ? max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 255), 0) : line->frontsector->lightlevel, + (line->flags & ML_DONTPEGBOTTOM) ? max(sides[line->sidenum[0]].rowoffset>>FRACBITS, 0) : P_AproxDistance(line->dx, line->dy)>>FRACBITS, + (line->flags & ML_EFFECT5), (line->flags & ML_TFERLINE)); break; From baababcf0b7646d00696780b3d80879528617462 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 12:44:35 -0400 Subject: [PATCH 069/306] Add spawn_lightlevel to sector_t --- src/p_setup.c | 1 + src/r_defs.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/p_setup.c b/src/p_setup.c index 2361d1efd..0119e6584 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -678,6 +678,7 @@ static void P_LoadRawSectors(UINT8 *data, size_t i) ss->ceilingpic = P_AddLevelFlat(ms->ceilingpic, foundflats); ss->lightlevel = SHORT(ms->lightlevel); + ss->spawn_lightlevel = SHORT(ms->lightlevel); ss->special = SHORT(ms->special); ss->tag = SHORT(ms->tag); ss->nexttag = ss->firsttag = -1; diff --git a/src/r_defs.h b/src/r_defs.h index ea5db3947..65f8ee5c6 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -385,6 +385,9 @@ typedef struct sector_s boolean hasslope; // The sector, or one of its visible FOFs, contains a slope #endif + // for fade thinker + INT16 spawn_lightlevel; + // these are saved for netgames, so do not let Lua touch these! INT32 spawn_nexttag, spawn_firsttag; // the actual nexttag/firsttag values may differ if the sector's tag was changed From aeb45132c5d86e64a641f3311fff7f70e163af36 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 13:43:00 -0400 Subject: [PATCH 070/306] Revert "Snap light level to software values (32 levels)" This reverts commit cc26d03c93c91d6209b2b51acc63758c837b2cf4. --- src/lua_baselib.c | 3 +- src/p_lights.c | 79 +++++++++++++++++------------------------------ src/p_saveg.c | 4 --- src/p_spec.c | 3 +- src/p_spec.h | 8 ++--- 5 files changed, 32 insertions(+), 65 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 74b842e2a..840863eb0 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1810,10 +1810,9 @@ static int lib_pFadeLight(lua_State *L) INT32 destvalue = (INT32)luaL_checkinteger(L, 2); INT32 speed = (INT32)luaL_checkinteger(L, 3); boolean ticbased = lua_optboolean(L, 4); - boolean exactlightlevel = lua_optboolean(L, 5); NOHUD INLEVEL - P_FadeLight(tag, destvalue, speed, ticbased, exactlightlevel); + P_FadeLight(tag, destvalue, speed, ticbased); return 0; } diff --git a/src/p_lights.c b/src/p_lights.c index b2934b792..8be3d793c 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -15,7 +15,6 @@ #include "doomdef.h" #include "doomstat.h" // gametic #include "p_local.h" -#include "r_main.h" // LIGHTSEGSHIFT #include "r_state.h" #include "z_zone.h" #include "m_random.h" @@ -332,10 +331,9 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, * \param speed Speed of the fade; the change to the ligh * level in each sector per tic. * \param ticbased Use a specific duration for the fade, defined by speed - * \param exactlightlevel Do not snap to software values (for OpenGL) * \sa T_LightFade */ -void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ticbased, boolean exactlightlevel) +void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ticbased) { lightlevel_t *ll; @@ -355,8 +353,6 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ll->sector = sector; ll->destlevel = destvalue; - ll->exactlightlevel = exactlightlevel; - ll->lightlevel = sector->lightlevel; if (ticbased) { @@ -374,12 +370,12 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean } } -void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean exactlightlevel) +void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased) { INT32 i; // search all sectors for ones with tag for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0 ;) - P_FadeLightBySector(§ors[i], destvalue, speed, ticbased, exactlightlevel); + P_FadeLightBySector(§ors[i], destvalue, speed, ticbased); } /** Fades the light level in a sector to a new value. @@ -389,66 +385,47 @@ void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, bool */ void T_LightFade(lightlevel_t *ll) { - boolean stillfading = false; - INT16 lightlevel = ll->lightlevel; - if (ll->duration >= 0) // tic-based { - stillfading = !(gametic - ll->firsttic >= ll->duration); if (gametic - ll->firsttic >= ll->duration) { - lightlevel = (INT16)ll->destlevel; // set to dest lightlevel + ll->sector->lightlevel = (INT16)ll->destlevel; // set to dest lightlevel P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker } else if (!((gametic - ll->firsttic) % ll->interval)) { if (ll->speed < 0) - lightlevel = max(lightlevel + (INT16)ll->speed, (INT16)ll->destlevel); + ll->sector->lightlevel = max(ll->sector->lightlevel + (INT16)ll->speed, (INT16)ll->destlevel); else - lightlevel = min(lightlevel + (INT16)ll->speed, (INT16)ll->destlevel); + ll->sector->lightlevel = min(ll->sector->lightlevel + (INT16)ll->speed, (INT16)ll->destlevel); } + return; } - else // x/tic speed-based - { - if (lightlevel < ll->destlevel) - { - // increase the lightlevel - if (lightlevel + ll->speed >= ll->destlevel) - { - // stop changing light level - lightlevel = (INT16)ll->destlevel; // set to dest lightlevel - P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker - } - else - { - stillfading = true; - lightlevel = (INT16)(lightlevel + (INT16)ll->speed); // move lightlevel - } + if (ll->sector->lightlevel < ll->destlevel) + { + // increase the lightlevel + if (ll->sector->lightlevel + ll->speed >= ll->destlevel) + { + // stop changing light level + ll->sector->lightlevel = (INT16)ll->destlevel; // set to dest lightlevel + + P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker } else - { - // decrease lightlevel - if (lightlevel - ll->speed <= ll->destlevel) - { - // stop changing light level - lightlevel = (INT16)ll->destlevel; // set to dest lightlevel - - P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker - } - else - { - stillfading = true; - lightlevel = (INT16)(lightlevel - (INT16)ll->speed); // move lightlevel - } - } + ll->sector->lightlevel = (INT16)(ll->sector->lightlevel + (INT16)ll->speed); // move lightlevel } - - // Snap light level to software values - if (!stillfading || ll->exactlightlevel) - ll->sector->lightlevel = lightlevel; else - ll->sector->lightlevel = (lightlevel >> LIGHTSEGSHIFT) << LIGHTSEGSHIFT; + { + // decrease lightlevel + if (ll->sector->lightlevel - ll->speed <= ll->destlevel) + { + // stop changing light level + ll->sector->lightlevel = (INT16)ll->destlevel; // set to dest lightlevel - ll->lightlevel = lightlevel; + P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker + } + else + ll->sector->lightlevel = (INT16)(ll->sector->lightlevel - (INT16)ll->speed); // move lightlevel + } } diff --git a/src/p_saveg.c b/src/p_saveg.c index 95d073fc9..8ec5b5ea8 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1542,8 +1542,6 @@ static void SaveLightlevelThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->duration); WRITEUINT32(save_p, ht->interval); WRITEUINT32(save_p, (UINT32)ht->firsttic); - WRITEUINT8(save_p, (UINT8)ht->exactlightlevel); - WRITEINT16(save_p, ht->lightlevel); } // @@ -2520,8 +2518,6 @@ static inline void LoadLightlevelThinker(actionf_p1 thinker) ht->duration = READINT32(save_p); ht->interval = READUINT32(save_p); ht->firsttic = (tic_t)READUINT32(save_p); - ht->exactlightlevel = (boolean)READUINT8(save_p); - ht->lightlevel = READINT16(save_p); if (ht->sector) ht->sector->lightingdata = ht; P_AddThinker(&ht->thinker); diff --git a/src/p_spec.c b/src/p_spec.c index 87f5676bb..917ad68d4 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2781,8 +2781,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_FadeLight(line->tag, (line->flags & ML_DONTPEGBOTTOM) ? max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 255), 0) : line->frontsector->lightlevel, (line->flags & ML_DONTPEGBOTTOM) ? max(sides[line->sidenum[0]].rowoffset>>FRACBITS, 0) : P_AproxDistance(line->dx, line->dy)>>FRACBITS, - (line->flags & ML_EFFECT5), - (line->flags & ML_TFERLINE)); + (line->flags & ML_EFFECT5)); break; case 421: // Stop lighting effect in tagged sectors diff --git a/src/p_spec.h b/src/p_spec.h index b354e6772..c2c4c8976 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -143,10 +143,6 @@ typedef struct INT32 duration; ///< If <0, do not use tic-based behavior. If 0, set instantly. If >0, fade lasts this duration. UINT32 interval; ///< Interval to deduct light level tic_t firsttic; ///< First gametic to count from - - // Snap to software values - boolean exactlightlevel; ///< Use exact values for OpenGL - INT16 lightlevel; ///< Internal counter for fading } lightlevel_t; #define GLOWSPEED 8 @@ -165,8 +161,8 @@ strobe_t * P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector void T_Glow(glow_t *g); glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, INT32 length); -void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ticbased, boolean exactlightlevel); -void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean exactlightlevel); +void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ticbased); +void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased); void T_LightFade(lightlevel_t *ll); typedef enum From 368f96e6058aa57b41c7beae0db1821a22f15cea Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 15:41:30 -0400 Subject: [PATCH 071/306] Fade FOF lighting fixes; properly calculate destlightvalue --- src/p_spec.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index d4b60c70c..5c171c3d6 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3358,8 +3358,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) destvalue, speed, !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT - !(line->flags & ML_BOUNCY), // do not handle interactive flags !(line->flags & ML_EFFECT2), // do not handle lighting + !(line->flags & ML_BOUNCY), // do not handle interactive flags (line->flags & ML_EFFECT1), // do ghost fade (no interactive flags during fade) (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) else @@ -3369,8 +3369,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) destvalue, 0, // set alpha immediately !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT - !(line->flags & ML_BOUNCY), // do not handle interactive flags !(line->flags & ML_EFFECT2), // do not handle lighting + !(line->flags & ML_BOUNCY), // do not handle interactive flags (line->flags & ML_EFFECT1), // do ghost fade (no interactive flags during fade) (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) } @@ -7453,10 +7453,7 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz rover->alpha = fadingdata->alpha; if (fadingdata->dolighting) - { P_RemoveLighting(§ors[rover->secnum]); - §ors[rover->secnum].lightlevel = rover->target->lightlevel; // \todo get fade light level destvalue - } P_RemoveThinker(&fadingdata->thinker); } @@ -7697,6 +7694,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, * \param speed speed to fade by * \param doexists handle FF_EXISTS * \param dotranslucent handle FF_TRANSLUCENT + * \param dolighting fade FOF light * \param docollision handle interactive flags * \param doghostfade no interactive flags during fading * \param exactalpha use exact alpha values (opengl) @@ -7740,10 +7738,24 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor // Set a separate thinker for shadow fading if (dolighting && !(rover->flags & FF_NOSHADE)) + { + UINT16 lightdelta = abs(sectors[rover->secnum].spawn_lightlevel - rover->target->lightlevel); + fixed_t alphapercent = FixedDiv(d->destvalue, rover->spawnalpha); + fixed_t adjustedlightdelta = FixedMul(lightdelta, alphapercent); + INT16 destlightvalue; + + if (rover->target->lightlevel >= sectors[rover->secnum].spawn_lightlevel) // fading out, get lighter + destlightvalue = rover->target->lightlevel - adjustedlightdelta; + else // fading in, get darker + destlightvalue = rover->target->lightlevel + adjustedlightdelta; + + //CONS_Printf("%d| LightDelta %d> AlphaPct %d> AdjLiDel %d> DestLight %d\n", gametic, lightdelta, FixedMul(alphapercent, 100), adjustedlightdelta, destlightvalue); + P_FadeLightBySector(§ors[rover->secnum], - rover->target->lightlevel, // (shadowlight - targetlight) * destvalue/256 // \todo get fade light level destvalue + destlightvalue, FixedFloor(FixedDiv(abs(d->destvalue - d->alpha), d->speed))/FRACUNIT, - true, exactalpha); + true); + } P_AddThinker(&d->thinker); } From 80a4a03f8e253f672a4651b4e556e609571b1944 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 17:19:49 -0400 Subject: [PATCH 072/306] Finalize light level on fade finish (not forced stop) * Added destlightlevel property to fade_t * Fixed dotranslucent, dolighting, docollision order weirdness in function calls --- src/p_saveg.c | 6 ++++-- src/p_spec.c | 35 ++++++++++++++++++++--------------- src/p_spec.h | 3 ++- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index be0363d05..334279a9a 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1591,11 +1591,12 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->ffloornum); WRITEINT32(save_p, ht->alpha); WRITEINT16(save_p, ht->destvalue); + WRITEINT16(save_p, ht->destlightlevel); WRITEINT16(save_p, ht->speed); WRITEUINT8(save_p, ht->doexists); WRITEUINT8(save_p, ht->dotranslucent); - WRITEUINT8(save_p, ht->docollision); WRITEUINT8(save_p, ht->dolighting); + WRITEUINT8(save_p, ht->docollision); WRITEUINT8(save_p, ht->doghostfade); WRITEUINT8(save_p, ht->exactalpha); } @@ -2599,11 +2600,12 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->ffloornum = READINT32(save_p); ht->alpha = READINT32(save_p); ht->destvalue = READINT16(save_p); + ht->destlightlevel = READINT16(save_p); ht->speed = READINT16(save_p); ht->doexists = READUINT8(save_p); ht->dotranslucent = READUINT8(save_p); - ht->docollision = READUINT8(save_p); ht->dolighting = READUINT8(save_p); + ht->docollision = READUINT8(save_p); ht->doghostfade = READUINT8(save_p); ht->exactalpha = READUINT8(save_p); diff --git a/src/p_spec.c b/src/p_spec.c index 5c171c3d6..d291d1e3b 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -106,10 +106,10 @@ static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t o static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize); #define P_RemoveFakeFloorFader(l) P_ResetFakeFloorFader(l, NULL, false); static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, - boolean doexists, boolean dotranslucent, boolean docollision, boolean dolighting, boolean doghostfade, boolean exactalpha); + boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha); static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, INT16 destvalue, INT16 speed, - boolean doexists, boolean dotranslucent, boolean docollision, boolean dolighting, boolean doghostfade, boolean exactalpha); + boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); @@ -3359,8 +3359,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT !(line->flags & ML_EFFECT2), // do not handle lighting - !(line->flags & ML_BOUNCY), // do not handle interactive flags - (line->flags & ML_EFFECT1), // do ghost fade (no interactive flags during fade) + !(line->flags & ML_BOUNCY), // do not handle collision + (line->flags & ML_EFFECT1), // do ghost fade (no collision during fade) (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) else { @@ -3370,8 +3370,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT !(line->flags & ML_EFFECT2), // do not handle lighting - !(line->flags & ML_BOUNCY), // do not handle interactive flags - (line->flags & ML_EFFECT1), // do ghost fade (no interactive flags during fade) + !(line->flags & ML_BOUNCY), // do not handle collision + (line->flags & ML_EFFECT1), // do ghost fade (no collision during fade) (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) } } @@ -7463,7 +7463,7 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz } static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, - boolean doexists, boolean dotranslucent, boolean docollision, boolean dolighting, boolean doghostfade, boolean exactalpha) + boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha) { boolean stillfading = false; INT32 alpha; @@ -7728,8 +7728,8 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor d->speed = max(1, speed); // minimum speed 1/tic // if speed < 1, alpha is set immediately in thinker d->doexists = doexists; d->dotranslucent = dotranslucent; - d->docollision = docollision; d->dolighting = dolighting; + d->docollision = docollision; d->doghostfade = doghostfade; d->exactalpha = exactalpha; @@ -7742,20 +7742,19 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor UINT16 lightdelta = abs(sectors[rover->secnum].spawn_lightlevel - rover->target->lightlevel); fixed_t alphapercent = FixedDiv(d->destvalue, rover->spawnalpha); fixed_t adjustedlightdelta = FixedMul(lightdelta, alphapercent); - INT16 destlightvalue; if (rover->target->lightlevel >= sectors[rover->secnum].spawn_lightlevel) // fading out, get lighter - destlightvalue = rover->target->lightlevel - adjustedlightdelta; + d->destlightlevel = rover->target->lightlevel - adjustedlightdelta; else // fading in, get darker - destlightvalue = rover->target->lightlevel + adjustedlightdelta; - - //CONS_Printf("%d| LightDelta %d> AlphaPct %d> AdjLiDel %d> DestLight %d\n", gametic, lightdelta, FixedMul(alphapercent, 100), adjustedlightdelta, destlightvalue); + d->destlightlevel = rover->target->lightlevel + adjustedlightdelta; P_FadeLightBySector(§ors[rover->secnum], - destlightvalue, + d->destlightlevel, FixedFloor(FixedDiv(abs(d->destvalue - d->alpha), d->speed))/FRACUNIT, true); } + else + d->destlightlevel = -1; P_AddThinker(&d->thinker); } @@ -7767,8 +7766,14 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor */ void T_Fade(fade_t *d) { - if (d->rover && !P_FadeFakeFloor(d->rover, d->destvalue, d->speed, d->doexists, d->dotranslucent, d->docollision, d->dolighting, d->doghostfade, d->exactalpha)) + if (d->rover && !P_FadeFakeFloor(d->rover, d->destvalue, d->speed, d->doexists, d->dotranslucent, d->dolighting, d->docollision, d->doghostfade, d->exactalpha)) + { + // Finalize lighting, copypasta from P_AddFakeFloorFader + if (d->dolighting && !(d->rover->flags & FF_NOSHADE) && d->destlightlevel > -1) + sectors[d->rover->secnum].lightlevel = d->destlightlevel; + P_RemoveFakeFloorFader(d->rover); + } } /* diff --git a/src/p_spec.h b/src/p_spec.h index aefb024af..461ae876b 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -470,11 +470,12 @@ typedef struct INT32 ffloornum; ///< Number of ffloor of target sector INT32 alpha; ///< Internal alpha counter INT16 destvalue; ///< Transparency value to fade to + INT16 destlightlevel; ///< Light level to fade to INT16 speed; ///< Speed to fade by boolean doexists; ///< Handle FF_EXISTS boolean dotranslucent; ///< Handle FF_TRANSLUCENT - boolean docollision; ///< Handle interactive flags boolean dolighting; ///< Handle shadows and light blocks + boolean docollision; ///< Handle interactive flags boolean doghostfade; ///< No interactive flags during fading boolean exactalpha; ///< Use exact alpha values (opengl) } fade_t; From c0bf79ad8e8230bb315035f6be7d93d137d3d176 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 9 Sep 2018 22:48:09 +0100 Subject: [PATCH 073/306] R_CreateColormap2 and R_MakeColormaps have been made obsolete, it's just R_CreateColormap now, like it used to be! With that, I moved R_CreateColormap2's exclusive software colormap malloc code to R_CreateColormap, and merged the two software-only blocks of code into one. I also disabled any unneeded variables and fixed a preprocessor-related goofup --- src/p_setup.c | 2 +- src/r_data.c | 88 +++++++++++++++++++++++++++++++++++++++------------ src/r_data.h | 4 +-- 3 files changed, 71 insertions(+), 23 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index d8c913e0f..58170e262 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2673,7 +2673,7 @@ boolean P_SetupLevel(boolean skipprecip) P_CreateBlockMap(); // Graue 02-29-2004 P_LoadSideDefs2(lastloadedmaplumpnum + ML_SIDEDEFS); - R_MakeColormaps(); + //R_MakeColormaps(); P_LoadLineDefs2(); P_LoadSubsectors(lastloadedmaplumpnum + ML_SSECTORS); P_LoadNodes(lastloadedmaplumpnum + ML_NODES); diff --git a/src/r_data.c b/src/r_data.c index e1d4b8935..2551a2946 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1038,8 +1038,8 @@ void R_ReInitColormaps(UINT16 num) static lumpnum_t foundcolormaps[MAXCOLORMAPS]; -static char colormapFixingArray[MAXCOLORMAPS][3][9]; -static size_t carrayindex; +//static char colormapFixingArray[MAXCOLORMAPS][3][9]; +//static size_t carrayindex; // // R_ClearColormaps @@ -1052,7 +1052,7 @@ void R_ClearColormaps(void) num_extra_colormaps = 0; - carrayindex = 0; + //carrayindex = 0; for (i = 0; i < MAXCOLORMAPS; i++) foundcolormaps[i] = LUMPERROR; @@ -1110,7 +1110,7 @@ static int RoundUp(double number); INT32 R_CreateColormap(char *p1, char *p2, char *p3) { double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb; - double r, g, b, cbrightness, maskamt = 0, othermask = 0; + double maskamt = 0, othermask = 0; int mask, fog = 0; size_t mapnum = num_extra_colormaps; size_t i; @@ -1163,7 +1163,7 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) fadedist = fadeend - fadestart; fog = NUMFROMCHAR(p2[1]); } -#undef getnum +#undef NUMFROMCHAR if (p3[0] == '#') { @@ -1194,14 +1194,35 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) if (num_extra_colormaps == MAXCOLORMAPS) I_Error("R_CreateColormap: Too many colormaps! the limit is %d\n", MAXCOLORMAPS); - strncpy(colormapFixingArray[num_extra_colormaps][0], p1, 8); - strncpy(colormapFixingArray[num_extra_colormaps][1], p2, 8); - strncpy(colormapFixingArray[num_extra_colormaps][2], p3, 8); + //strncpy(colormapFixingArray[num_extra_colormaps][0], p1, 8); + //strncpy(colormapFixingArray[num_extra_colormaps][1], p2, 8); + //strncpy(colormapFixingArray[num_extra_colormaps][2], p3, 8); num_extra_colormaps++; + foundcolormaps[mapnum] = LUMPERROR; + + // aligned on 8 bit for asm code + extra_colormaps[mapnum].colormap = NULL; + extra_colormaps[mapnum].maskcolor = (UINT16)maskcolor; + extra_colormaps[mapnum].fadecolor = (UINT16)fadecolor; + extra_colormaps[mapnum].maskamt = maskamt; + extra_colormaps[mapnum].fadestart = (UINT16)fadestart; + extra_colormaps[mapnum].fadeend = (UINT16)fadeend; + extra_colormaps[mapnum].fog = fog; + + // This code creates the colormap array used by software renderer if (rendermode == render_soft) { + double r, g, b, cbrightness; + int p; + char *colormap_p; + + // Initialise the map and delta arrays + // map[i] stores an RGB color (as double) for index i, + // which is then converted to SRB2's palette later + // deltas[i] stores a corresponding fade delta between the RGB color and the final fade color; + // map[i]'s values are decremented by after each use for (i = 0; i < 256; i++) { r = pLocalPalette[i].s.red; @@ -1224,22 +1245,48 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) map[i][2] = 255.0l; deltas[i][2] = (map[i][2] - cdestb) / (double)fadedist; } + + // Now allocate memory for the actual colormap array itself! + colormap_p = Z_MallocAlign((256 * 34) + 10, PU_LEVEL, NULL, 8); + extra_colormaps[mapnum].colormap = (UINT8 *)colormap_p; + + // Calculate the palette index for each palette index, for each light level + // (as well as the two unused colormap lines we inherited from Doom) + for (p = 0; p < 34; p++) + { + for (i = 0; i < 256; i++) + { + *colormap_p = NearestColor((UINT8)RoundUp(map[i][0]), + (UINT8)RoundUp(map[i][1]), + (UINT8)RoundUp(map[i][2])); + colormap_p++; + + if ((UINT32)p < fadestart) + continue; +#define ABS2(x) ((x) < 0 ? -(x) : (x)) + if (ABS2(map[i][0] - cdestr) > ABS2(deltas[i][0])) + map[i][0] -= deltas[i][0]; + else + map[i][0] = cdestr; + + if (ABS2(map[i][1] - cdestg) > ABS2(deltas[i][1])) + map[i][1] -= deltas[i][1]; + else + map[i][1] = cdestg; + + if (ABS2(map[i][2] - cdestb) > ABS2(deltas[i][1])) + map[i][2] -= deltas[i][2]; + else + map[i][2] = cdestb; +#undef ABS2 + } + } } - foundcolormaps[mapnum] = LUMPERROR; - - // aligned on 8 bit for asm code - extra_colormaps[mapnum].colormap = NULL; - extra_colormaps[mapnum].maskcolor = (UINT16)maskcolor; - extra_colormaps[mapnum].fadecolor = (UINT16)fadecolor; - extra_colormaps[mapnum].maskamt = maskamt; - extra_colormaps[mapnum].fadestart = (UINT16)fadestart; - extra_colormaps[mapnum].fadeend = (UINT16)fadeend; - extra_colormaps[mapnum].fog = fog; - return (INT32)mapnum; } +/* void R_MakeColormaps(void) { size_t i; @@ -1310,7 +1357,7 @@ void R_CreateColormap2(char *p1, char *p2, char *p3) fadedist = fadeend - fadestart; fog = NUMFROMCHAR(p2[1]); } -#undef getnum +#undef NUMFROMCHAR if (p3[0] == '#') { @@ -1419,6 +1466,7 @@ void R_CreateColormap2(char *p1, char *p2, char *p3) return; } +*/ // Thanks to quake2 source! // utils3/qdata/images.c diff --git a/src/r_data.h b/src/r_data.h index 1e9e0eb5e..c1f2a73da 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -93,8 +93,8 @@ void R_ReInitColormaps(UINT16 num); void R_ClearColormaps(void); INT32 R_ColormapNumForName(char *name); INT32 R_CreateColormap(char *p1, char *p2, char *p3); -void R_CreateColormap2(char *p1, char *p2, char *p3); -void R_MakeColormaps(void); +//void R_CreateColormap2(char *p1, char *p2, char *p3); +//void R_MakeColormaps(void); const char *R_ColormapNameForNum(INT32 num); extern INT32 numtextures; From c3c4a251f1d547d430c8551d2a7cecf5af6f9db0 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 19:31:32 -0400 Subject: [PATCH 074/306] Added tic-based logic to FOF fade (ML_EFFECT5) --- src/p_saveg.c | 6 ++++++ src/p_spec.c | 53 ++++++++++++++++++++++++++++++++++++++++----------- src/p_spec.h | 3 +++ 3 files changed, 51 insertions(+), 11 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 334279a9a..162241573 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1593,6 +1593,9 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type) WRITEINT16(save_p, ht->destvalue); WRITEINT16(save_p, ht->destlightlevel); WRITEINT16(save_p, ht->speed); + WRITEINT32(save_p, ht->duration); + WRITEUINT32(save_p, ht->interval); + WRITEUINT32(save_p, (UINT32)ht->firsttic); WRITEUINT8(save_p, ht->doexists); WRITEUINT8(save_p, ht->dotranslucent); WRITEUINT8(save_p, ht->dolighting); @@ -2602,6 +2605,9 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->destvalue = READINT16(save_p); ht->destlightlevel = READINT16(save_p); ht->speed = READINT16(save_p); + ht->duration = READINT32(save_p); + ht->interval = READUINT32(save_p); + ht->firsttic = (tic_t)READUINT32(save_p); ht->doexists = READUINT8(save_p); ht->dotranslucent = READUINT8(save_p); ht->dolighting = READUINT8(save_p); diff --git a/src/p_spec.c b/src/p_spec.c index d291d1e3b..8d1f4f295 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -105,10 +105,10 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t * static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize); #define P_RemoveFakeFloorFader(l) P_ResetFakeFloorFader(l, NULL, false); -static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, +static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, INT32 duration, UINT32 interval, tic_t firsttic, boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha); static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, - INT16 destvalue, INT16 speed, + INT16 destvalue, INT16 speed, boolean ticbased, boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); @@ -3356,6 +3356,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (speed > 0) P_AddFakeFloorFader(rover, secnum, j, destvalue, speed, + (line->flags & ML_EFFECT5), // tic-based logic !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT !(line->flags & ML_EFFECT2), // do not handle lighting @@ -3367,6 +3368,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_RemoveFakeFloorFader(rover); P_FadeFakeFloor(rover, destvalue, 0, // set alpha immediately + -1, 0, 0, // tic-based logic !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT !(line->flags & ML_EFFECT2), // do not handle lighting @@ -7444,6 +7446,9 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz fadingdata->alpha - 1 : // trigger fade-out finish fadingdata->alpha + 1, // trigger fade-in finish 0, + fadingdata->duration, + fadingdata->interval, + fadingdata->firsttic, fadingdata->doexists, fadingdata->dotranslucent, fadingdata->docollision, @@ -7462,9 +7467,10 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz } } -static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, +static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, INT32 duration, UINT32 interval, tic_t firsttic, boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha) { + boolean ticbased = (duration > -1); boolean stillfading = false; INT32 alpha; fade_t *fadingdata = (fade_t *)rover->fadingdata; @@ -7492,7 +7498,8 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, else if (alpha > destvalue) // fade out { // finish fading out - if (speed < 1 || alpha - speed <= destvalue + speed) + if (speed < 1 || (!ticbased && alpha - speed <= destvalue + speed) || + (ticbased && (gametic - firsttic >= duration || alpha <= destvalue))) { alpha = destvalue; @@ -7512,14 +7519,18 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, } else // continue fading out { - alpha -= speed; + if (!ticbased) + alpha -= speed; + else if (ticbased && !((gametic - firsttic) % interval)) + alpha = max(alpha - speed, destvalue); stillfading = true; } } else // fade in { // finish fading in - if (speed < 1 || alpha + speed >= destvalue - speed) + if (speed < 1 || (!ticbased && alpha + speed >= destvalue - speed) || + (ticbased && (gametic - firsttic >= duration || alpha >= destvalue))) { alpha = destvalue; @@ -7539,7 +7550,10 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, } else // continue fading in { - alpha += speed; + if (!ticbased) + alpha += speed; + else if (ticbased && !((gametic - firsttic) % interval)) + alpha = min(alpha + speed, destvalue); stillfading = true; } } @@ -7692,6 +7706,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, * * \param destvalue transparency value to fade to * \param speed speed to fade by + * \param ticbased tic-based logic, speed = duration * \param doexists handle FF_EXISTS * \param dotranslucent handle FF_TRANSLUCENT * \param dolighting fade FOF light @@ -7700,7 +7715,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, * \param exactalpha use exact alpha values (opengl) */ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, - INT16 destvalue, INT16 speed, + INT16 destvalue, INT16 speed, boolean ticbased, boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha) { // already equal, nothing to do @@ -7725,7 +7740,21 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor d->alpha = rover->alpha; d->destvalue = max(1, min(256, destvalue)); // ffloor->alpha is 1-256 - d->speed = max(1, speed); // minimum speed 1/tic // if speed < 1, alpha is set immediately in thinker + + if (ticbased) + { + d->duration = abs(speed); + d->speed = max(abs(FixedFloor(FixedDiv(d->destvalue - d->alpha, d->duration))/FRACUNIT), 1); + d->interval = max(FixedFloor(FixedDiv(d->duration, abs(d->destvalue - d->alpha)))/FRACUNIT, 1); + d->firsttic = gametic; + } + else + { + d->speed = max(1, speed); // minimum speed 1/tic // if speed < 1, alpha is set immediately in thinker + d->duration = -1; + d->interval = d->firsttic = 0; + } + d->doexists = doexists; d->dotranslucent = dotranslucent; d->dolighting = dolighting; @@ -7750,7 +7779,8 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor P_FadeLightBySector(§ors[rover->secnum], d->destlightlevel, - FixedFloor(FixedDiv(abs(d->destvalue - d->alpha), d->speed))/FRACUNIT, + ticbased ? d->duration : + FixedFloor(FixedDiv(abs(d->destvalue - d->alpha), d->speed))/FRACUNIT, true); } else @@ -7766,7 +7796,8 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor */ void T_Fade(fade_t *d) { - if (d->rover && !P_FadeFakeFloor(d->rover, d->destvalue, d->speed, d->doexists, d->dotranslucent, d->dolighting, d->docollision, d->doghostfade, d->exactalpha)) + if (d->rover && !P_FadeFakeFloor(d->rover, d->destvalue, d->speed, d->duration, d->interval, d->firsttic, + d->doexists, d->dotranslucent, d->dolighting, d->docollision, d->doghostfade, d->exactalpha)) { // Finalize lighting, copypasta from P_AddFakeFloorFader if (d->dolighting && !(d->rover->flags & FF_NOSHADE) && d->destlightlevel > -1) diff --git a/src/p_spec.h b/src/p_spec.h index 461ae876b..93d113be3 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -472,6 +472,9 @@ typedef struct INT16 destvalue; ///< Transparency value to fade to INT16 destlightlevel; ///< Light level to fade to INT16 speed; ///< Speed to fade by + INT32 duration; ///< Duration for tic-based logic, > -1 means use tic-based + UINT32 interval; ///< Skip interval for tic-based logic + tic_t firsttic; ///< First tic for tic-based logic boolean doexists; ///< Handle FF_EXISTS boolean dotranslucent; ///< Handle FF_TRANSLUCENT boolean dolighting; ///< Handle shadows and light blocks From 43ae628adc746bcb8d11dbe4d4f383d79cff076e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 19:44:35 -0400 Subject: [PATCH 075/306] Cap lightlevel fading at spawn_lightlevel (don't make darker) --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 8d1f4f295..de61064fd 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7769,7 +7769,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor if (dolighting && !(rover->flags & FF_NOSHADE)) { UINT16 lightdelta = abs(sectors[rover->secnum].spawn_lightlevel - rover->target->lightlevel); - fixed_t alphapercent = FixedDiv(d->destvalue, rover->spawnalpha); + fixed_t alphapercent = min(FixedDiv(d->destvalue, rover->spawnalpha), 1*FRACUNIT); // don't make darker than spawn_lightlevel fixed_t adjustedlightdelta = FixedMul(lightdelta, alphapercent); if (rover->target->lightlevel >= sectors[rover->secnum].spawn_lightlevel) // fading out, get lighter From ea2276eb07539f2d3369233eb02030d66ff6ab37 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 19:57:41 -0400 Subject: [PATCH 076/306] Fix tic-based bug returning early --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index de61064fd..8b5b0c1c4 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7493,7 +7493,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, IN alpha = rover->alpha; // routines specific to fade in and fade out - if (alpha == destvalue) + if (!ticbased && alpha == destvalue) return stillfading; else if (alpha > destvalue) // fade out { From 3d5f225702bbb9cae9a52ec00ff1a32304d8eb71 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 20:18:43 -0400 Subject: [PATCH 077/306] Replace firsttic with decrement timer --- src/p_lights.c | 16 ++++++++-------- src/p_saveg.c | 8 ++++---- src/p_spec.h | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/p_lights.c b/src/p_lights.c index 8be3d793c..77d05dad3 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -356,16 +356,16 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean if (ticbased) { - ll->duration = abs(speed); - ll->speed = FixedFloor(FixedDiv(destvalue - sector->lightlevel, ll->duration))/FRACUNIT; + ll->ticbased = ticbased; + ll->timer = abs(speed); + ll->speed = FixedFloor(FixedDiv(destvalue - sector->lightlevel, ll->timer))/FRACUNIT; if (!ll->speed) ll->speed = (destvalue < sector->lightlevel) ? -1 : 1; - ll->interval = max(FixedFloor(FixedDiv(ll->duration, abs(destvalue - sector->lightlevel)))/FRACUNIT, 1); - ll->firsttic = gametic; + ll->interval = max(FixedFloor(FixedDiv(ll->timer, abs(destvalue - sector->lightlevel)))/FRACUNIT, 1); } else { - ll->duration = -1; + ll->timer = -1; ll->speed = abs(speed); } } @@ -385,14 +385,14 @@ void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased) */ void T_LightFade(lightlevel_t *ll) { - if (ll->duration >= 0) // tic-based + if (ll->ticbased) { - if (gametic - ll->firsttic >= ll->duration) + if (--ll->timer <= 0) { ll->sector->lightlevel = (INT16)ll->destlevel; // set to dest lightlevel P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker } - else if (!((gametic - ll->firsttic) % ll->interval)) + else if (!(ll->timer % ll->interval)) { if (ll->speed < 0) ll->sector->lightlevel = max(ll->sector->lightlevel + (INT16)ll->speed, (INT16)ll->destlevel); diff --git a/src/p_saveg.c b/src/p_saveg.c index 8ec5b5ea8..eefee072d 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1539,9 +1539,9 @@ static void SaveLightlevelThinker(const thinker_t *th, const UINT8 type) WRITEUINT32(save_p, SaveSector(ht->sector)); WRITEINT32(save_p, ht->destlevel); WRITEINT32(save_p, ht->speed); - WRITEINT32(save_p, ht->duration); + WRITEUINT8(save_p, (UINT8)ht->ticbased); + WRITEINT32(save_p, ht->timer); WRITEUINT32(save_p, ht->interval); - WRITEUINT32(save_p, (UINT32)ht->firsttic); } // @@ -2515,9 +2515,9 @@ static inline void LoadLightlevelThinker(actionf_p1 thinker) ht->sector = LoadSector(READUINT32(save_p)); ht->destlevel = READINT32(save_p); ht->speed = READINT32(save_p); - ht->duration = READINT32(save_p); + ht->ticbased = (boolean)READUINT8(save_p); + ht->timer = READINT32(save_p); ht->interval = READUINT32(save_p); - ht->firsttic = (tic_t)READUINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; P_AddThinker(&ht->thinker); diff --git a/src/p_spec.h b/src/p_spec.h index c2c4c8976..1e327c5f2 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -140,9 +140,9 @@ typedef struct INT32 speed; ///< Speed at which to change light level. // Tic-based behavior - INT32 duration; ///< If <0, do not use tic-based behavior. If 0, set instantly. If >0, fade lasts this duration. + boolean ticbased; ///< Tic-based logic + INT32 timer; ///< Tic-based timer UINT32 interval; ///< Interval to deduct light level - tic_t firsttic; ///< First gametic to count from } lightlevel_t; #define GLOWSPEED 8 From 0202bbcfd325165760915710c1e0a768c335d822 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 20:45:12 -0400 Subject: [PATCH 078/306] Replace firsttic with timer increment --- src/p_saveg.c | 8 ++++---- src/p_spec.c | 36 ++++++++++++++++++------------------ src/p_spec.h | 4 ++-- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 8ec35a0d6..a3790d6f0 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1593,9 +1593,9 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type) WRITEINT16(save_p, ht->destvalue); WRITEINT16(save_p, ht->destlightlevel); WRITEINT16(save_p, ht->speed); - WRITEINT32(save_p, ht->duration); + WRITEUINT8(save_p, (UINT8)ht->ticbased); + WRITEINT32(save_p, ht->timer); WRITEUINT32(save_p, ht->interval); - WRITEUINT32(save_p, (UINT32)ht->firsttic); WRITEUINT8(save_p, ht->doexists); WRITEUINT8(save_p, ht->dotranslucent); WRITEUINT8(save_p, ht->dolighting); @@ -2605,9 +2605,9 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->destvalue = READINT16(save_p); ht->destlightlevel = READINT16(save_p); ht->speed = READINT16(save_p); - ht->duration = READINT32(save_p); + ht->ticbased = (boolean)READUINT8(save_p); + ht->timer = READINT32(save_p); ht->interval = READUINT32(save_p); - ht->firsttic = (tic_t)READUINT32(save_p); ht->doexists = READUINT8(save_p); ht->dotranslucent = READUINT8(save_p); ht->dolighting = READUINT8(save_p); diff --git a/src/p_spec.c b/src/p_spec.c index 8b5b0c1c4..1bc60cc71 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -105,7 +105,7 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t * static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize); #define P_RemoveFakeFloorFader(l) P_ResetFakeFloorFader(l, NULL, false); -static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, INT32 duration, UINT32 interval, tic_t firsttic, +static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, boolean ticbased, INT32 *timer, UINT32 interval, boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha); static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, INT16 destvalue, INT16 speed, boolean ticbased, @@ -3368,7 +3368,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_RemoveFakeFloorFader(rover); P_FadeFakeFloor(rover, destvalue, 0, // set alpha immediately - -1, 0, 0, // tic-based logic + false, NULL, 0, // tic-based logic !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT !(line->flags & ML_EFFECT2), // do not handle lighting @@ -7446,9 +7446,9 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz fadingdata->alpha - 1 : // trigger fade-out finish fadingdata->alpha + 1, // trigger fade-in finish 0, - fadingdata->duration, + fadingdata->ticbased, + &fadingdata->timer, fadingdata->interval, - fadingdata->firsttic, fadingdata->doexists, fadingdata->dotranslucent, fadingdata->docollision, @@ -7467,10 +7467,9 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz } } -static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, INT32 duration, UINT32 interval, tic_t firsttic, +static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, boolean ticbased, INT32 *timer, UINT32 interval, boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha) { - boolean ticbased = (duration > -1); boolean stillfading = false; INT32 alpha; fade_t *fadingdata = (fade_t *)rover->fadingdata; @@ -7499,7 +7498,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, IN { // finish fading out if (speed < 1 || (!ticbased && alpha - speed <= destvalue + speed) || - (ticbased && (gametic - firsttic >= duration || alpha <= destvalue))) + (ticbased && (--(*timer) <= 0 || alpha <= destvalue))) { alpha = destvalue; @@ -7521,7 +7520,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, IN { if (!ticbased) alpha -= speed; - else if (ticbased && !((gametic - firsttic) % interval)) + else if (ticbased && !((*timer) % interval)) alpha = max(alpha - speed, destvalue); stillfading = true; } @@ -7530,7 +7529,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, IN { // finish fading in if (speed < 1 || (!ticbased && alpha + speed >= destvalue - speed) || - (ticbased && (gametic - firsttic >= duration || alpha >= destvalue))) + (ticbased && (--(*timer) <= 0|| alpha >= destvalue))) { alpha = destvalue; @@ -7552,7 +7551,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, IN { if (!ticbased) alpha += speed; - else if (ticbased && !((gametic - firsttic) % interval)) + else if (ticbased && !((*timer) % interval)) alpha = min(alpha + speed, destvalue); stillfading = true; } @@ -7743,16 +7742,17 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor if (ticbased) { - d->duration = abs(speed); - d->speed = max(abs(FixedFloor(FixedDiv(d->destvalue - d->alpha, d->duration))/FRACUNIT), 1); - d->interval = max(FixedFloor(FixedDiv(d->duration, abs(d->destvalue - d->alpha)))/FRACUNIT, 1); - d->firsttic = gametic; + d->ticbased = true; + d->timer = abs(speed); + d->speed = max(abs(FixedFloor(FixedDiv(d->destvalue - d->alpha, d->timer))/FRACUNIT), 1); + d->interval = max(FixedFloor(FixedDiv(d->timer, abs(d->destvalue - d->alpha)))/FRACUNIT, 1); } else { d->speed = max(1, speed); // minimum speed 1/tic // if speed < 1, alpha is set immediately in thinker - d->duration = -1; - d->interval = d->firsttic = 0; + d->ticbased = false; + d->timer = -1; + d->interval = 0; } d->doexists = doexists; @@ -7779,7 +7779,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor P_FadeLightBySector(§ors[rover->secnum], d->destlightlevel, - ticbased ? d->duration : + ticbased ? d->timer : FixedFloor(FixedDiv(abs(d->destvalue - d->alpha), d->speed))/FRACUNIT, true); } @@ -7796,7 +7796,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor */ void T_Fade(fade_t *d) { - if (d->rover && !P_FadeFakeFloor(d->rover, d->destvalue, d->speed, d->duration, d->interval, d->firsttic, + if (d->rover && !P_FadeFakeFloor(d->rover, d->destvalue, d->speed, d->ticbased, &d->timer, d->interval, d->doexists, d->dotranslucent, d->dolighting, d->docollision, d->doghostfade, d->exactalpha)) { // Finalize lighting, copypasta from P_AddFakeFloorFader diff --git a/src/p_spec.h b/src/p_spec.h index 2499ddcba..9e602b192 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -472,9 +472,9 @@ typedef struct INT16 destvalue; ///< Transparency value to fade to INT16 destlightlevel; ///< Light level to fade to INT16 speed; ///< Speed to fade by - INT32 duration; ///< Duration for tic-based logic, > -1 means use tic-based + boolean ticbased; ///< Tic-based logic toggle + INT32 timer; ///< Timer for tic-based logic UINT32 interval; ///< Skip interval for tic-based logic - tic_t firsttic; ///< First tic for tic-based logic boolean doexists; ///< Handle FF_EXISTS boolean dotranslucent; ///< Handle FF_TRANSLUCENT boolean dolighting; ///< Handle shadows and light blocks From 573e1d00173d373bf0a6e72b7800c9925c209441 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 21:01:00 -0400 Subject: [PATCH 079/306] Replace firsttic with timer increment --- src/p_polyobj.c | 9 ++++----- src/p_polyobj.h | 6 ++---- src/p_saveg.c | 6 ++---- src/p_spec.c | 7 +++---- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 9e5cdf90e..a8616dba1 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -2873,9 +2873,9 @@ void T_PolyObjFade(polyfade_t *th) if (po->thinker == NULL) po->thinker = &th->thinker; - stillfading = !(gametic - th->firsttic >= th->duration); + stillfading = !(--(th->timer) <= 0); - if (gametic - th->firsttic >= th->duration) + if (th->timer <= 0) { po->translucency = th->destvalue; // set to dest translucency @@ -2884,7 +2884,7 @@ void T_PolyObjFade(polyfade_t *th) po->thinker = NULL; P_RemoveThinker(&th->thinker); } - else if (!((gametic - th->firsttic) % th->interval)) + else if (!(th->timer % th->interval)) { if (th->speed <= 0) po->translucency = max(po->translucency + th->speed, th->destvalue); @@ -2968,10 +2968,9 @@ INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata) th->destvalue = pfdata->destvalue; th->docollision = pfdata->docollision; th->doghostfade = pfdata->doghostfade; - th->duration = pfdata->duration; + th->timer = pfdata->timer; th->speed = pfdata->speed; th->interval = pfdata->interval; - th->firsttic = pfdata->firsttic; oldpo = po; diff --git a/src/p_polyobj.h b/src/p_polyobj.h index cf00d64ba..d5c07cb5b 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -215,10 +215,9 @@ typedef struct polyfade_s INT32 destvalue; boolean docollision; boolean doghostfade; - UINT32 duration; + INT32 timer; INT32 speed; UINT32 interval; - tic_t firsttic; } polyfade_t; // @@ -286,10 +285,9 @@ typedef struct polyfadedata_s INT32 destvalue; boolean docollision; boolean doghostfade; - UINT32 duration; + INT32 timer; INT32 speed; UINT32 interval; - tic_t firsttic; } polyfadedata_t; // diff --git a/src/p_saveg.c b/src/p_saveg.c index fc9382233..403f05b00 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1708,10 +1708,9 @@ static void SavePolyfadeThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->destvalue); WRITEUINT8(save_p, (UINT8)ht->docollision); WRITEUINT8(save_p, (UINT8)ht->doghostfade); - WRITEUINT32(save_p, ht->duration); + WRITEINT32(save_p, ht->timer); WRITEINT32(save_p, ht->speed); WRITEUINT32(save_p, ht->interval); - WRITEUINT32(save_p, (UINT32)ht->firsttic); } #endif @@ -2723,10 +2722,9 @@ static void LoadPolyfadeThinker(actionf_p1 thinker) ht->destvalue = READINT32(save_p); ht->docollision = (boolean)READUINT8(save_p); ht->doghostfade = (boolean)READUINT8(save_p); - ht->duration = READUINT32(save_p); + ht->timer = READINT32(save_p); ht->speed = READINT32(save_p); ht->interval = READUINT32(save_p); - ht->firsttic = (tic_t)READUINT32(save_p); P_AddThinker(&ht->thinker); } #endif diff --git a/src/p_spec.c b/src/p_spec.c index 6d746f670..a20a339ed 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1276,12 +1276,11 @@ static boolean PolyFade(line_t *line) pfd.docollision = !(line->flags & ML_BOUNCY), // do not handle collision flags pfd.doghostfade = (line->flags & ML_EFFECT1), // do ghost fade (no collision flags during fade) - pfd.duration = abs(sides[line->sidenum[0]].rowoffset>>FRACBITS); - pfd.speed = FixedFloor(FixedDiv(pfd.destvalue - po->translucency, pfd.duration))/FRACUNIT; + pfd.timer = abs(sides[line->sidenum[0]].rowoffset>>FRACBITS); + pfd.speed = FixedFloor(FixedDiv(pfd.destvalue - po->translucency, pfd.timer))/FRACUNIT; if (!pfd.speed) pfd.speed = (pfd.destvalue < po->translucency) ? -1 : 1; - pfd.interval = max(FixedFloor(FixedDiv(pfd.duration, abs(pfd.destvalue - po->translucency)))/FRACUNIT, 1); - pfd.firsttic = gametic; + pfd.interval = max(FixedFloor(FixedDiv(pfd.timer, abs(pfd.destvalue - po->translucency)))/FRACUNIT, 1); return EV_DoPolyObjFade(&pfd); } From 231f19aaabb28bfc40b0a5e25546da8df186372d Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 21:02:43 -0400 Subject: [PATCH 080/306] Revert "Merge branch 'random-fof-fixes' into fof-fixes-movingplatexists" This reverts commit cc114590548cb1b7f099d12499d556af2da2c993, reversing changes made to 7e3d5cd3734c5b2194dca7fb8875c9cfeca97dc4. --- src/p_floor.c | 44 ++++++++++++++------------------------------ 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/src/p_floor.c b/src/p_floor.c index bb6bf8d16..0e28b831f 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1839,7 +1839,6 @@ void T_ThwompSector(levelspecthink_t *thwomp) #define ceilingwasheight vars[5] fixed_t thwompx, thwompy; sector_t *actionsector; - ffloor_t *rover = NULL; INT32 secnum; // If you just crashed down, wait a second before coming back up. @@ -1854,16 +1853,7 @@ void T_ThwompSector(levelspecthink_t *thwomp) secnum = P_FindSectorFromTag((INT16)thwomp->vars[0], -1); if (secnum > 0) - { actionsector = §ors[secnum]; - - // Look for thwomp FFloor - for (rover = actionsector->ffloors; rover; rover = rover->next) - { - if (rover->master == thwomp->sourceline) - break; - } - } else return; // Bad bad bad! @@ -1952,13 +1942,10 @@ void T_ThwompSector(levelspecthink_t *thwomp) { mobj_t *mp = (void *)&actionsector->soundorg; - if (!rover || (rover->flags & FF_EXISTS)) - { - if (thwomp->sourceline->flags & ML_EFFECT4) - S_StartSound(mp, sides[thwomp->sourceline->sidenum[0]].textureoffset>>FRACBITS); - else - S_StartSound(mp, sfx_thwomp); - } + if (thwomp->sourceline->flags & ML_EFFECT4) + S_StartSound(mp, sides[thwomp->sourceline->sidenum[0]].textureoffset>>FRACBITS); + else + S_StartSound(mp, sfx_thwomp); thwomp->direction = 1; // start heading back up thwomp->distance = TICRATE; // but only after a small delay @@ -1972,21 +1959,18 @@ void T_ThwompSector(levelspecthink_t *thwomp) thinker_t *th; mobj_t *mo; - if (!rover || (rover->flags & FF_EXISTS)) + // scan the thinkers to find players! + for (th = thinkercap.next; th != &thinkercap; th = th->next) { - // scan the thinkers to find players! - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; - mo = (mobj_t *)th; - if (mo->type == MT_PLAYER && mo->health && mo->z <= thwomp->sector->ceilingheight - && P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT) - { - thwomp->direction = -1; - break; - } + mo = (mobj_t *)th; + if (mo->type == MT_PLAYER && mo->health && mo->z <= thwomp->sector->ceilingheight + && P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT) + { + thwomp->direction = -1; + break; } } From d01193df80d3164d437ceb02e9e75cbe304248e9 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 21:59:41 -0400 Subject: [PATCH 081/306] Apply ~FF_EXISTS moving plat fix for VERTICALFLIP --- src/p_map.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index c275ba0be..ab6c03da0 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2723,6 +2723,7 @@ static boolean P_ThingHeightClip(mobj_t *thing) boolean floormoved; fixed_t oldfloorz = thing->floorz; size_t oldfloor_sectornum = thing->floor_sectornum, oldfloor_rovernum = thing->floor_rovernum; + size_t oldceil_sectornum = thing->ceiling_sectornum, oldceil_rovernum = thing->ceiling_rovernum; boolean onfloor = P_IsObjectOnGround(thing);//(thing->z <= thing->floorz); ffloor_t *rover = NULL; @@ -2751,13 +2752,15 @@ static boolean P_ThingHeightClip(mobj_t *thing) if (onfloor && !(thing->flags & MF_NOGRAVITY) && floormoved) { + size_t old_sectornum = (thing->eflags & MFE_VERTICALFLIP) ? oldceil_sectornum : oldfloor_sectornum; + size_t old_rovernum = (thing->eflags & MFE_VERTICALFLIP) ? oldceil_rovernum : oldfloor_rovernum; // Find FOF referenced by floorz - if (oldfloor_sectornum) + if (old_sectornum) { size_t rovernum = 0; - for (rover = sectors[oldfloor_sectornum].ffloors; rover; rover = rover->next) + for (rover = sectors[old_sectornum].ffloors; rover; rover = rover->next) { - if (rovernum == oldfloor_rovernum) + if (rovernum == old_rovernum) break; rovernum++; } From 9cc186441b6703e7ab8a6e62abadb2cc118e7210 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 22:14:24 -0400 Subject: [PATCH 082/306] Fix fog visual glitch with fading --- src/p_spec.c | 58 ++++++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 1bc60cc71..0346bdd3d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7481,6 +7481,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, bo // initialize its alpha to 1 if (dotranslucent && (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->flags & FF_FOG) && // do not include fog !(rover->spawnflags & FF_RENDERSIDES) && !(rover->spawnflags & FF_RENDERPLANES) && !(rover->flags & FF_RENDERALL)) @@ -7572,7 +7573,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, bo rover->target->moved = true; } - if (dotranslucent) + if (dotranslucent && !(rover->flags & FF_FOG)) { if (alpha >= 256) { @@ -7619,7 +7620,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, bo rover->flags |= FF_EXISTS; } - if (dotranslucent) + if (dotranslucent && !(rover->flags & FF_FOG)) { rover->flags |= FF_TRANSLUCENT; @@ -7667,32 +7668,35 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, bo } } - if (!stillfading || exactalpha) - rover->alpha = alpha; - else // clamp fadingdata->alpha to software's alpha levels + if (!(rover->flags & FF_FOG)) // don't set FOG alpha { - if (alpha < 12) - rover->alpha = destvalue < 12 ? destvalue : 1; // Don't even draw it - else if (alpha < 38) - rover->alpha = destvalue >= 12 && destvalue < 38 ? destvalue : 25; - else if (alpha < 64) - rover->alpha = destvalue >=38 && destvalue < 64 ? destvalue : 51; - else if (alpha < 89) - rover->alpha = destvalue >= 64 && destvalue < 89 ? destvalue : 76; - else if (alpha < 115) - rover->alpha = destvalue >= 89 && destvalue < 115 ? destvalue : 102; - else if (alpha < 140) - rover->alpha = destvalue >= 115 && destvalue < 140 ? destvalue : 128; - else if (alpha < 166) - rover->alpha = destvalue >= 140 && destvalue < 166 ? destvalue : 154; - else if (alpha < 192) - rover->alpha = destvalue >= 166 && destvalue < 192 ? destvalue : 179; - else if (alpha < 217) - rover->alpha = destvalue >= 192 && destvalue < 217 ? destvalue : 204; - else if (alpha < 243) - rover->alpha = destvalue >= 217 && destvalue < 243 ? destvalue : 230; - else // Opaque - rover->alpha = destvalue >= 243 ? destvalue : 256; + if (!stillfading || exactalpha) + rover->alpha = alpha; + else // clamp fadingdata->alpha to software's alpha levels + { + if (alpha < 12) + rover->alpha = destvalue < 12 ? destvalue : 1; // Don't even draw it + else if (alpha < 38) + rover->alpha = destvalue >= 12 && destvalue < 38 ? destvalue : 25; + else if (alpha < 64) + rover->alpha = destvalue >=38 && destvalue < 64 ? destvalue : 51; + else if (alpha < 89) + rover->alpha = destvalue >= 64 && destvalue < 89 ? destvalue : 76; + else if (alpha < 115) + rover->alpha = destvalue >= 89 && destvalue < 115 ? destvalue : 102; + else if (alpha < 140) + rover->alpha = destvalue >= 115 && destvalue < 140 ? destvalue : 128; + else if (alpha < 166) + rover->alpha = destvalue >= 140 && destvalue < 166 ? destvalue : 154; + else if (alpha < 192) + rover->alpha = destvalue >= 166 && destvalue < 192 ? destvalue : 179; + else if (alpha < 217) + rover->alpha = destvalue >= 192 && destvalue < 217 ? destvalue : 204; + else if (alpha < 243) + rover->alpha = destvalue >= 217 && destvalue < 243 ? destvalue : 230; + else // Opaque + rover->alpha = destvalue >= 243 ? destvalue : 256; + } } if (fadingdata) From f33f9dd284f67a1a0cf4c1b8a3b671ce3bd30249 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 23:12:37 -0400 Subject: [PATCH 083/306] Replace sectornum/rovernum index vars with ffloor pointers --- src/p_map.c | 93 ++++++++++++++------------------------------------- src/p_mobj.h | 6 ++-- src/p_saveg.c | 48 +++++++++++++++++++------- 3 files changed, 62 insertions(+), 85 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index ab6c03da0..4bf06fa4b 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -52,8 +52,7 @@ fixed_t tmfloorz, tmceilingz; static fixed_t tmdropoffz, tmdrpoffceilz; // drop-off floor/ceiling heights mobj_t *tmfloorthing; // the thing corresponding to tmfloorz or NULL if tmfloorz is from a sector mobj_t *tmhitthing; // the solid thing you bumped into (for collisions) -//ffloor_t *tmfloorrover, *tmceilingrover; // unused for now -size_t tmfloor_sectornum, tmfloor_rovernum, tmceiling_sectornum, tmceiling_rovernum; +ffloor_t *tmfloorrover, *tmceilingrover; #ifdef ESLOPE pslope_t *tmfloorslope, *tmceilingslope; #endif @@ -1419,8 +1418,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->z + thing->height > tmfloorz) { tmfloorz = thing->z + thing->height; - // tmfloorrover = NULL; - tmfloor_sectornum = tmfloor_rovernum = 0; + tmfloorrover = NULL; #ifdef ESLOPE tmfloorslope = NULL; #endif @@ -1441,8 +1439,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return false; tmfloorz = tmceilingz = topz; // block while in air - // tmceilingrover = NULL; - tmceiling_sectornum = tmceiling_rovernum = 0; + tmceilingrover = NULL; #ifdef ESLOPE tmceilingslope = NULL; #endif @@ -1451,8 +1448,7 @@ static boolean PIT_CheckThing(mobj_t *thing) else if (topz < tmceilingz && tmthing->z <= thing->z+thing->height) { tmceilingz = topz; - // tmceilingrover = NULL; - tmceiling_sectornum = tmceiling_rovernum = 0; + tmceilingrover = NULL; #ifdef ESLOPE tmceilingslope = NULL; #endif @@ -1469,8 +1465,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->z < tmceilingz) { tmceilingz = thing->z; - // tmceilingrover = NULL; - tmceiling_sectornum = tmceiling_rovernum = 0; + tmceilingrover = NULL; #ifdef ESLOPE tmceilingslope = NULL; #endif @@ -1491,8 +1486,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return false; tmfloorz = tmceilingz = topz; // block while in air - // tmfloorrover = NULL; - tmfloor_sectornum = tmfloor_rovernum = 0; + tmfloorrover = NULL; #ifdef ESLOPE tmfloorslope = NULL; #endif @@ -1501,8 +1495,7 @@ static boolean PIT_CheckThing(mobj_t *thing) else if (topz > tmfloorz && tmthing->z+tmthing->height >= thing->z) { tmfloorz = topz; - // tmfloorrover = NULL; - tmfloor_sectornum = tmfloor_rovernum = 0; + tmfloorrover = NULL; #ifdef ESLOPE tmfloorslope = NULL; #endif @@ -1654,8 +1647,7 @@ static boolean PIT_CheckLine(line_t *ld) { tmceilingz = opentop; ceilingline = ld; - // tmceilingrover = NULL; - tmceiling_sectornum = tmceiling_rovernum = 0; + tmceilingrover = NULL; #ifdef ESLOPE tmceilingslope = opentopslope; #endif @@ -1664,8 +1656,7 @@ static boolean PIT_CheckLine(line_t *ld) if (openbottom > tmfloorz) { tmfloorz = openbottom; - // tmfloorrover = NULL; - tmfloor_sectornum = tmfloor_rovernum = 0; + tmfloorrover = NULL; #ifdef ESLOPE tmfloorslope = openbottomslope; #endif @@ -1747,10 +1738,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) // will adjust them. tmfloorz = tmdropoffz = P_GetFloorZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->floorheight; tmceilingz = P_GetCeilingZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->ceilingheight; - // tmfloorrover = NULL; - tmfloor_sectornum = tmfloor_rovernum = 0; - // tmceilingrover = NULL; - tmceiling_sectornum = tmceiling_rovernum = 0; + tmfloorrover = NULL; + tmceilingrover = NULL; #ifdef ESLOPE tmfloorslope = newsubsec->sector->f_slope; tmceilingslope = newsubsec->sector->c_slope; @@ -1798,9 +1787,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) { if (tmfloorz < topheight - sinklevel) { tmfloorz = topheight - sinklevel; - // tmfloorrover = rover; - tmfloor_sectornum = newsubsec->sector - sectors; - tmfloor_rovernum = rovernum; + tmfloorrover = rover; #ifdef ESLOPE tmfloorslope = *rover->t_slope; #endif @@ -1810,9 +1797,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) { if (tmceilingz > bottomheight + sinklevel) { tmceilingz = bottomheight + sinklevel; - // tmceilingrover = rover; - tmceiling_sectornum = newsubsec->sector - sectors; - tmceiling_rovernum = rovernum; + tmceilingrover = rover; #ifdef ESLOPE tmceilingslope = *rover->b_slope; #endif @@ -1841,9 +1826,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) { if (tmfloorz < thing->z) { tmfloorz = thing->z; - // tmfloorrover = rover; - tmfloor_sectornum = newsubsec->sector - sectors; - tmfloor_rovernum = rovernum; + tmfloorrover = rover; #ifdef ESLOPE tmfloorslope = NULL; #endif @@ -1863,9 +1846,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) && !(rover->flags & FF_REVERSEPLATFORM)) { tmfloorz = tmdropoffz = topheight; - // tmfloorrover = rover; - tmfloor_sectornum = newsubsec->sector - sectors; - tmfloor_rovernum = rovernum; + tmfloorrover = rover; #ifdef ESLOPE tmfloorslope = *rover->t_slope; #endif @@ -1875,9 +1856,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) && !(thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE))) { tmceilingz = tmdrpoffceilz = bottomheight; - // tmceilingrover = rover; - tmceiling_sectornum = newsubsec->sector - sectors; - tmceiling_rovernum = rovernum; + tmceilingrover = rover; #ifdef ESLOPE tmceilingslope = *rover->b_slope; #endif @@ -2375,12 +2354,8 @@ boolean PIT_PushableMoved(mobj_t *thing) mobj_t *oldthing = tmthing; line_t *oldceilline = ceilingline; line_t *oldblockline = blockingline; - // ffloor_t *oldflrrover = tmfloorrover; - // ffloor_t *oldceilrover = tmceilingrover; - size_t oldflrrover_sectornum = tmfloor_sectornum; - size_t oldflrrover_ffloornum = tmfloor_rovernum; - size_t oldceilrover_sectornum = tmceiling_sectornum; - size_t oldceilrover_ffloornum = tmceiling_rovernum; + ffloor_t *oldflrrover = tmfloorrover; + ffloor_t *oldceilrover = tmceilingrover; #ifdef ESLOPE pslope_t *oldfslope = tmfloorslope; pslope_t *oldcslope = tmceilingslope; @@ -2397,12 +2372,8 @@ boolean PIT_PushableMoved(mobj_t *thing) P_SetTarget(&tmthing, oldthing); ceilingline = oldceilline; blockingline = oldblockline; - // tmfloorrover = oldflrrover; - // tmceilingrover = oldceilrover; - tmfloor_sectornum = oldflrrover_sectornum; - tmfloor_rovernum = oldflrrover_ffloornum; - tmceiling_sectornum = oldceilrover_sectornum; - tmceiling_rovernum = oldceilrover_ffloornum; + tmfloorrover = oldflrrover; + tmceilingrover = oldceilrover; #ifdef ESLOPE tmfloorslope = oldfslope; tmceilingslope = oldcslope; @@ -2722,8 +2693,8 @@ static boolean P_ThingHeightClip(mobj_t *thing) { boolean floormoved; fixed_t oldfloorz = thing->floorz; - size_t oldfloor_sectornum = thing->floor_sectornum, oldfloor_rovernum = thing->floor_rovernum; - size_t oldceil_sectornum = thing->ceiling_sectornum, oldceil_rovernum = thing->ceiling_rovernum; + ffloor_t *oldfloorrover = thing->floorrover; + ffloor_t *oldceilingrover = thing->ceilingrover; boolean onfloor = P_IsObjectOnGround(thing);//(thing->z <= thing->floorz); ffloor_t *rover = NULL; @@ -2740,10 +2711,8 @@ static boolean P_ThingHeightClip(mobj_t *thing) thing->floorz = tmfloorz; thing->ceilingz = tmceilingz; - thing->floor_sectornum = tmfloor_sectornum; - thing->floor_rovernum = tmfloor_rovernum; - thing->ceiling_sectornum = tmceiling_sectornum; - thing->ceiling_rovernum = tmceiling_rovernum; + thing->floorrover = tmfloorrover; + thing->ceilingrover = tmceilingrover; // Ugly hack?!?! As long as just ceilingz is the lowest, // you'll still get crushed, right? @@ -2752,19 +2721,7 @@ static boolean P_ThingHeightClip(mobj_t *thing) if (onfloor && !(thing->flags & MF_NOGRAVITY) && floormoved) { - size_t old_sectornum = (thing->eflags & MFE_VERTICALFLIP) ? oldceil_sectornum : oldfloor_sectornum; - size_t old_rovernum = (thing->eflags & MFE_VERTICALFLIP) ? oldceil_rovernum : oldfloor_rovernum; - // Find FOF referenced by floorz - if (old_sectornum) - { - size_t rovernum = 0; - for (rover = sectors[old_sectornum].ffloors; rover; rover = rover->next) - { - if (rovernum == old_rovernum) - break; - rovernum++; - } - } + rover = (thing->eflags & MFE_VERTICALFLIP) ? oldceilingrover : oldfloorrover; // Match the Thing's old floorz to an FOF and check for FF_EXISTS // If ~FF_EXISTS, don't set mobj Z. diff --git a/src/p_mobj.h b/src/p_mobj.h index 3a83a0f58..90394c70d 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -282,10 +282,8 @@ typedef struct mobj_s // The closest interval over all contacted sectors (or things). fixed_t floorz; // Nearest floor below. fixed_t ceilingz; // Nearest ceiling above. - size_t floor_sectornum; // FOF referred by floorz - size_t floor_rovernum; // FOF referred by floorz - size_t ceiling_sectornum; // FOF referred by ceilingz - size_t ceiling_rovernum; // FOF referred by ceilingz + struct ffloor_s *floorrover; // FOF referred by floorz + struct ffloor_s *ceilingrover; // FOF referred by ceilingz // For movement checking. fixed_t radius; diff --git a/src/p_saveg.c b/src/p_saveg.c index 33dfd1424..d0ca0a873 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1192,10 +1192,13 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, mobj->z); // Force this so 3dfloor problems don't arise. WRITEFIXED(save_p, mobj->floorz); WRITEFIXED(save_p, mobj->ceilingz); - WRITEUINT32(save_p, (UINT32)mobj->floor_sectornum); - WRITEUINT32(save_p, (UINT32)mobj->floor_rovernum); - WRITEUINT32(save_p, (UINT32)mobj->ceiling_sectornum); - WRITEUINT32(save_p, (UINT32)mobj->ceiling_rovernum); + + // \todo netsync for floorrover + + // WRITEUINT32(save_p, (UINT32)mobj->floor_sectornum); + // WRITEUINT32(save_p, (UINT32)mobj->floor_rovernum); + // WRITEUINT32(save_p, (UINT32)mobj->ceiling_sectornum); + // WRITEUINT32(save_p, (UINT32)mobj->ceiling_rovernum); if (diff & MD_SPAWNPOINT) { @@ -1993,7 +1996,7 @@ static void LoadMobjThinker(actionf_p1 thinker) UINT16 diff2; INT32 i; fixed_t z, floorz, ceilingz; - size_t floor_sectornum, floor_rovernum, ceiling_sectornum, ceiling_rovernum; + //size_t floor_sectornum, floor_rovernum, ceiling_sectornum, ceiling_rovernum; diff = READUINT32(save_p); if (diff & MD_MORE) @@ -2006,10 +2009,26 @@ static void LoadMobjThinker(actionf_p1 thinker) z = READFIXED(save_p); // Force this so 3dfloor problems don't arise. floorz = READFIXED(save_p); ceilingz = READFIXED(save_p); - floor_sectornum = (size_t)READUINT32(save_p); - floor_rovernum = (size_t)READUINT32(save_p); - ceiling_sectornum = (size_t)READUINT32(save_p); - ceiling_rovernum = (size_t)READUINT32(save_p); + + // \todo netsync for floorrover +#if 0 + // Find FOF referenced by floorz + if (old_sectornum) + { + size_t rovernum = 0; + for (rover = sectors[old_sectornum].ffloors; rover; rover = rover->next) + { + if (rovernum == old_rovernum) + break; + rovernum++; + } + } +#endif + + // floor_sectornum = (size_t)READUINT32(save_p); + // floor_rovernum = (size_t)READUINT32(save_p); + // ceiling_sectornum = (size_t)READUINT32(save_p); + // ceiling_rovernum = (size_t)READUINT32(save_p); if (diff & MD_SPAWNPOINT) { @@ -2035,10 +2054,13 @@ static void LoadMobjThinker(actionf_p1 thinker) mobj->z = z; mobj->floorz = floorz; mobj->ceilingz = ceilingz; - mobj->floor_sectornum = floor_sectornum; - mobj->floor_rovernum = floor_rovernum; - mobj->ceiling_sectornum = ceiling_sectornum; - mobj->ceiling_rovernum = ceiling_rovernum; + + // \todo netsync for floorrover + + // mobj->floor_sectornum = floor_sectornum; + // mobj->floor_rovernum = floor_rovernum; + // mobj->ceiling_sectornum = ceiling_sectornum; + // mobj->ceiling_rovernum = ceiling_rovernum; if (diff & MD_TYPE) mobj->type = READUINT32(save_p); From dd35871699cef6f77d05435c1aecdb2ae594f92f Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 23:48:14 -0400 Subject: [PATCH 084/306] Savegame netsync for mobj->floorrover and ceilingrrover --- src/p_saveg.c | 100 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 73 insertions(+), 27 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index d0ca0a873..4c9e17b4f 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -972,11 +972,13 @@ typedef enum MD2_EXTVAL1 = 1<<5, MD2_EXTVAL2 = 1<<6, MD2_HNEXT = 1<<7, -#ifdef ESLOPE MD2_HPREV = 1<<8, - MD2_SLOPE = 1<<9 + MD2_FLOORROVER = 1<<9, +#ifdef ESLOPE + MD2_CEILINGROVER = 1<<10, + MD2_SLOPE = 1<<11 #else - MD2_HPREV = 1<<8 + MD2_CEILINGROVER = 1<<10 #endif } mobj_diff2_t; @@ -1170,6 +1172,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_HNEXT; if (mobj->hprev) diff2 |= MD2_HPREV; + if (mobj->floorrover) + diff2 |= MD2_FLOORROVER; + if (mobj->ceilingrover) + diff2 |= MD2_CEILINGROVER; #ifdef ESLOPE if (mobj->standingslope) diff2 |= MD2_SLOPE; @@ -1193,12 +1199,45 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, mobj->floorz); WRITEFIXED(save_p, mobj->ceilingz); - // \todo netsync for floorrover + if (diff & MD2_FLOORROVER) + { + ffloor_t *rover; + size_t i = 0; + INT32 roverindex = -1; - // WRITEUINT32(save_p, (UINT32)mobj->floor_sectornum); - // WRITEUINT32(save_p, (UINT32)mobj->floor_rovernum); - // WRITEUINT32(save_p, (UINT32)mobj->ceiling_sectornum); - // WRITEUINT32(save_p, (UINT32)mobj->ceiling_rovernum); + for (rover = mobj->floorrover->target->ffloors; rover; rover = rover->next) + { + if (rover == mobj->floorrover) + { + roverindex = i; + break; + } + i++; + } + + WRITEUINT32(save_p, (UINT32)(mobj->floorrover->target - sectors)); + WRITEUINT32(save_p, (UINT32)roverindex); + } + + if (diff & MD2_CEILINGROVER) + { + ffloor_t *rover; + size_t i = 0; + INT32 roverindex = -1; + + for (rover = mobj->ceilingrover->target->ffloors; rover; rover = rover->next) + { + if (rover == mobj->ceilingrover) + { + roverindex = i; + break; + } + i++; + } + + WRITEUINT32(save_p, mobj->ceilingrover->target - sectors); + WRITEUINT32(save_p, roverindex); + } if (diff & MD_SPAWNPOINT) { @@ -1996,7 +2035,7 @@ static void LoadMobjThinker(actionf_p1 thinker) UINT16 diff2; INT32 i; fixed_t z, floorz, ceilingz; - //size_t floor_sectornum, floor_rovernum, ceiling_sectornum, ceiling_rovernum; + ffloor_t *floorrover = NULL, *ceilingrover = NULL; diff = READUINT32(save_p); if (diff & MD_MORE) @@ -2010,25 +2049,37 @@ static void LoadMobjThinker(actionf_p1 thinker) floorz = READFIXED(save_p); ceilingz = READFIXED(save_p); - // \todo netsync for floorrover -#if 0 - // Find FOF referenced by floorz - if (old_sectornum) + if (diff2 & MD2_FLOORROVER) { + size_t floor_sectornum = (size_t)READUINT32(save_p); + size_t floor_rovernum = (size_t)READUINT32(save_p); + ffloor_t *rover = NULL; size_t rovernum = 0; - for (rover = sectors[old_sectornum].ffloors; rover; rover = rover->next) + + for (rover = sectors[floor_sectornum].ffloors; rover; rover = rover->next) { - if (rovernum == old_rovernum) + if (rovernum == floor_rovernum) break; rovernum++; } + floorrover = rover; } -#endif - // floor_sectornum = (size_t)READUINT32(save_p); - // floor_rovernum = (size_t)READUINT32(save_p); - // ceiling_sectornum = (size_t)READUINT32(save_p); - // ceiling_rovernum = (size_t)READUINT32(save_p); + if (diff2 & MD2_CEILINGROVER) + { + size_t ceiling_sectornum = (size_t)READUINT32(save_p); + size_t ceiling_rovernum = (size_t)READUINT32(save_p); + ffloor_t *rover = NULL; + size_t rovernum = 0; + + for (rover = sectors[ceiling_sectornum].ffloors; rover; rover = rover->next) + { + if (rovernum == ceiling_rovernum) + break; + rovernum++; + } + ceilingrover = rover; + } if (diff & MD_SPAWNPOINT) { @@ -2054,13 +2105,8 @@ static void LoadMobjThinker(actionf_p1 thinker) mobj->z = z; mobj->floorz = floorz; mobj->ceilingz = ceilingz; - - // \todo netsync for floorrover - - // mobj->floor_sectornum = floor_sectornum; - // mobj->floor_rovernum = floor_rovernum; - // mobj->ceiling_sectornum = ceiling_sectornum; - // mobj->ceiling_rovernum = ceiling_rovernum; + mobj->floorrover = floorrover; + mobj->ceilingrover = ceilingrover; if (diff & MD_TYPE) mobj->type = READUINT32(save_p); From 5136293f62ecf8d8b2532648b8858b217ba9f3e4 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 23:52:36 -0400 Subject: [PATCH 085/306] Store sectornum/ffloornum as UINT32, not INT32 --- src/p_saveg.c | 8 ++++---- src/p_spec.c | 4 ++-- src/p_spec.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index a3790d6f0..24d0d699b 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1587,8 +1587,8 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type) { const fade_t *ht = (const void *)th; WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->sectornum); - WRITEINT32(save_p, ht->ffloornum); + WRITEUINT32(save_p, ht->sectornum); + WRITEUINT32(save_p, ht->ffloornum); WRITEINT32(save_p, ht->alpha); WRITEINT16(save_p, ht->destvalue); WRITEINT16(save_p, ht->destlightlevel); @@ -2599,8 +2599,8 @@ static inline void LoadFadeThinker(actionf_p1 thinker) { fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sectornum = READINT32(save_p); - ht->ffloornum = READINT32(save_p); + ht->sectornum = READUINT32(save_p); + ht->ffloornum = READUINT32(save_p); ht->alpha = READINT32(save_p); ht->destvalue = READINT16(save_p); ht->destlightlevel = READINT16(save_p); diff --git a/src/p_spec.c b/src/p_spec.c index 0346bdd3d..4cd9e5cb8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7729,8 +7729,8 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor d->thinker.function.acp1 = (actionf_p1)T_Fade; d->rover = rover; - d->sectornum = (INT32)sectornum; - d->ffloornum = (INT32)ffloornum; + d->sectornum = (UINT32)sectornum; + d->ffloornum = (UINT32)ffloornum; // If fading an invisible FOF whose render flags we did not yet set, // initialize its alpha to 1 diff --git a/src/p_spec.h b/src/p_spec.h index 9e602b192..b4577ff88 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -466,8 +466,8 @@ typedef struct { thinker_t thinker; ///< Thinker structure for effect. ffloor_t *rover; ///< Target ffloor - INT32 sectornum; ///< Number of ffloor target sector - INT32 ffloornum; ///< Number of ffloor of target sector + UINT32 sectornum; ///< Number of ffloor target sector + UINT32 ffloornum; ///< Number of ffloor of target sector INT32 alpha; ///< Internal alpha counter INT16 destvalue; ///< Transparency value to fade to INT16 destlightlevel; ///< Light level to fade to From 03d1baf422434b87f7e1c842f89f9fa3ab7236fa Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 00:07:22 -0400 Subject: [PATCH 086/306] Savegame floorrover fixes --- src/p_saveg.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 4c9e17b4f..c73df0cc9 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1199,11 +1199,11 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, mobj->floorz); WRITEFIXED(save_p, mobj->ceilingz); - if (diff & MD2_FLOORROVER) + if (diff2 & MD2_FLOORROVER) { ffloor_t *rover; size_t i = 0; - INT32 roverindex = -1; + UINT32 roverindex = 0; for (rover = mobj->floorrover->target->ffloors; rover; rover = rover->next) { @@ -1216,14 +1216,14 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) } WRITEUINT32(save_p, (UINT32)(mobj->floorrover->target - sectors)); - WRITEUINT32(save_p, (UINT32)roverindex); + WRITEUINT32(save_p, rover ? roverindex : i); // store max index to denote invalid ffloor ref } - if (diff & MD2_CEILINGROVER) + if (diff2 & MD2_CEILINGROVER) { ffloor_t *rover; size_t i = 0; - INT32 roverindex = -1; + UINT32 roverindex = 0; for (rover = mobj->ceilingrover->target->ffloors; rover; rover = rover->next) { @@ -1235,8 +1235,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) i++; } - WRITEUINT32(save_p, mobj->ceilingrover->target - sectors); - WRITEUINT32(save_p, roverindex); + WRITEUINT32(save_p, (UINT32)(mobj->ceilingrover->target - sectors)); + WRITEUINT32(save_p, rover ? roverindex : i); // store max index to denote invalid ffloor ref } if (diff & MD_SPAWNPOINT) From 832f891cbbacb5f8c1dbb96436753c7472cdce86 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 00:13:32 -0400 Subject: [PATCH 087/306] Remove rovernum increment from P_CheckPosition because unused --- src/p_map.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 4bf06fa4b..0726084d5 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1749,7 +1749,6 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) if (newsubsec->sector->ffloors) { ffloor_t *rover; - size_t rovernum = 0; fixed_t delta1, delta2; INT32 thingtop = thing->z + thing->height; @@ -1758,10 +1757,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) fixed_t topheight, bottomheight; if (!(rover->flags & FF_EXISTS)) - { - rovernum++; continue; - } topheight = P_GetFOFTopZ(thing, newsubsec->sector, rover, x, y, NULL); bottomheight = P_GetFOFBottomZ(thing, newsubsec->sector, rover, x, y, NULL); @@ -1804,7 +1800,6 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) } } } - rovernum++; continue; } @@ -1815,10 +1810,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) else if (!((rover->flags & FF_BLOCKPLAYER && thing->player) || (rover->flags & FF_BLOCKOTHERS && !thing->player) || rover->flags & FF_QUICKSAND)) - { - rovernum++; continue; - } if (rover->flags & FF_QUICKSAND) { @@ -1833,7 +1825,6 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) } } // Quicksand blocks never change heights otherwise. - rovernum++; continue; } @@ -1861,7 +1852,6 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) tmceilingslope = *rover->b_slope; #endif } - rovernum++; } } From 943dc9412d3e3f39ceb906f379786ac285c533da Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 00:20:51 -0400 Subject: [PATCH 088/306] Initialize floorrover and ceilingrover on SpawnMobj --- src/p_mobj.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 7b588645b..d433561ae 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8627,6 +8627,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) #endif mobj->subsector->sector->ceilingheight; + mobj->floorrover = NULL; + mobj->ceilingrover = NULL; + // Tells MobjCheckWater that the water height was not set. mobj->watertop = INT32_MAX; @@ -8890,6 +8893,9 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype #endif mobj->subsector->sector->ceilingheight; + mobj->floorrover = NULL; + mobj->ceilingrover = NULL; + mobj->z = z; mobj->momz = mobjinfo[type].speed; From 0d88f31bbd22b8893503f7d6719bc72923947970 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 00:23:23 -0400 Subject: [PATCH 089/306] Add floorrover and ceilingrover to precipmobj_t --- src/p_mobj.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_mobj.h b/src/p_mobj.h index 90394c70d..630600b54 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -400,6 +400,8 @@ typedef struct precipmobj_s // The closest interval over all contacted sectors (or things). fixed_t floorz; // Nearest floor below. fixed_t ceilingz; // Nearest ceiling above. + struct ffloor_s *floorrover; // FOF referred by floorz + struct ffloor_s *ceilingrover; // FOF referred by ceilingz // For movement checking. fixed_t radius; // Fixed at 2*FRACUNIT From a6f959ba21c9f599b4823d0adce9bc9d7c355b65 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 00:35:40 -0400 Subject: [PATCH 090/306] Set mobj->floorrover and ceilingrover in appropriate places --- src/lua_mobjlib.c | 6 ++++++ src/p_local.h | 1 + src/p_map.c | 10 ++++++++++ src/p_mobj.c | 4 ++++ src/p_polyobj.c | 2 ++ 5 files changed, 23 insertions(+) diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 1583bd3c4..6efbeff8e 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -396,6 +396,8 @@ static int mobj_set(lua_State *L) P_CheckPosition(mo, mo->x, mo->y); mo->floorz = tmfloorz; mo->ceilingz = tmceilingz; + mo->floorrover = tmfloorrover; + mo->ceilingrover = tmceilingrover; P_SetTarget(&tmthing, ptmthing); break; } @@ -439,6 +441,8 @@ static int mobj_set(lua_State *L) P_CheckPosition(mo, mo->x, mo->y); mo->floorz = tmfloorz; mo->ceilingz = tmceilingz; + mo->floorrover = tmfloorrover; + mo->ceilingrover = tmceilingrover; P_SetTarget(&tmthing, ptmthing); break; } @@ -451,6 +455,8 @@ static int mobj_set(lua_State *L) P_CheckPosition(mo, mo->x, mo->y); mo->floorz = tmfloorz; mo->ceilingz = tmceilingz; + mo->floorrover = tmfloorrover; + mo->ceilingrover = tmceilingrover; P_SetTarget(&tmthing, ptmthing); break; } diff --git a/src/p_local.h b/src/p_local.h index 2676fb030..b98eeae1c 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -326,6 +326,7 @@ void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angl extern boolean floatok; extern fixed_t tmfloorz; extern fixed_t tmceilingz; +extern ffloor_t *tmfloorrover, *tmceilingrover; extern mobj_t *tmfloorthing, *tmhitthing, *tmthing; extern camera_t *mapcampointer; extern fixed_t tmx; diff --git a/src/p_map.c b/src/p_map.c index 0726084d5..648bb2bcc 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -102,6 +102,8 @@ boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z) thing->floorz = tmfloorz; thing->ceilingz = tmceilingz; + thing->floorrover = tmfloorrover; + thing->ceilingrover = tmceilingrover; return true; } @@ -2485,6 +2487,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (thingtop == thing->ceilingz && tmceilingz > thingtop && tmceilingz - thingtop <= maxstep) { thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height; + thing->ceilingrover = tmceilingrover; thing->eflags |= MFE_JUSTSTEPPEDDOWN; } #ifdef ESLOPE @@ -2492,6 +2495,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) else if (tmceilingslope && tmceilingz < thingtop && thingtop - tmceilingz <= maxstep) { thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height; + thing->ceilingrover = tmceilingrover; thing->eflags |= MFE_JUSTSTEPPEDDOWN; } #endif @@ -2499,6 +2503,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) else if (thing->z == thing->floorz && tmfloorz < thing->z && thing->z - tmfloorz <= maxstep) { thing->z = thing->floorz = tmfloorz; + thing->floorrover = tmfloorrover; thing->eflags |= MFE_JUSTSTEPPEDDOWN; } #ifdef ESLOPE @@ -2506,6 +2511,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) else if (tmfloorslope && tmfloorz > thing->z && tmfloorz - thing->z <= maxstep) { thing->z = thing->floorz = tmfloorz; + thing->floorrover = tmfloorrover; thing->eflags |= MFE_JUSTSTEPPEDDOWN; } #endif @@ -2577,6 +2583,8 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) thing->floorz = tmfloorz; thing->ceilingz = tmceilingz; + thing->floorrover = tmfloorrover; + thing->ceilingrover = tmceilingrover; #ifdef ESLOPE if (!(thing->flags & MF_NOCLIPHEIGHT)) @@ -2657,6 +2665,8 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y) thing->floorz = tmfloorz; thing->ceilingz = tmceilingz; + thing->floorrover = tmfloorrover; + thing->ceilingrover = tmceilingrover; thing->x = x; thing->y = y; diff --git a/src/p_mobj.c b/src/p_mobj.c index d433561ae..7c9baf0f1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8027,6 +8027,8 @@ void P_MobjThinker(mobj_t *mobj) return; mobj->floorz = tmfloorz; mobj->ceilingz = tmceilingz; + mobj->floorrover = tmfloorrover; + mobj->ceilingrover = tmceilingrover; if ((mobj->eflags & MFE_UNDERWATER) && mobj->health > 0) { @@ -8545,6 +8547,8 @@ void P_SceneryThinker(mobj_t *mobj) return; mobj->floorz = tmfloorz; mobj->ceilingz = tmceilingz; + mobj->floorrover = tmfloorrover; + mobj->ceilingrover = tmceilingrover; } else { diff --git a/src/p_polyobj.c b/src/p_polyobj.c index fd3237c9d..23e799d06 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -985,6 +985,8 @@ static void Polyobj_pushThing(polyobj_t *po, line_t *line, mobj_t *mo) P_CheckPosition(mo, mo->x + momx, mo->y + momy); mo->floorz = tmfloorz; mo->ceilingz = tmceilingz; + mo->floorrover = tmfloorrover; + mo->ceilingrover = tmceilingrover; } } From 002f1bad8fe8741590b362f62a3a092ce77e0e49 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 12:01:50 -0400 Subject: [PATCH 091/306] Savegame netsync for sector colormaps; add spawn_midmap and co for comparison --- src/p_saveg.c | 74 ++++++++++++++++++++++++++++++++++++++------------- src/p_setup.c | 5 ++-- src/p_spec.c | 2 +- src/r_defs.h | 1 + 4 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 22d43f358..1c9589e8f 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -487,10 +487,16 @@ static void P_NetUnArchivePlayers(void) #define SD_FYOFFS 0x02 #define SD_CXOFFS 0x04 #define SD_CYOFFS 0x08 -#define SD_TAG 0x10 -#define SD_FLOORANG 0x20 -#define SD_CEILANG 0x40 -#define SD_TAGLIST 0x80 +#define SD_FLOORANG 0x10 +#define SD_CEILANG 0x20 +#define SD_TAG 0x40 +#define SD_DIFF3 0x80 + +// diff3 flags +#define SD_TAGLIST 0x01 +#define SD_BOTTOMMAP 0x02 +#define SD_MIDMAP 0x04 +#define SD_TOPMAP 0x08 #define LD_FLAG 0x01 #define LD_SPECIAL 0x02 @@ -523,7 +529,7 @@ static void P_NetArchiveWorld(void) mapsidedef_t *msd; maplinedef_t *mld; const sector_t *ss = sectors; - UINT8 diff, diff2; + UINT8 diff, diff2, diff3; WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD); put = save_p; @@ -550,7 +556,7 @@ static void P_NetArchiveWorld(void) for (i = 0; i < numsectors; i++, ss++, ms++) { - diff = diff2 = 0; + diff = diff2 = diff3 = 0; if (ss->floorheight != SHORT(ms->floorheight)<ceilingheight != SHORT(ms->ceilingheight)<tag != SHORT(ms->tag)) diff2 |= SD_TAG; if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag) - diff2 |= SD_TAGLIST; + diff3 |= SD_TAGLIST; + if (ss->bottommap != ss->spawn_bottommap) + diff3 |= SD_BOTTOMMAP; + if (ss->midmap != ss->spawn_midmap) + diff3 |= SD_MIDMAP; + if (ss->topmap != ss->spawn_topmap) + diff3 |= SD_TOPMAP; // Check if any of the sector's FOFs differ from how they spawned if (ss->ffloors) @@ -601,6 +613,9 @@ static void P_NetArchiveWorld(void) } } + if (diff3) + diff2 |= SD_DIFF3; + if (diff2) diff |= SD_DIFF2; @@ -612,6 +627,8 @@ static void P_NetArchiveWorld(void) WRITEUINT8(put, diff); if (diff & SD_DIFF2) WRITEUINT8(put, diff2); + if (diff2 & SD_DIFF3) + WRITEUINT8(put, diff3); if (diff & SD_FLOORHT) WRITEFIXED(put, ss->floorheight); if (diff & SD_CEILHT) @@ -632,17 +649,23 @@ static void P_NetArchiveWorld(void) WRITEFIXED(put, ss->ceiling_xoffs); if (diff2 & SD_CYOFFS) WRITEFIXED(put, ss->ceiling_yoffs); - if (diff2 & SD_TAG) // save only the tag - WRITEINT16(put, ss->tag); if (diff2 & SD_FLOORANG) WRITEANGLE(put, ss->floorpic_angle); if (diff2 & SD_CEILANG) WRITEANGLE(put, ss->ceilingpic_angle); - if (diff2 & SD_TAGLIST) // save both firsttag and nexttag + if (diff2 & SD_TAG) // save only the tag + WRITEINT16(put, ss->tag); + if (diff3 & SD_TAGLIST) // save both firsttag and nexttag { // either of these could be changed even if tag isn't WRITEINT32(put, ss->firsttag); WRITEINT32(put, ss->nexttag); } + if (diff3 & SD_BOTTOMMAP) + WRITEINT32(put, ss->bottommap); + if (diff3 & SD_MIDMAP) + WRITEINT32(put, ss->midmap); + if (diff3 & SD_TOPMAP) + WRITEINT32(put, ss->topmap); // Special case: save the stats of all modified ffloors along with their ffloor "number"s // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed @@ -680,7 +703,7 @@ static void P_NetArchiveWorld(void) // do lines for (i = 0; i < numlines; i++, mld++, li++) { - diff = diff2 = 0; + diff = diff2 = diff3 = 0; if (li->special != SHORT(mld->special)) diff |= LD_SPECIAL; @@ -772,7 +795,7 @@ static void P_NetUnArchiveWorld(void) line_t *li; side_t *si; UINT8 *get; - UINT8 diff, diff2; + UINT8 diff, diff2, diff3; if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD) I_Error("Bad $$$.sav at archive block World"); @@ -794,6 +817,10 @@ static void P_NetUnArchiveWorld(void) diff2 = READUINT8(get); else diff2 = 0; + if (diff2 & SD_DIFF3) + diff3 = READUINT8(get); + else + diff3 = 0; if (diff & SD_FLOORHT) sectors[i].floorheight = READFIXED(get); @@ -822,17 +849,23 @@ static void P_NetUnArchiveWorld(void) sectors[i].ceiling_xoffs = READFIXED(get); if (diff2 & SD_CYOFFS) sectors[i].ceiling_yoffs = READFIXED(get); - if (diff2 & SD_TAG) - sectors[i].tag = READINT16(get); // DON'T use P_ChangeSectorTag - if (diff2 & SD_TAGLIST) - { - sectors[i].firsttag = READINT32(get); - sectors[i].nexttag = READINT32(get); - } if (diff2 & SD_FLOORANG) sectors[i].floorpic_angle = READANGLE(get); if (diff2 & SD_CEILANG) sectors[i].ceilingpic_angle = READANGLE(get); + if (diff2 & SD_TAG) + sectors[i].tag = READINT16(get); // DON'T use P_ChangeSectorTag + if (diff3 & SD_TAGLIST) + { + sectors[i].firsttag = READINT32(get); + sectors[i].nexttag = READINT32(get); + } + if (diff3 & SD_BOTTOMMAP) + sectors[i].bottommap = READINT32(get); + if (diff3 & SD_MIDMAP) + sectors[i].midmap = READINT32(get); + if (diff3 & SD_TOPMAP) + sectors[i].topmap = READINT32(get); if (diff & SD_FFLOORS) { @@ -891,6 +924,9 @@ static void P_NetUnArchiveWorld(void) diff2 = READUINT8(get); else diff2 = 0; + + diff3 = 0; + if (diff & LD_FLAG) li->flags = READINT16(get); if (diff & LD_SPECIAL) diff --git a/src/p_setup.c b/src/p_setup.c index 92a618b98..50b2e8eda 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -719,6 +719,7 @@ static void P_LoadRawSectors(UINT8 *data, size_t i) ss->floorpic_angle = ss->ceilingpic_angle = 0; ss->spawn_flrpic_angle = ss->spawn_ceilpic_angle = 0; ss->bottommap = ss->midmap = ss->topmap = -1; + ss->spawn_bottommap = ss->spawn_midmap = ss->spawn_topmap = -1; ss->gravity = NULL; ss->cullheight = NULL; ss->verticalflip = false; @@ -1477,7 +1478,7 @@ static void P_LoadRawSideDefs2(void *data) { if (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#') { - sec->midmap = R_CreateColormap(msd->toptexture, msd->midtexture, + sec->midmap = sec->spawn_midmap = R_CreateColormap(msd->toptexture, msd->midtexture, msd->bottomtexture); sd->toptexture = sd->bottomtexture = 0; } @@ -1507,7 +1508,7 @@ static void P_LoadRawSideDefs2(void *data) { char *col; - sec->midmap = R_CreateColormap(msd->toptexture, msd->midtexture, + sec->midmap = sec->spawn_midmap = R_CreateColormap(msd->toptexture, msd->midtexture, msd->bottomtexture); sd->toptexture = sd->bottomtexture = 0; #define HEX2INT(x) (x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) diff --git a/src/p_spec.c b/src/p_spec.c index 87a0bae9c..40be3c7fb 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6769,7 +6769,7 @@ void P_SpawnSpecials(INT32 fromnetsave) case 606: // HACK! Copy colormaps. Just plain colormaps. for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - sectors[s].midmap = lines[i].frontsector->midmap; + sectors[s].midmap = sectors[s].spawn_midmap = lines[i].frontsector->midmap; break; #ifdef ESLOPE // Slope copy specials. Handled here for sanity. diff --git a/src/r_defs.h b/src/r_defs.h index 7c8f2a73f..f219f0f9e 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -385,6 +385,7 @@ typedef struct sector_s // these are saved for netgames, so do not let Lua touch these! INT32 spawn_nexttag, spawn_firsttag; // the actual nexttag/firsttag values may differ if the sector's tag was changed + INT32 spawn_bottommap, spawn_midmap, spawn_topmap; // offsets sector spawned with (via linedef type 7) fixed_t spawn_flr_xoffs, spawn_flr_yoffs; From e171e565ceb794ac50109f8687b77a5609c1c5fb Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 09:03:58 -0400 Subject: [PATCH 092/306] Remove bottommap and topmap from savegame because unused --- src/p_saveg.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 1c9589e8f..42757faf2 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -494,9 +494,7 @@ static void P_NetUnArchivePlayers(void) // diff3 flags #define SD_TAGLIST 0x01 -#define SD_BOTTOMMAP 0x02 -#define SD_MIDMAP 0x04 -#define SD_TOPMAP 0x08 +#define SD_MIDMAP 0x02 #define LD_FLAG 0x01 #define LD_SPECIAL 0x02 @@ -591,12 +589,8 @@ static void P_NetArchiveWorld(void) diff2 |= SD_TAG; if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag) diff3 |= SD_TAGLIST; - if (ss->bottommap != ss->spawn_bottommap) - diff3 |= SD_BOTTOMMAP; if (ss->midmap != ss->spawn_midmap) diff3 |= SD_MIDMAP; - if (ss->topmap != ss->spawn_topmap) - diff3 |= SD_TOPMAP; // Check if any of the sector's FOFs differ from how they spawned if (ss->ffloors) @@ -660,12 +654,8 @@ static void P_NetArchiveWorld(void) WRITEINT32(put, ss->firsttag); WRITEINT32(put, ss->nexttag); } - if (diff3 & SD_BOTTOMMAP) - WRITEINT32(put, ss->bottommap); if (diff3 & SD_MIDMAP) WRITEINT32(put, ss->midmap); - if (diff3 & SD_TOPMAP) - WRITEINT32(put, ss->topmap); // Special case: save the stats of all modified ffloors along with their ffloor "number"s // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed @@ -860,12 +850,8 @@ static void P_NetUnArchiveWorld(void) sectors[i].firsttag = READINT32(get); sectors[i].nexttag = READINT32(get); } - if (diff3 & SD_BOTTOMMAP) - sectors[i].bottommap = READINT32(get); if (diff3 & SD_MIDMAP) sectors[i].midmap = READINT32(get); - if (diff3 & SD_TOPMAP) - sectors[i].topmap = READINT32(get); if (diff & SD_FFLOORS) { From b8da218b6113255f6788953b4e5345afdcb7aabd Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 09:48:24 -0400 Subject: [PATCH 093/306] Add relative destvalue calc (ML_EFFECT4) * rover->alpha init fixes with invisible FOFs --- src/p_spec.c | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 4cd9e5cb8..713291e15 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -108,7 +108,7 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, boolean ticbased, INT32 *timer, UINT32 interval, boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha); static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, - INT16 destvalue, INT16 speed, boolean ticbased, + INT16 destvalue, INT16 speed, boolean ticbased, boolean relative, boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); @@ -3357,6 +3357,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_AddFakeFloorFader(rover, secnum, j, destvalue, speed, (line->flags & ML_EFFECT5), // tic-based logic + (line->flags & ML_EFFECT4), // Relative destvalue !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT !(line->flags & ML_EFFECT2), // do not handle lighting @@ -3365,10 +3366,20 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) else { + // If fading an invisible FOF whose render flags we did not yet set, + // initialize its alpha to 1 + if (!(line->flags & ML_NOCLIMB) && // do translucent + (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES) && + !(rover->flags & FF_RENDERALL)) + rover->alpha = 1; + P_RemoveFakeFloorFader(rover); P_FadeFakeFloor(rover, - destvalue, 0, // set alpha immediately - false, NULL, 0, // tic-based logic + max(1, min(256, (line->flags & ML_EFFECT4) ? rover->alpha + destvalue : destvalue)), + 0, // set alpha immediately + false, NULL, 0, // tic-based logic !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT !(line->flags & ML_EFFECT2), // do not handle lighting @@ -7710,6 +7721,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, bo * \param destvalue transparency value to fade to * \param speed speed to fade by * \param ticbased tic-based logic, speed = duration + * \param relative Destvalue is relative to rover->alpha * \param doexists handle FF_EXISTS * \param dotranslucent handle FF_TRANSLUCENT * \param dolighting fade FOF light @@ -7718,20 +7730,9 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, bo * \param exactalpha use exact alpha values (opengl) */ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, - INT16 destvalue, INT16 speed, boolean ticbased, + INT16 destvalue, INT16 speed, boolean ticbased, boolean relative, boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha) { - // already equal, nothing to do - if (rover->alpha == max(1, min(256, destvalue))) - return; - - fade_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); - - d->thinker.function.acp1 = (actionf_p1)T_Fade; - d->rover = rover; - d->sectornum = (UINT32)sectornum; - d->ffloornum = (UINT32)ffloornum; - // If fading an invisible FOF whose render flags we did not yet set, // initialize its alpha to 1 if (dotranslucent && @@ -7741,8 +7742,19 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor !(rover->flags & FF_RENDERALL)) rover->alpha = 1; + // already equal, nothing to do + if (rover->alpha == max(1, min(256, relative ? rover->alpha + destvalue : destvalue))) + return; + + fade_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); + + d->thinker.function.acp1 = (actionf_p1)T_Fade; + d->rover = rover; + d->sectornum = (UINT32)sectornum; + d->ffloornum = (UINT32)ffloornum; + d->alpha = rover->alpha; - d->destvalue = max(1, min(256, destvalue)); // ffloor->alpha is 1-256 + d->destvalue = max(1, min(256, relative ? rover->alpha + destvalue : destvalue)); // ffloor->alpha is 1-256 if (ticbased) { From 02a94dc9415948be143b5509cbefa10dde56d4e5 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 09:49:52 -0400 Subject: [PATCH 094/306] Add distance-based params and make default (ML_DONTPEGBOTTOM to use back offsets) --- src/p_spec.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 713291e15..0afb267df 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3322,8 +3322,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 452: // Fade FOF { - INT16 destvalue = (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS); - INT16 speed = (INT16)(sides[line->sidenum[1]].rowoffset>>FRACBITS); + INT16 destvalue = (line->flags & ML_DONTPEGBOTTOM) && line->sidenum[1] != 0xffff ? + (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : (INT16)(line->dx>>FRACBITS); + INT16 speed = (line->flags & ML_DONTPEGBOTTOM) && line->sidenum[1] != 0xffff ? + (INT16)(sides[line->sidenum[1]].rowoffset>>FRACBITS) : (INT16)(abs(line->dy)>>FRACBITS); INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in @@ -3355,7 +3357,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (speed > 0) P_AddFakeFloorFader(rover, secnum, j, - destvalue, speed, + destvalue, + speed, (line->flags & ML_EFFECT5), // tic-based logic (line->flags & ML_EFFECT4), // Relative destvalue !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS From da5a7a013d584cd76b5ff9465a86b13d401789c3 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 10:09:02 -0400 Subject: [PATCH 095/306] Add type 452 Set FOF Alpha * Fade FOF moved to type 453 * Stop Fade FOF moved to type 454 --- src/p_spec.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 0afb267df..fe742457e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3320,7 +3320,63 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; } - case 452: // Fade FOF + case 452: // Set FOF alpha + { + INT16 destvalue = (line->flags & ML_DONTPEGBOTTOM) && line->sidenum[1] != 0xffff ? + (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : (INT16)(line->dx>>FRACBITS); + INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + sector_t *sec; // Sector that the FOF is visible in + ffloor_t *rover; // FOF that we are going to operate + + for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) + { + sec = sectors + secnum; + + if (!sec->ffloors) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Target sector #%d has no FOFs.\n", secnum); + return; + } + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (rover->master->frontsector->tag == foftag) + break; + } + + if (!rover) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Can't find a FOF control sector with tag %d\n", foftag); + return; + } + + // If fading an invisible FOF whose render flags we did not yet set, + // initialize its alpha to 1 + // for relative alpha calc + if (!(line->flags & ML_NOCLIMB) && // do translucent + (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES) && + !(rover->flags & FF_RENDERALL)) + rover->alpha = 1; + + P_RemoveFakeFloorFader(rover); + P_FadeFakeFloor(rover, + max(1, min(256, (line->flags & ML_EFFECT4) ? rover->alpha + destvalue : destvalue)), + 0, // set alpha immediately + false, NULL, 0, // tic-based logic + false, // do not handle FF_EXISTS + true, // handle FF_TRANSLUCENT + false, // do not handle lighting + false, // do not handle collision + false, // do not do ghost fade (no collision during fade) + true); // use exact alpha values (for opengl) + } + break; + } + + case 453: // Fade FOF { INT16 destvalue = (line->flags & ML_DONTPEGBOTTOM) && line->sidenum[1] != 0xffff ? (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : (INT16)(line->dx>>FRACBITS); @@ -3338,7 +3394,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!sec->ffloors) { - CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Target sector #%d has no FOFs.\n", secnum); + CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Target sector #%d has no FOFs.\n", secnum); return; } @@ -3351,7 +3407,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!rover) { - CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Can't find a FOF control sector with tag %d\n", foftag); + CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Can't find a FOF control sector with tag %d\n", foftag); return; } @@ -3371,6 +3427,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { // If fading an invisible FOF whose render flags we did not yet set, // initialize its alpha to 1 + // for relative alpha calc if (!(line->flags & ML_NOCLIMB) && // do translucent (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE !(rover->spawnflags & FF_RENDERSIDES) && @@ -3394,7 +3451,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; } - case 453: // Stop fading FOF + case 454: // Stop fading FOF { INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); @@ -3407,7 +3464,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!sec->ffloors) { - CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Target sector #%d has no FOFs.\n", secnum); + CONS_Debug(DBG_GAMELOGIC, "Line type 454 Executor: Target sector #%d has no FOFs.\n", secnum); return; } @@ -3419,7 +3476,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!rover) { - CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Can't find a FOF control sector with tag %d\n", foftag); + CONS_Debug(DBG_GAMELOGIC, "Line type 454 Executor: Can't find a FOF control sector with tag %d\n", foftag); return; } From 8e75fe50db1333fdf0b7c7b02ce16eefe3e094be Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 10:11:27 -0400 Subject: [PATCH 096/306] Default to using back offset params if back linedef exists; else fallback to distance-based params --- src/p_spec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index fe742457e..f5915b4d6 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3322,8 +3322,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 452: // Set FOF alpha { - INT16 destvalue = (line->flags & ML_DONTPEGBOTTOM) && line->sidenum[1] != 0xffff ? - (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : (INT16)(line->dx>>FRACBITS); + INT16 destvalue = line->sidenum[1] != 0xffff ? + (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : (INT16)(P_AproxDistance(line->dx, line->dy)>>FRACBITS); INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in @@ -3378,9 +3378,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 453: // Fade FOF { - INT16 destvalue = (line->flags & ML_DONTPEGBOTTOM) && line->sidenum[1] != 0xffff ? + INT16 destvalue = line->sidenum[1] != 0xffff ? (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : (INT16)(line->dx>>FRACBITS); - INT16 speed = (line->flags & ML_DONTPEGBOTTOM) && line->sidenum[1] != 0xffff ? + INT16 speed = line->sidenum[1] != 0xffff ? (INT16)(sides[line->sidenum[1]].rowoffset>>FRACBITS) : (INT16)(abs(line->dy)>>FRACBITS); INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); From 148e3ff538061c8e20e5e657ea622ad9c86387bf Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 10:17:39 -0400 Subject: [PATCH 097/306] Use ML_NOCLIMB for FF_TRANSLUCENT handling in type 452 --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index f5915b4d6..f397f5b75 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3367,7 +3367,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) 0, // set alpha immediately false, NULL, 0, // tic-based logic false, // do not handle FF_EXISTS - true, // handle FF_TRANSLUCENT + !(line->flags & ML_NOCLIMB), // handle FF_TRANSLUCENT false, // do not handle lighting false, // do not handle collision false, // do not do ghost fade (no collision during fade) From 40ff43682971987413b56721d03b5bd8a2daba9a Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 10 Sep 2018 15:49:21 +0100 Subject: [PATCH 098/306] Remove commented out stuff, now I've confirmed everything works fine without them --- src/p_setup.c | 1 - src/r_data.c | 191 -------------------------------------------------- src/r_data.h | 2 - 3 files changed, 194 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 58170e262..17a6797f4 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2673,7 +2673,6 @@ boolean P_SetupLevel(boolean skipprecip) P_CreateBlockMap(); // Graue 02-29-2004 P_LoadSideDefs2(lastloadedmaplumpnum + ML_SIDEDEFS); - //R_MakeColormaps(); P_LoadLineDefs2(); P_LoadSubsectors(lastloadedmaplumpnum + ML_SSECTORS); P_LoadNodes(lastloadedmaplumpnum + ML_NODES); diff --git a/src/r_data.c b/src/r_data.c index 2551a2946..f2c9b1466 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1038,9 +1038,6 @@ void R_ReInitColormaps(UINT16 num) static lumpnum_t foundcolormaps[MAXCOLORMAPS]; -//static char colormapFixingArray[MAXCOLORMAPS][3][9]; -//static size_t carrayindex; - // // R_ClearColormaps // @@ -1052,8 +1049,6 @@ void R_ClearColormaps(void) num_extra_colormaps = 0; - //carrayindex = 0; - for (i = 0; i < MAXCOLORMAPS; i++) foundcolormaps[i] = LUMPERROR; @@ -1194,10 +1189,6 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) if (num_extra_colormaps == MAXCOLORMAPS) I_Error("R_CreateColormap: Too many colormaps! the limit is %d\n", MAXCOLORMAPS); - //strncpy(colormapFixingArray[num_extra_colormaps][0], p1, 8); - //strncpy(colormapFixingArray[num_extra_colormaps][1], p2, 8); - //strncpy(colormapFixingArray[num_extra_colormaps][2], p3, 8); - num_extra_colormaps++; foundcolormaps[mapnum] = LUMPERROR; @@ -1286,188 +1277,6 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) return (INT32)mapnum; } -/* -void R_MakeColormaps(void) -{ - size_t i; - - carrayindex = num_extra_colormaps; - num_extra_colormaps = 0; - - for (i = 0; i < carrayindex; i++) - R_CreateColormap2(colormapFixingArray[i][0], colormapFixingArray[i][1], - colormapFixingArray[i][2]); -} - -void R_CreateColormap2(char *p1, char *p2, char *p3) -{ - double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb; - double r, g, b, cbrightness; - double maskamt = 0, othermask = 0; - int mask, p, fog = 0; - size_t mapnum = num_extra_colormaps; - size_t i; - char *colormap_p; - UINT32 cr, cg, cb, maskcolor, fadecolor; - UINT32 fadestart = 0, fadeend = 31, fadedist = 31; - -#define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) - if (p1[0] == '#') - { - cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2])); - cmaskr = cr; - cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4])); - cmaskg = cg; - cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6])); - cmaskb = cb; - // Create a rough approximation of the color (a 16 bit color) - maskcolor = ((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11); - if (p1[7] >= 'a' && p1[7] <= 'z') - mask = (p1[7] - 'a'); - else if (p1[7] >= 'A' && p1[7] <= 'Z') - mask = (p1[7] - 'A'); - else - mask = 24; - - maskamt = (double)(mask/24.0l); - - othermask = 1 - maskamt; - maskamt /= 0xff; - cmaskr *= maskamt; - cmaskg *= maskamt; - cmaskb *= maskamt; - } - else - { - cmaskr = cmaskg = cmaskb = 0xff; - maskamt = 0; - maskcolor = ((0xff) >> 3) + (((0xff) >> 2) << 5) + (((0xff) >> 3) << 11); - } - -#define NUMFROMCHAR(c) (c >= '0' && c <= '9' ? c - '0' : 0) - if (p2[0] == '#') - { - // Get parameters like fadestart, fadeend, and the fogflag - fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10); - fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10); - if (fadestart > 30) - fadestart = 0; - if (fadeend > 31 || fadeend < 1) - fadeend = 31; - fadedist = fadeend - fadestart; - fog = NUMFROMCHAR(p2[1]); - } -#undef NUMFROMCHAR - - if (p3[0] == '#') - { - cdestr = cr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2])); - cdestg = cg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4])); - cdestb = cb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6])); - fadecolor = (((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11)); - } - else - cdestr = cdestg = cdestb = fadecolor = 0; -#undef HEX2INT - - for (i = 0; i < num_extra_colormaps; i++) - { - if (foundcolormaps[i] != LUMPERROR) - continue; - if (maskcolor == extra_colormaps[i].maskcolor - && fadecolor == extra_colormaps[i].fadecolor - && (float)maskamt == (float)extra_colormaps[i].maskamt - && fadestart == extra_colormaps[i].fadestart - && fadeend == extra_colormaps[i].fadeend - && fog == extra_colormaps[i].fog) - { - return; - } - } - - if (num_extra_colormaps == MAXCOLORMAPS) - I_Error("R_CreateColormap: Too many colormaps! the limit is %d\n", MAXCOLORMAPS); - - num_extra_colormaps++; - - if (rendermode == render_soft) - { - for (i = 0; i < 256; i++) - { - r = pLocalPalette[i].s.red; - g = pLocalPalette[i].s.green; - b = pLocalPalette[i].s.blue; - cbrightness = sqrt((r*r) + (g*g) + (b*b)); - - map[i][0] = (cbrightness * cmaskr) + (r * othermask); - if (map[i][0] > 255.0l) - map[i][0] = 255.0l; - deltas[i][0] = (map[i][0] - cdestr) / (double)fadedist; - - map[i][1] = (cbrightness * cmaskg) + (g * othermask); - if (map[i][1] > 255.0l) - map[i][1] = 255.0l; - deltas[i][1] = (map[i][1] - cdestg) / (double)fadedist; - - map[i][2] = (cbrightness * cmaskb) + (b * othermask); - if (map[i][2] > 255.0l) - map[i][2] = 255.0l; - deltas[i][2] = (map[i][2] - cdestb) / (double)fadedist; - } - } - - foundcolormaps[mapnum] = LUMPERROR; - - // aligned on 8 bit for asm code - extra_colormaps[mapnum].colormap = NULL; - extra_colormaps[mapnum].maskcolor = (UINT16)maskcolor; - extra_colormaps[mapnum].fadecolor = (UINT16)fadecolor; - extra_colormaps[mapnum].maskamt = maskamt; - extra_colormaps[mapnum].fadestart = (UINT16)fadestart; - extra_colormaps[mapnum].fadeend = (UINT16)fadeend; - extra_colormaps[mapnum].fog = fog; - -#define ABS2(x) ((x) < 0 ? -(x) : (x)) - if (rendermode == render_soft) - { - colormap_p = Z_MallocAlign((256 * 34) + 10, PU_LEVEL, NULL, 8); - extra_colormaps[mapnum].colormap = (UINT8 *)colormap_p; - - for (p = 0; p < 34; p++) - { - for (i = 0; i < 256; i++) - { - *colormap_p = NearestColor((UINT8)RoundUp(map[i][0]), - (UINT8)RoundUp(map[i][1]), - (UINT8)RoundUp(map[i][2])); - colormap_p++; - - if ((UINT32)p < fadestart) - continue; - - if (ABS2(map[i][0] - cdestr) > ABS2(deltas[i][0])) - map[i][0] -= deltas[i][0]; - else - map[i][0] = cdestr; - - if (ABS2(map[i][1] - cdestg) > ABS2(deltas[i][1])) - map[i][1] -= deltas[i][1]; - else - map[i][1] = cdestg; - - if (ABS2(map[i][2] - cdestb) > ABS2(deltas[i][1])) - map[i][2] -= deltas[i][2]; - else - map[i][2] = cdestb; - } - } - } -#undef ABS2 - - return; -} -*/ - // Thanks to quake2 source! // utils3/qdata/images.c static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) diff --git a/src/r_data.h b/src/r_data.h index c1f2a73da..a656e5db7 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -93,8 +93,6 @@ void R_ReInitColormaps(UINT16 num); void R_ClearColormaps(void); INT32 R_ColormapNumForName(char *name); INT32 R_CreateColormap(char *p1, char *p2, char *p3); -//void R_CreateColormap2(char *p1, char *p2, char *p3); -//void R_MakeColormaps(void); const char *R_ColormapNameForNum(INT32 num); extern INT32 numtextures; From acea0bfd68532524437b096f58d0c50f5cebb315 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 12:00:15 -0400 Subject: [PATCH 099/306] Move tic-based to EFFECT4, relative calc to EFFECT3 --- src/p_spec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index f397f5b75..3a27cd987 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3363,7 +3363,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_RemoveFakeFloorFader(rover); P_FadeFakeFloor(rover, - max(1, min(256, (line->flags & ML_EFFECT4) ? rover->alpha + destvalue : destvalue)), + max(1, min(256, (line->flags & ML_EFFECT3) ? rover->alpha + destvalue : destvalue)), 0, // set alpha immediately false, NULL, 0, // tic-based logic false, // do not handle FF_EXISTS @@ -3415,8 +3415,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_AddFakeFloorFader(rover, secnum, j, destvalue, speed, - (line->flags & ML_EFFECT5), // tic-based logic - (line->flags & ML_EFFECT4), // Relative destvalue + (line->flags & ML_EFFECT4), // tic-based logic + (line->flags & ML_EFFECT3), // Relative destvalue !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT !(line->flags & ML_EFFECT2), // do not handle lighting @@ -3437,7 +3437,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_RemoveFakeFloorFader(rover); P_FadeFakeFloor(rover, - max(1, min(256, (line->flags & ML_EFFECT4) ? rover->alpha + destvalue : destvalue)), + max(1, min(256, (line->flags & ML_EFFECT3) ? rover->alpha + destvalue : destvalue)), 0, // set alpha immediately false, NULL, 0, // tic-based logic !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS From 88d9da79e6433164336663f3df6f66b64662d9ba Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 12:00:44 -0400 Subject: [PATCH 100/306] Move tic-based to EFFECT4 --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 917ad68d4..aa3a81f23 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2781,7 +2781,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_FadeLight(line->tag, (line->flags & ML_DONTPEGBOTTOM) ? max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 255), 0) : line->frontsector->lightlevel, (line->flags & ML_DONTPEGBOTTOM) ? max(sides[line->sidenum[0]].rowoffset>>FRACBITS, 0) : P_AproxDistance(line->dx, line->dy)>>FRACBITS, - (line->flags & ML_EFFECT5)); + (line->flags & ML_EFFECT4)); break; case 421: // Stop lighting effect in tagged sectors From d26ba2ee5451bb53bf15384b1ad7af12ecd665ff Mon Sep 17 00:00:00 2001 From: PrisimaTheFox Date: Sun, 9 Sep 2018 23:16:28 -0500 Subject: [PATCH 101/306] Update m_anigif.c More accurate GIF delay. --- src/m_anigif.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/m_anigif.c b/src/m_anigif.c index 2540665ad..5c7cfbd68 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -492,7 +492,9 @@ static void GIF_framewrite(void) // screen regions are handled in GIF_lzw { - UINT16 delay = 3; // todo + int d1 = (int)((100.0/NEWTICRATE)*gif_frames); + int d2 = (int)((100.0/NEWTICRATE)*(gif_frames-1)); + UINT16 delay = d1-d2; INT32 startline; WRITEMEM(p, gifframe_gchead, 4); From 4ada0b0a9e42f5b3b71cf509bc66f7881104b4aa Mon Sep 17 00:00:00 2001 From: PrisimaTheFox Date: Sun, 9 Sep 2018 23:33:51 -0500 Subject: [PATCH 102/306] Update m_anigif.c Remember gif_frames starts at 0 --- src/m_anigif.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_anigif.c b/src/m_anigif.c index 5c7cfbd68..d46d889bb 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -492,8 +492,8 @@ static void GIF_framewrite(void) // screen regions are handled in GIF_lzw { - int d1 = (int)((100.0/NEWTICRATE)*gif_frames); - int d2 = (int)((100.0/NEWTICRATE)*(gif_frames-1)); + int d1 = (int)((100.0/NEWTICRATE)*gif_frames+1); + int d2 = (int)((100.0/NEWTICRATE)*(gif_frames)); UINT16 delay = d1-d2; INT32 startline; From e33ed45b7b774a819812d4f7887bd93c107206cc Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 15:59:31 -0400 Subject: [PATCH 103/306] Colormap overhaul in r_data.c * Split R_CreateColormap to R_CreateLightTable * Replace extra_colormaps array with next/prev pointer chain * Remove foundcolormaps; instead store lumpnum in extracolormap_t * Add properties to extracolormap_t for portability --- src/r_data.c | 333 ++++++++++++++++++++++++++++++++------------------ src/r_data.h | 3 +- src/r_defs.h | 12 +- src/r_state.h | 3 +- 4 files changed, 226 insertions(+), 125 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 18c93787c..1c964993f 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1311,8 +1311,6 @@ void R_ReInitColormaps(UINT16 num) R_ClearColormaps(); } -static lumpnum_t foundcolormaps[MAXCOLORMAPS]; - // // R_ClearColormaps // @@ -1320,48 +1318,73 @@ static lumpnum_t foundcolormaps[MAXCOLORMAPS]; // void R_ClearColormaps(void) { - size_t i; + extracolormap_t *exc, *exc_next; - num_extra_colormaps = 0; + for (exc = extra_colormaps; exc; exc = exc_next) + { + exc_next = exc->next; + memset(exc, 0, sizeof(exc)); + } - for (i = 0; i < MAXCOLORMAPS; i++) - foundcolormaps[i] = LUMPERROR; + extra_colormaps = NULL; +} - memset(extra_colormaps, 0, sizeof (extra_colormaps)); +// +// R_AddColormapToList +// +// Sets prev/next chain for extra_colormaps var +// Copypasta from P_AddFFloorToList +// +void R_AddColormapToList(extracolormap_t *extra_colormap) +{ + extracolormap_t *exc; + + if (!extra_colormaps) + { + extra_colormaps = extra_colormap; + extra_colormap->next = 0; + extra_colormap->prev = 0; + return; + } + + for (exc = extra_colormaps; exc->next; exc = exc->next); + + exc->next = extra_colormap; + extra_colormap->prev = exc; + extra_colormap->next = 0; } INT32 R_ColormapNumForName(char *name) { - lumpnum_t lump, i; - - if (num_extra_colormaps == MAXCOLORMAPS) - I_Error("R_ColormapNumForName: Too many colormaps! the limit is %d\n", MAXCOLORMAPS); + lumpnum_t lump; + extracolormap_t *exc; lump = R_CheckNumForNameList(name, colormaplumps, numcolormaplumps); if (lump == LUMPERROR) I_Error("R_ColormapNumForName: Cannot find colormap lump %.8s\n", name); - for (i = 0; i < num_extra_colormaps; i++) - if (lump == foundcolormaps[i]) - return i; + for (exc = extra_colormaps; exc; exc = exc->next) + if (lump == exc->lump) + return exc; - foundcolormaps[num_extra_colormaps] = lump; + exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); + + exc->lump = lump; // aligned on 8 bit for asm code - extra_colormaps[num_extra_colormaps].colormap = Z_MallocAlign(W_LumpLength(lump), PU_LEVEL, NULL, 16); - W_ReadLump(lump, extra_colormaps[num_extra_colormaps].colormap); + exc->colormap = Z_MallocAlign(W_LumpLength(lump), PU_LEVEL, NULL, 16); + W_ReadLump(lump, exc->colormap); // We set all params of the colormap to normal because there // is no real way to tell how GL should handle a colormap lump anyway.. - extra_colormaps[num_extra_colormaps].maskcolor = 0xffff; - extra_colormaps[num_extra_colormaps].fadecolor = 0x0; - extra_colormaps[num_extra_colormaps].maskamt = 0x0; - extra_colormaps[num_extra_colormaps].fadestart = 0; - extra_colormaps[num_extra_colormaps].fadeend = 31; - extra_colormaps[num_extra_colormaps].fog = 0; + exc->maskcolor = 0xffff; + exc->fadecolor = 0x0; + exc->maskamt = 0x0; + exc->fadestart = 0; + exc->fadeend = 31; + exc->fog = 0; - num_extra_colormaps++; - return (INT32)num_extra_colormaps - 1; + return exc; } // @@ -1377,105 +1400,30 @@ static double deltas[256][3], map[256][3]; static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); static int RoundUp(double number); -INT32 R_CreateColormap(char *p1, char *p2, char *p3) +lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) { - double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb; - double maskamt = 0, othermask = 0; - int mask, fog = 0; - size_t mapnum = num_extra_colormaps; - size_t i; - UINT32 cr, cg, cb, maskcolor, fadecolor; - UINT32 fadestart = 0, fadeend = 31, fadedist = 31; + // "Unpackage" our variables for ease of reading below + UINT32 maskcolor = (UINT32)extra_colormap->maskcolor, + fadecolor = (UINT32)extra_colormap->fadecolor, + fadestart = (UINT16)extra_colormap->fadestart, + fadeend = (UINT16)extra_colormap->fadeend, + fadedist = extra_colormap->fadedist; -#define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) - if (p1[0] == '#') - { - cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2])); - cmaskr = cr; - cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4])); - cmaskg = cg; - cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6])); - cmaskb = cb; - // Create a rough approximation of the color (a 16 bit color) - maskcolor = ((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11); - if (p1[7] >= 'a' && p1[7] <= 'z') - mask = (p1[7] - 'a'); - else if (p1[7] >= 'A' && p1[7] <= 'Z') - mask = (p1[7] - 'A'); - else - mask = 24; + double maskamt = extra_colormap->maskamt, + othermask = extra_colormap->othermask, + cmaskr = extra_colormap->cmaskr, + cmaskg = extra_colormap->cmaskg, + cmaskb = extra_colormap->cmaskb, + cdestr = extra_colormap->cdestr, + cdestg = extra_colormap->cdestg, + cdestb = extra_colormap->cdestb; - maskamt = (double)(mask/24.0l); + int fog = extra_colormap->fog; - othermask = 1 - maskamt; - maskamt /= 0xff; - cmaskr *= maskamt; - cmaskg *= maskamt; - cmaskb *= maskamt; - } - else - { - cmaskr = cmaskg = cmaskb = 0xff; - maskamt = 0; - maskcolor = ((0xff) >> 3) + (((0xff) >> 2) << 5) + (((0xff) >> 3) << 11); - } + INT32 rgba = extra_colormap->rgba, + fadergba = extra_colormap->fadergba; -#define NUMFROMCHAR(c) (c >= '0' && c <= '9' ? c - '0' : 0) - if (p2[0] == '#') - { - // Get parameters like fadestart, fadeend, and the fogflag - fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10); - fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10); - if (fadestart > 30) - fadestart = 0; - if (fadeend > 31 || fadeend < 1) - fadeend = 31; - fadedist = fadeend - fadestart; - fog = NUMFROMCHAR(p2[1]); - } -#undef NUMFROMCHAR - - if (p3[0] == '#') - { - cdestr = cr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2])); - cdestg = cg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4])); - cdestb = cb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6])); - fadecolor = (((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11)); - } - else - cdestr = cdestg = cdestb = fadecolor = 0; -#undef HEX2INT - - for (i = 0; i < num_extra_colormaps; i++) - { - if (foundcolormaps[i] != LUMPERROR) - continue; - if (maskcolor == extra_colormaps[i].maskcolor - && fadecolor == extra_colormaps[i].fadecolor - && (float)maskamt == (float)extra_colormaps[i].maskamt - && fadestart == extra_colormaps[i].fadestart - && fadeend == extra_colormaps[i].fadeend - && fog == extra_colormaps[i].fog) - { - return (INT32)i; - } - } - - if (num_extra_colormaps == MAXCOLORMAPS) - I_Error("R_CreateColormap: Too many colormaps! the limit is %d\n", MAXCOLORMAPS); - - num_extra_colormaps++; - - foundcolormaps[mapnum] = LUMPERROR; - - // aligned on 8 bit for asm code - extra_colormaps[mapnum].colormap = NULL; - extra_colormaps[mapnum].maskcolor = (UINT16)maskcolor; - extra_colormaps[mapnum].fadecolor = (UINT16)fadecolor; - extra_colormaps[mapnum].maskamt = maskamt; - extra_colormaps[mapnum].fadestart = (UINT16)fadestart; - extra_colormaps[mapnum].fadeend = (UINT16)fadeend; - extra_colormaps[mapnum].fog = fog; + lighttable_t *lighttable; // This code creates the colormap array used by software renderer if (rendermode == render_soft) @@ -1513,8 +1461,9 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) } // Now allocate memory for the actual colormap array itself! + // aligned on 8 bit for asm code colormap_p = Z_MallocAlign((256 * 34) + 10, PU_LEVEL, NULL, 8); - extra_colormaps[mapnum].colormap = (UINT8 *)colormap_p; + lighttable = (UINT8 *)colormap_p; // Calculate the palette index for each palette index, for each light level // (as well as the two unused colormap lines we inherited from Doom) @@ -1549,7 +1498,149 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) } } - return (INT32)mapnum; + return lighttable; +} + +extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) +{ + double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb; + double maskamt = 0, othermask = 0; + int mask, fog = 0; + extracolormap_t *extra_colormap, *exc; + + UINT32 cr, cg, cb, maskcolor, fadecolor; + UINT32 fadestart = 0, fadeend = 31, fadedist = 31; + + INT32 rgba, fadergba; + +#define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) + if (p1[0] == '#') + { + cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2])); + cmaskr = cr; + cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4])); + cmaskg = cg; + cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6])); + cmaskb = cb; + // Create a rough approximation of the color (a 16 bit color) + maskcolor = ((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11); + if (p1[7] >= 'a' && p1[7] <= 'z') + mask = (p1[7] - 'a'); + else if (p1[7] >= 'A' && p1[7] <= 'Z') + mask = (p1[7] - 'A'); + else + mask = 24; + + maskamt = (double)(mask/24.0l); + + othermask = 1 - maskamt; + maskamt /= 0xff; + cmaskr *= maskamt; + cmaskg *= maskamt; + cmaskb *= maskamt; + + // package up cmask vars for passing around + maskrgba = + + // for opengl; generate on software too for netsync + rgba = (HEX2INT(p1[1]) << 4) + (HEX2INT(p1[2]) << 0) + + (HEX2INT(p1[3]) << 12) + (HEX2INT(p1[4]) << 8) + + (HEX2INT(p1[5]) << 20) + (HEX2INT(p1[6]) << 16); + + if (p1[7] >= 'a' && p1[7] <= 'z' || p1[7] >= 'A' && p1[7] <= 'Z') + rgba += (ALPHA2INT(p1[7]) << 24); + else + rgba += (25 << 24); + } + else + { + cmaskr = cmaskg = cmaskb = 0xff; + maskamt = 0; + maskcolor = ((0xff) >> 3) + (((0xff) >> 2) << 5) + (((0xff) >> 3) << 11); + rgba = 0; + } + +#define NUMFROMCHAR(c) (c >= '0' && c <= '9' ? c - '0' : 0) + if (p2[0] == '#') + { + // Get parameters like fadestart, fadeend, and the fogflag + fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10); + fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10); + if (fadestart > 30) + fadestart = 0; + if (fadeend > 31 || fadeend < 1) + fadeend = 31; + fadedist = fadeend - fadestart; + fog = NUMFROMCHAR(p2[1]); + } +#undef NUMFROMCHAR + + if (p3[0] == '#') + { + cdestr = cr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2])); + cdestg = cg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4])); + cdestb = cb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6])); + fadecolor = (((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11)); + + // for opengl; generate on software too for netsync + fadergba = (HEX2INT(p3[1]) << 4) + (HEX2INT(p3[2]) << 0) + + (HEX2INT(p3[3]) << 12) + (HEX2INT(p3[4]) << 8) + + (HEX2INT(p3[5]) << 20) + (HEX2INT(p3[6]) << 16); + + if (p3[7] >= 'a' && p3[7] <= 'z' || p3[7] >= 'A' && p3[7] <= 'Z') + fadergba += (ALPHA2INT(p3[7]) << 24); + else + fadergba += (25 << 24); + } + else + { + cdestr = cdestg = cdestb = fadecolor = 0; + fadergba = 0x19000000; // default alpha for fade, (25 << 24) + } +#undef HEX2INT + + for (exc = extra_colormaps; exc; exc = exc->next) + { + if (exc->lump) + continue; + if (maskcolor == exc->maskcolor + && fadecolor == exc->fadecolor + && (float)maskamt == (float)exc->maskamt + && fadestart == exc->fadestart + && fadeend == exc->fadeend + && fog == exc->fog) + return exc; + } + + extra_colormap = Z_Calloc(sizeof (*extra_colormap), PU_LEVEL, NULL); + + extra_colormap->maskcolor = (UINT16)maskcolor; + extra_colormap->fadecolor = (UINT16)fadecolor; + extra_colormap->maskamt = maskamt; + extra_colormap->othermask = othermask; + extra_colormap->fadestart = (UINT16)fadestart; + extra_colormap->fadeend = (UINT16)fadeend; + extra_colormap->fadedist = fadedist; + extra_colormap->fog = fog; + + extra_colormap->cmaskr = cmaskr; + extra_colormap->cmaskg = cmaskg; + extra_colormap->cmaskb = cmaskb; + extra_colormap->cdestr = cdestr; + extra_colormap->cdestg = cdestg; + extra_colormap->cdestb = cdestb; + + extra_colormap->rgba = rgba; + extra_colormap->fadergba = fadergba; + + extra_colormap->lump = LUMPERROR; + extra_colormap->next = extra_colormap->prev = NULL; + + extra_colormap->colormap = R_CreateLightTable(extra_colormap); + + R_AddColormapToList(extra_colormap); + + return extra_colormap; } // Thanks to quake2 source! diff --git a/src/r_data.h b/src/r_data.h index 250f4d7c2..612c184e4 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -99,7 +99,8 @@ INT32 R_CheckTextureNumForName(const char *name); void R_ReInitColormaps(UINT16 num); void R_ClearColormaps(void); INT32 R_ColormapNumForName(char *name); -INT32 R_CreateColormap(char *p1, char *p2, char *p3); +lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); +extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3); const char *R_ColormapNameForNum(INT32 num); extern INT32 numtextures; diff --git a/src/r_defs.h b/src/r_defs.h index 7c8f2a73f..15312114a 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -53,15 +53,25 @@ typedef UINT8 lighttable_t; typedef struct { UINT16 maskcolor, fadecolor; - double maskamt; + double maskamt, othermask; UINT16 fadestart, fadeend; + UINT32 fadedist; INT32 fog; + // mask rgb for colormap table generation + double cmaskr, cmaskg, cmaskb; + double cdestr, cdestg, cdestb; + // rgba is used in hw mode for colored sector lighting INT32 rgba; // similar to maskcolor in sw mode INT32 fadergba; // The colour the colourmaps fade to lighttable_t *colormap; + + lumpnum_t lump; // for colormap lump matching, init to LUMPERROR + + extracolormap_t *next; + extracolormap_t *prev; } extracolormap_t; // diff --git a/src/r_state.h b/src/r_state.h index ac3e1fa42..effa4e36c 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -43,8 +43,7 @@ extern lighttable_t *colormaps; // Had to put a limit on colormaps :( #define MAXCOLORMAPS 60 -extern size_t num_extra_colormaps; -extern extracolormap_t extra_colormaps[MAXCOLORMAPS]; +extern extracolormap_t *extra_colormaps; // for global animation extern INT32 *texturetranslation; From 574a591d434bc1574e54479a443b15b315e422b2 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 16:08:43 -0400 Subject: [PATCH 104/306] P_LoadRawSideDefs2 colormap cleanup (merge ogl and software to one block) --- src/p_setup.c | 82 +++++---------------------------------------------- 1 file changed, 7 insertions(+), 75 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 5cc7279c5..a29a6080a 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1474,82 +1474,17 @@ static void P_LoadRawSideDefs2(void *data) // Perhaps we should just call it instead of doing the calculations here. if (rendermode == render_soft || rendermode == render_none) { - if (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#') - { - sec->midmap = R_CreateColormap(msd->toptexture, msd->midtexture, - msd->bottomtexture); - sd->toptexture = sd->bottomtexture = 0; - } - else - { - if ((num = R_CheckTextureNumForName(msd->toptexture)) == -1) - sd->toptexture = 0; - else - sd->toptexture = num; - if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1) - sd->midtexture = 0; - else - sd->midtexture = num; - if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1) - sd->bottomtexture = 0; - else - sd->bottomtexture = num; - } - break; - } + if ( + ((rendermode == render_soft || rendermode == render_none) && (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#')) #ifdef HWRENDER - else - { - // for now, full support of toptexture only - if ((msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6]) - || (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6])) + || (msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6]) + || (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6]) +#endif + ) { - char *col; - - sec->midmap = R_CreateColormap(msd->toptexture, msd->midtexture, + sec->extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture, msd->bottomtexture); sd->toptexture = sd->bottomtexture = 0; -#define HEX2INT(x) (x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) -#define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0) - sec->extra_colormap = &extra_colormaps[sec->midmap]; - - if (msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6]) - { - col = msd->toptexture; - - sec->extra_colormap->rgba = - (HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0) + - (HEX2INT(col[3]) << 12) + (HEX2INT(col[4]) << 8) + - (HEX2INT(col[5]) << 20) + (HEX2INT(col[6]) << 16); - - // alpha - if (msd->toptexture[7]) - sec->extra_colormap->rgba += (ALPHA2INT(col[7]) << 24); - else - sec->extra_colormap->rgba += (25 << 24); - } - else - sec->extra_colormap->rgba = 0; - - if (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6]) - { - col = msd->bottomtexture; - - sec->extra_colormap->fadergba = - (HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0) + - (HEX2INT(col[3]) << 12) + (HEX2INT(col[4]) << 8) + - (HEX2INT(col[5]) << 20) + (HEX2INT(col[6]) << 16); - - // alpha - if (msd->bottomtexture[7]) - sec->extra_colormap->fadergba += (ALPHA2INT(col[7]) << 24); - else - sec->extra_colormap->fadergba += (25 << 24); - } - else - sec->extra_colormap->fadergba = 0x19000000; // default alpha, (25 << 24) -#undef ALPHA2INT -#undef HEX2INT } else { @@ -1557,12 +1492,10 @@ static void P_LoadRawSideDefs2(void *data) sd->toptexture = 0; else sd->toptexture = num; - if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1) sd->midtexture = 0; else sd->midtexture = num; - if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1) sd->bottomtexture = 0; else @@ -1570,7 +1503,6 @@ static void P_LoadRawSideDefs2(void *data) } break; } -#endif case 413: // Change music { From e0d8a6eec0807afe4dc93fcb65e80e82d2131a73 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 16:16:04 -0400 Subject: [PATCH 105/306] Get rid of bottommap, midmap, topmap --- src/p_setup.c | 1 - src/p_spec.c | 2 +- src/r_bsp.c | 25 ++++--------------------- src/r_defs.h | 2 -- 4 files changed, 5 insertions(+), 25 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index a29a6080a..eb8489726 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -718,7 +718,6 @@ static void P_LoadRawSectors(UINT8 *data, size_t i) ss->spawn_flr_xoffs = ss->spawn_ceil_xoffs = ss->spawn_flr_yoffs = ss->spawn_ceil_yoffs = 0; ss->floorpic_angle = ss->ceilingpic_angle = 0; ss->spawn_flrpic_angle = ss->spawn_ceilpic_angle = 0; - ss->bottommap = ss->midmap = ss->topmap = -1; ss->gravity = NULL; ss->cullheight = NULL; ss->verticalflip = false; diff --git a/src/p_spec.c b/src/p_spec.c index 6c359c9cc..698c8f4b1 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6760,7 +6760,7 @@ void P_SpawnSpecials(INT32 fromnetsave) case 606: // HACK! Copy colormaps. Just plain colormaps. for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - sectors[s].midmap = lines[i].frontsector->midmap; + sectors[s].extra_colormap = lines[i].frontsector->extra_colormap; break; #ifdef ESLOPE // Slope copy specials. Handled here for sanity. diff --git a/src/r_bsp.c b/src/r_bsp.c index 183def25a..512aab696 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -234,8 +234,6 @@ static INT32 R_DoorClosed(void) sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, INT32 *ceilinglightlevel, boolean back) { - INT32 mapnum = -1; - if (floorlightlevel) *floorlightlevel = sec->floorlightsec == -1 ? sec->lightlevel : sectors[sec->floorlightsec].lightlevel; @@ -244,10 +242,10 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, *ceilinglightlevel = sec->ceilinglightsec == -1 ? sec->lightlevel : sectors[sec->ceilinglightsec].lightlevel; - // If the sector has a midmap, it's probably from 280 type - if (sec->midmap != -1) - mapnum = sec->midmap; - else if (sec->heightsec != -1) + // if (sec->midmap != -1) + // mapnum = sec->midmap; + // In original colormap code, this block did not run if sec->midmap was set + if (!sec->extra_colormap && sec->heightsec != -1) { const sector_t *s = §ors[sec->heightsec]; mobj_t *viewmobj = viewplayer->mo; @@ -271,8 +269,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->floorheight = s->floorheight; tempsec->ceilingheight = s->ceilingheight; - mapnum = s->midmap; - if ((underwater && (tempsec-> floorheight = sec->floorheight, tempsec->ceilingheight = s->floorheight - 1, !back)) || viewz <= s->floorheight) { // head-below-floor hack @@ -298,7 +294,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->ceiling_yoffs = s->ceiling_yoffs; tempsec->ceilingpic_angle = s->ceilingpic_angle; } - mapnum = s->bottommap; } tempsec->lightlevel = s->lightlevel; @@ -322,8 +317,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->floor_yoffs = tempsec->ceiling_yoffs = s->ceiling_yoffs; tempsec->floorpic_angle = tempsec->ceilingpic_angle = s->ceilingpic_angle; - mapnum = s->topmap; - if (s->floorpic == skyflatnum) // SKYFIX? { tempsec->ceilingheight = tempsec->floorheight-1; @@ -354,11 +347,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, sec = tempsec; } - if (mapnum >= 0 && (size_t)mapnum < num_extra_colormaps) - sec->extra_colormap = &extra_colormaps[mapnum]; - else - sec->extra_colormap = NULL; - return sec; } @@ -1342,11 +1330,6 @@ void R_Prep3DFloors(sector_t *sector) sector->lightlist[i].slope = bestslope; #endif sec = §ors[best->secnum]; - mapnum = sec->midmap; - if (mapnum >= 0 && (size_t)mapnum < num_extra_colormaps) - sec->extra_colormap = &extra_colormaps[mapnum]; - else - sec->extra_colormap = NULL; if (best->flags & FF_NOSHADE) { diff --git a/src/r_defs.h b/src/r_defs.h index 15312114a..257e36147 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -333,8 +333,6 @@ typedef struct sector_s INT32 floorlightsec, ceilinglightsec; INT32 crumblestate; // used for crumbling and bobbing - INT32 bottommap, midmap, topmap; // dynamic colormaps - // list of mobjs that are at least partially in the sector // thinglist is a subset of touching_thinglist struct msecnode_s *touching_thinglist; From 2701976ba39124f1687da05018c30644c821f30e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 16:28:39 -0400 Subject: [PATCH 106/306] Compiler fixes --- src/r_bsp.c | 2 +- src/r_data.c | 43 +++++++++++++++---------------------------- src/r_data.h | 2 +- src/r_defs.h | 6 +++--- src/r_main.c | 3 +-- 5 files changed, 21 insertions(+), 35 deletions(-) diff --git a/src/r_bsp.c b/src/r_bsp.c index 512aab696..01676572e 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -1225,7 +1225,7 @@ void R_Prep3DFloors(sector_t *sector) ffloor_t *rover; ffloor_t *best; fixed_t bestheight, maxheight; - INT32 count, i, mapnum; + INT32 count, i; sector_t *sec; #ifdef ESLOPE pslope_t *bestslope = NULL; diff --git a/src/r_data.c b/src/r_data.c index 1c964993f..eb5e27b0b 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1323,7 +1323,7 @@ void R_ClearColormaps(void) for (exc = extra_colormaps; exc; exc = exc_next) { exc_next = exc->next; - memset(exc, 0, sizeof(exc)); + memset(exc, 0, sizeof(*exc)); } extra_colormaps = NULL; @@ -1354,14 +1354,14 @@ void R_AddColormapToList(extracolormap_t *extra_colormap) extra_colormap->next = 0; } -INT32 R_ColormapNumForName(char *name) +extracolormap_t *R_ColormapForName(char *name) { lumpnum_t lump; extracolormap_t *exc; lump = R_CheckNumForNameList(name, colormaplumps, numcolormaplumps); if (lump == LUMPERROR) - I_Error("R_ColormapNumForName: Cannot find colormap lump %.8s\n", name); + I_Error("R_ColormapForName: Cannot find colormap lump %.8s\n", name); for (exc = extra_colormaps; exc; exc = exc->next) if (lump == exc->lump) @@ -1402,15 +1402,10 @@ static int RoundUp(double number); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) { - // "Unpackage" our variables for ease of reading below - UINT32 maskcolor = (UINT32)extra_colormap->maskcolor, - fadecolor = (UINT32)extra_colormap->fadecolor, - fadestart = (UINT16)extra_colormap->fadestart, - fadeend = (UINT16)extra_colormap->fadeend, + UINT32 fadestart = (UINT16)extra_colormap->fadestart, fadedist = extra_colormap->fadedist; - double maskamt = extra_colormap->maskamt, - othermask = extra_colormap->othermask, + double othermask = extra_colormap->othermask, cmaskr = extra_colormap->cmaskr, cmaskg = extra_colormap->cmaskg, cmaskb = extra_colormap->cmaskb, @@ -1418,12 +1413,8 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) cdestg = extra_colormap->cdestg, cdestb = extra_colormap->cdestb; - int fog = extra_colormap->fog; - - INT32 rgba = extra_colormap->rgba, - fadergba = extra_colormap->fadergba; - - lighttable_t *lighttable; + lighttable_t *lighttable = NULL; + size_t i; // This code creates the colormap array used by software renderer if (rendermode == render_soft) @@ -1514,6 +1505,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) INT32 rgba, fadergba; #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) +#define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0) if (p1[0] == '#') { cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2])); @@ -1539,15 +1531,12 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) cmaskg *= maskamt; cmaskb *= maskamt; - // package up cmask vars for passing around - maskrgba = - // for opengl; generate on software too for netsync rgba = (HEX2INT(p1[1]) << 4) + (HEX2INT(p1[2]) << 0) + (HEX2INT(p1[3]) << 12) + (HEX2INT(p1[4]) << 8) + (HEX2INT(p1[5]) << 20) + (HEX2INT(p1[6]) << 16); - if (p1[7] >= 'a' && p1[7] <= 'z' || p1[7] >= 'A' && p1[7] <= 'Z') + if ((p1[7] >= 'a' && p1[7] <= 'z') || (p1[7] >= 'A' && p1[7] <= 'Z')) rgba += (ALPHA2INT(p1[7]) << 24); else rgba += (25 << 24); @@ -1587,7 +1576,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) (HEX2INT(p3[3]) << 12) + (HEX2INT(p3[4]) << 8) + (HEX2INT(p3[5]) << 20) + (HEX2INT(p3[6]) << 16); - if (p3[7] >= 'a' && p3[7] <= 'z' || p3[7] >= 'A' && p3[7] <= 'Z') + if ((p3[7] >= 'a' && p3[7] <= 'z') || (p3[7] >= 'A' && p3[7] <= 'Z')) fadergba += (ALPHA2INT(p3[7]) << 24); else fadergba += (25 << 24); @@ -1597,6 +1586,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) cdestr = cdestg = cdestb = fadecolor = 0; fadergba = 0x19000000; // default alpha for fade, (25 << 24) } +#undef ALPHA2INT #undef HEX2INT for (exc = extra_colormaps; exc; exc = exc->next) @@ -1683,18 +1673,15 @@ static int RoundUp(double number) return (int)number; } -const char *R_ColormapNameForNum(INT32 num) +const char *R_ColormapNameForColormap(extracolormap_t *extra_colormap) { - if (num == -1) + if (!extra_colormap) return "NONE"; - if (num < 0 || num > MAXCOLORMAPS) - I_Error("R_ColormapNameForNum: num %d is invalid!\n", num); - - if (foundcolormaps[num] == LUMPERROR) + if (extra_colormap->lump == LUMPERROR) return "INLEVEL"; - return W_CheckNameForNum(foundcolormaps[num]); + return W_CheckNameForNum(extra_colormap->lump); } diff --git a/src/r_data.h b/src/r_data.h index 612c184e4..db2749834 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -98,7 +98,7 @@ INT32 R_CheckTextureNumForName(const char *name); void R_ReInitColormaps(UINT16 num); void R_ClearColormaps(void); -INT32 R_ColormapNumForName(char *name); +extracolormap_t *R_ColormapForName(char *name); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3); const char *R_ColormapNameForNum(INT32 num); diff --git a/src/r_defs.h b/src/r_defs.h index 257e36147..d8915cab8 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -50,7 +50,7 @@ typedef struct typedef UINT8 lighttable_t; // ExtraColormap type. Use for extra_colormaps from now on. -typedef struct +typedef struct extracolormap_s { UINT16 maskcolor, fadecolor; double maskamt, othermask; @@ -70,8 +70,8 @@ typedef struct lumpnum_t lump; // for colormap lump matching, init to LUMPERROR - extracolormap_t *next; - extracolormap_t *prev; + struct extracolormap_s *next; + struct extracolormap_s *prev; } extracolormap_t; // diff --git a/src/r_main.c b/src/r_main.c index 8e58906d4..281058362 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -118,8 +118,7 @@ lighttable_t *scalelightfixed[MAXLIGHTSCALE]; lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; // Hack to support extra boom colormaps. -size_t num_extra_colormaps; -extracolormap_t extra_colormaps[MAXCOLORMAPS]; +extracolormap_t *extra_colormaps; static CV_PossibleValue_t drawdist_cons_t[] = { {256, "256"}, {512, "512"}, {768, "768"}, From 53733ddf76440a70cf414c67b8ff5c58e93fe1f3 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 16:32:54 -0400 Subject: [PATCH 107/306] Type 606 renderer check allow OGL again --- src/p_setup.c | 53 ++++++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index eb8489726..09ba553bf 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1471,37 +1471,34 @@ static void P_LoadRawSideDefs2(void *data) case 606: //SoM: 4/4/2000: Just colormap transfer // SoM: R_CreateColormap will only create a colormap in software mode... // Perhaps we should just call it instead of doing the calculations here. - if (rendermode == render_soft || rendermode == render_none) - { - if ( - ((rendermode == render_soft || rendermode == render_none) && (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#')) + if ( + ((rendermode == render_soft || rendermode == render_none) && (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#')) #ifdef HWRENDER - || (msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6]) - || (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6]) + || (msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6]) + || (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6]) #endif - ) - { - sec->extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture, - msd->bottomtexture); - sd->toptexture = sd->bottomtexture = 0; - } - else - { - if ((num = R_CheckTextureNumForName(msd->toptexture)) == -1) - sd->toptexture = 0; - else - sd->toptexture = num; - if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1) - sd->midtexture = 0; - else - sd->midtexture = num; - if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1) - sd->bottomtexture = 0; - else - sd->bottomtexture = num; - } - break; + ) + { + sec->extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture, + msd->bottomtexture); + sd->toptexture = sd->bottomtexture = 0; } + else + { + if ((num = R_CheckTextureNumForName(msd->toptexture)) == -1) + sd->toptexture = 0; + else + sd->toptexture = num; + if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1) + sd->midtexture = 0; + else + sd->midtexture = num; + if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1) + sd->bottomtexture = 0; + else + sd->bottomtexture = num; + } + break; case 413: // Change music { From 7608583c6fbe134d6f9ef6677cd2d1b3c26c6cd5 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 16:42:07 -0400 Subject: [PATCH 108/306] Fix shared colormap matching --- src/r_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_data.c b/src/r_data.c index eb5e27b0b..eef6434b0 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1591,7 +1591,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) for (exc = extra_colormaps; exc; exc = exc->next) { - if (exc->lump) + if (exc->lump != LUMPERROR) continue; if (maskcolor == exc->maskcolor && fadecolor == exc->fadecolor From 7e9297d06e0fbfe104b8749c44d7aa54fa11ce86 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 9 Sep 2018 12:01:50 -0400 Subject: [PATCH 109/306] Savegame netsync for sector colormaps; add spawn_midmap and co for comparison --- src/p_saveg.c | 74 ++++++++++++++++++++++++++++++++++++++------------- src/p_setup.c | 3 ++- src/p_spec.c | 2 +- src/r_defs.h | 3 +++ 4 files changed, 61 insertions(+), 21 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 22d43f358..1c9589e8f 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -487,10 +487,16 @@ static void P_NetUnArchivePlayers(void) #define SD_FYOFFS 0x02 #define SD_CXOFFS 0x04 #define SD_CYOFFS 0x08 -#define SD_TAG 0x10 -#define SD_FLOORANG 0x20 -#define SD_CEILANG 0x40 -#define SD_TAGLIST 0x80 +#define SD_FLOORANG 0x10 +#define SD_CEILANG 0x20 +#define SD_TAG 0x40 +#define SD_DIFF3 0x80 + +// diff3 flags +#define SD_TAGLIST 0x01 +#define SD_BOTTOMMAP 0x02 +#define SD_MIDMAP 0x04 +#define SD_TOPMAP 0x08 #define LD_FLAG 0x01 #define LD_SPECIAL 0x02 @@ -523,7 +529,7 @@ static void P_NetArchiveWorld(void) mapsidedef_t *msd; maplinedef_t *mld; const sector_t *ss = sectors; - UINT8 diff, diff2; + UINT8 diff, diff2, diff3; WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD); put = save_p; @@ -550,7 +556,7 @@ static void P_NetArchiveWorld(void) for (i = 0; i < numsectors; i++, ss++, ms++) { - diff = diff2 = 0; + diff = diff2 = diff3 = 0; if (ss->floorheight != SHORT(ms->floorheight)<ceilingheight != SHORT(ms->ceilingheight)<tag != SHORT(ms->tag)) diff2 |= SD_TAG; if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag) - diff2 |= SD_TAGLIST; + diff3 |= SD_TAGLIST; + if (ss->bottommap != ss->spawn_bottommap) + diff3 |= SD_BOTTOMMAP; + if (ss->midmap != ss->spawn_midmap) + diff3 |= SD_MIDMAP; + if (ss->topmap != ss->spawn_topmap) + diff3 |= SD_TOPMAP; // Check if any of the sector's FOFs differ from how they spawned if (ss->ffloors) @@ -601,6 +613,9 @@ static void P_NetArchiveWorld(void) } } + if (diff3) + diff2 |= SD_DIFF3; + if (diff2) diff |= SD_DIFF2; @@ -612,6 +627,8 @@ static void P_NetArchiveWorld(void) WRITEUINT8(put, diff); if (diff & SD_DIFF2) WRITEUINT8(put, diff2); + if (diff2 & SD_DIFF3) + WRITEUINT8(put, diff3); if (diff & SD_FLOORHT) WRITEFIXED(put, ss->floorheight); if (diff & SD_CEILHT) @@ -632,17 +649,23 @@ static void P_NetArchiveWorld(void) WRITEFIXED(put, ss->ceiling_xoffs); if (diff2 & SD_CYOFFS) WRITEFIXED(put, ss->ceiling_yoffs); - if (diff2 & SD_TAG) // save only the tag - WRITEINT16(put, ss->tag); if (diff2 & SD_FLOORANG) WRITEANGLE(put, ss->floorpic_angle); if (diff2 & SD_CEILANG) WRITEANGLE(put, ss->ceilingpic_angle); - if (diff2 & SD_TAGLIST) // save both firsttag and nexttag + if (diff2 & SD_TAG) // save only the tag + WRITEINT16(put, ss->tag); + if (diff3 & SD_TAGLIST) // save both firsttag and nexttag { // either of these could be changed even if tag isn't WRITEINT32(put, ss->firsttag); WRITEINT32(put, ss->nexttag); } + if (diff3 & SD_BOTTOMMAP) + WRITEINT32(put, ss->bottommap); + if (diff3 & SD_MIDMAP) + WRITEINT32(put, ss->midmap); + if (diff3 & SD_TOPMAP) + WRITEINT32(put, ss->topmap); // Special case: save the stats of all modified ffloors along with their ffloor "number"s // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed @@ -680,7 +703,7 @@ static void P_NetArchiveWorld(void) // do lines for (i = 0; i < numlines; i++, mld++, li++) { - diff = diff2 = 0; + diff = diff2 = diff3 = 0; if (li->special != SHORT(mld->special)) diff |= LD_SPECIAL; @@ -772,7 +795,7 @@ static void P_NetUnArchiveWorld(void) line_t *li; side_t *si; UINT8 *get; - UINT8 diff, diff2; + UINT8 diff, diff2, diff3; if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD) I_Error("Bad $$$.sav at archive block World"); @@ -794,6 +817,10 @@ static void P_NetUnArchiveWorld(void) diff2 = READUINT8(get); else diff2 = 0; + if (diff2 & SD_DIFF3) + diff3 = READUINT8(get); + else + diff3 = 0; if (diff & SD_FLOORHT) sectors[i].floorheight = READFIXED(get); @@ -822,17 +849,23 @@ static void P_NetUnArchiveWorld(void) sectors[i].ceiling_xoffs = READFIXED(get); if (diff2 & SD_CYOFFS) sectors[i].ceiling_yoffs = READFIXED(get); - if (diff2 & SD_TAG) - sectors[i].tag = READINT16(get); // DON'T use P_ChangeSectorTag - if (diff2 & SD_TAGLIST) - { - sectors[i].firsttag = READINT32(get); - sectors[i].nexttag = READINT32(get); - } if (diff2 & SD_FLOORANG) sectors[i].floorpic_angle = READANGLE(get); if (diff2 & SD_CEILANG) sectors[i].ceilingpic_angle = READANGLE(get); + if (diff2 & SD_TAG) + sectors[i].tag = READINT16(get); // DON'T use P_ChangeSectorTag + if (diff3 & SD_TAGLIST) + { + sectors[i].firsttag = READINT32(get); + sectors[i].nexttag = READINT32(get); + } + if (diff3 & SD_BOTTOMMAP) + sectors[i].bottommap = READINT32(get); + if (diff3 & SD_MIDMAP) + sectors[i].midmap = READINT32(get); + if (diff3 & SD_TOPMAP) + sectors[i].topmap = READINT32(get); if (diff & SD_FFLOORS) { @@ -891,6 +924,9 @@ static void P_NetUnArchiveWorld(void) diff2 = READUINT8(get); else diff2 = 0; + + diff3 = 0; + if (diff & LD_FLAG) li->flags = READINT16(get); if (diff & LD_SPECIAL) diff --git a/src/p_setup.c b/src/p_setup.c index 09ba553bf..b503b6a58 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -713,6 +713,7 @@ static void P_LoadRawSectors(UINT8 *data, size_t i) ss->moved = true; ss->extra_colormap = NULL; + ss->spawn_extra_colormap = NULL; ss->floor_xoffs = ss->ceiling_xoffs = ss->floor_yoffs = ss->ceiling_yoffs = 0; ss->spawn_flr_xoffs = ss->spawn_ceil_xoffs = ss->spawn_flr_yoffs = ss->spawn_ceil_yoffs = 0; @@ -1479,7 +1480,7 @@ static void P_LoadRawSideDefs2(void *data) #endif ) { - sec->extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture, + sec->extra_colormap = sec->spawn_extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture, msd->bottomtexture); sd->toptexture = sd->bottomtexture = 0; } diff --git a/src/p_spec.c b/src/p_spec.c index 698c8f4b1..5135676ab 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6760,7 +6760,7 @@ void P_SpawnSpecials(INT32 fromnetsave) case 606: // HACK! Copy colormaps. Just plain colormaps. for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - sectors[s].extra_colormap = lines[i].frontsector->extra_colormap; + sectors[s].extra_colormap = sectors[s].spawn_extra_colormap = lines[i].frontsector->extra_colormap; break; #ifdef ESLOPE // Slope copy specials. Handled here for sanity. diff --git a/src/r_defs.h b/src/r_defs.h index d8915cab8..e81631eb9 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -401,6 +401,9 @@ typedef struct sector_s // flag angles sector spawned with (via linedef type 7) angle_t spawn_flrpic_angle; angle_t spawn_ceilpic_angle; + + // colormap structure + extracolormap_t *spawn_extra_colormap; } sector_t; // From c92226890e002cee36d5b5700b59724a851ae445 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 09:03:58 -0400 Subject: [PATCH 110/306] Remove bottommap and topmap from savegame because unused --- src/p_saveg.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 1c9589e8f..42757faf2 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -494,9 +494,7 @@ static void P_NetUnArchivePlayers(void) // diff3 flags #define SD_TAGLIST 0x01 -#define SD_BOTTOMMAP 0x02 -#define SD_MIDMAP 0x04 -#define SD_TOPMAP 0x08 +#define SD_MIDMAP 0x02 #define LD_FLAG 0x01 #define LD_SPECIAL 0x02 @@ -591,12 +589,8 @@ static void P_NetArchiveWorld(void) diff2 |= SD_TAG; if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag) diff3 |= SD_TAGLIST; - if (ss->bottommap != ss->spawn_bottommap) - diff3 |= SD_BOTTOMMAP; if (ss->midmap != ss->spawn_midmap) diff3 |= SD_MIDMAP; - if (ss->topmap != ss->spawn_topmap) - diff3 |= SD_TOPMAP; // Check if any of the sector's FOFs differ from how they spawned if (ss->ffloors) @@ -660,12 +654,8 @@ static void P_NetArchiveWorld(void) WRITEINT32(put, ss->firsttag); WRITEINT32(put, ss->nexttag); } - if (diff3 & SD_BOTTOMMAP) - WRITEINT32(put, ss->bottommap); if (diff3 & SD_MIDMAP) WRITEINT32(put, ss->midmap); - if (diff3 & SD_TOPMAP) - WRITEINT32(put, ss->topmap); // Special case: save the stats of all modified ffloors along with their ffloor "number"s // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed @@ -860,12 +850,8 @@ static void P_NetUnArchiveWorld(void) sectors[i].firsttag = READINT32(get); sectors[i].nexttag = READINT32(get); } - if (diff3 & SD_BOTTOMMAP) - sectors[i].bottommap = READINT32(get); if (diff3 & SD_MIDMAP) sectors[i].midmap = READINT32(get); - if (diff3 & SD_TOPMAP) - sectors[i].topmap = READINT32(get); if (diff & SD_FFLOORS) { From 8d78c2219474f91b8741854e1ecb67e486dd63c4 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 20:36:34 -0400 Subject: [PATCH 111/306] extracolormap_t refinement and netsyncing * Store raw values per rgba in extracolormap_t (no maskcolor or fadecolor) * Crunched some UINT16/32 into UINT8 * Calculate mask values in R_CreateLightTable * ifdef out EXTRACOLORMAPLUMPS --- src/p_saveg.c | 116 +++++++++++++++++++++++++++++++++--- src/r_data.c | 160 ++++++++++++++++++++++++++++++++------------------ src/r_data.h | 11 +++- src/r_defs.h | 16 ++--- 4 files changed, 228 insertions(+), 75 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 42757faf2..68d00a42c 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -21,6 +21,7 @@ #include "p_local.h" #include "p_setup.h" #include "p_saveg.h" +#include "r_data.h" #include "r_things.h" #include "r_state.h" #include "w_wad.h" @@ -494,7 +495,7 @@ static void P_NetUnArchivePlayers(void) // diff3 flags #define SD_TAGLIST 0x01 -#define SD_MIDMAP 0x02 +#define SD_COLORMAP 0x02 #define LD_FLAG 0x01 #define LD_SPECIAL 0x02 @@ -589,8 +590,8 @@ static void P_NetArchiveWorld(void) diff2 |= SD_TAG; if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag) diff3 |= SD_TAGLIST; - if (ss->midmap != ss->spawn_midmap) - diff3 |= SD_MIDMAP; + if (ss->extra_colormap != ss->spawn_extra_colormap) + diff3 |= SD_COLORMAP; // Check if any of the sector's FOFs differ from how they spawned if (ss->ffloors) @@ -654,8 +655,30 @@ static void P_NetArchiveWorld(void) WRITEINT32(put, ss->firsttag); WRITEINT32(put, ss->nexttag); } - if (diff3 & SD_MIDMAP) - WRITEINT32(put, ss->midmap); + + if (diff3 & SD_COLORMAP) + { + WRITEUINT8(put, ss->extra_colormap->fadestart); + WRITEUINT8(put, ss->extra_colormap->fadeend); + WRITEUINT8(put, ss->extra_colormap->fadedist); + WRITEUINT8(put, (UINT8)ss->extra_colormap->fog); + + WRITEUINT8(put, ss->extra_colormap->cr); + WRITEUINT8(put, ss->extra_colormap->cg); + WRITEUINT8(put, ss->extra_colormap->cb); + WRITEUINT8(put, ss->extra_colormap->ca); + WRITEUINT8(put, ss->extra_colormap->cfr); + WRITEUINT8(put, ss->extra_colormap->cfg); + WRITEUINT8(put, ss->extra_colormap->cfb); + WRITEUINT8(put, ss->extra_colormap->cfa); + + WRITEINT32(put, ss->extra_colormap->rgba); + WRITEINT32(put, ss->extra_colormap->fadergba); + +#ifdef EXTRACOLORMAPLUMPS + WRITESTRINGN(put, ss->extra_colormap->lumpname, 9); +#endif + } // Special case: save the stats of all modified ffloors along with their ffloor "number"s // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed @@ -850,8 +873,87 @@ static void P_NetUnArchiveWorld(void) sectors[i].firsttag = READINT32(get); sectors[i].nexttag = READINT32(get); } - if (diff3 & SD_MIDMAP) - sectors[i].midmap = READINT32(get); + + if (diff3 & SD_COLORMAP) + { + extracolormap_t *exc; + + UINT8 fadestart = READUINT8(get), + fadeend = READUINT8(get), + fadedist = READUINT8(get); + + boolean fog = (boolean)READUINT8(get); + + UINT8 cr = READUINT8(get), + cg = READUINT8(get), + cb = READUINT8(get), + ca = READUINT8(get), + cfr = READUINT8(get), + cfg = READUINT8(get), + cfb = READUINT8(get), + cfa = READUINT8(get); + + INT32 rgba = READINT32(get), + fadergba = READINT32(get); + +#ifdef EXTRACOLORMAPLUMPS + char lumpname[9]; + READSTRINGN(get, lumpname, 9); + + if (lumpname[0]) + sectors[i].extra_colormap = R_ColormapForName(lumpname); + else + { +#endif + + for (exc = extra_colormaps; exc; exc = exc->next) + { +#ifdef EXTRACOLORMAPLUMPS + if (exc->lump != LUMPERROR) + continue; +#endif + if (cr == exc->cr && cg == exc->cg && cb == exc->cb && ca == exc->ca + && cfr == exc->cfr && cfg == exc->cfg && cfb == exc->cfb && cfa == exc->cfa + && fadestart == exc->fadestart + && fadeend == exc->fadeend + && fog == exc->fog) + break; + } + + if (!exc) + { + exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); + + exc->fadestart = fadestart; + exc->fadeend = fadeend; + exc->fadedist = fadedist; + exc->fog = fog; + + exc->cr = cr; + exc->cg = cg; + exc->cb = cb; + exc->ca = ca; + exc->cfr = cfr; + exc->cfg = cfg; + exc->cfb = cfb; + exc->cfa = cfa; + + exc->rgba = rgba; + exc->fadergba = fadergba; + + exc->colormap = R_CreateLightTable(exc); + + R_AddColormapToList(exc); + + sectors[i].extra_colormap = exc; + +#ifdef EXTRACOLORMAPLUMPS + exc->lump = LUMPERROR; + exc->lumpname[0] = 0; + } // if (!exc) // if (!lumpname[0] || !R_ColormapForName(lumpname)) +#endif + } + } if (diff & SD_FFLOORS) { diff --git a/src/r_data.c b/src/r_data.c index eef6434b0..32cf17fa9 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1160,6 +1160,7 @@ static inline lumpnum_t R_CheckNumForNameList(const char *name, lumplist_t *list return LUMPERROR; } +#ifdef EXTRACOLORMAPLUMPS static lumplist_t *colormaplumps = NULL; ///\todo free leak static size_t numcolormaplumps = 0; @@ -1195,6 +1196,7 @@ static void R_InitExtraColormaps(void) } CONS_Printf(M_GetText("Number of Extra Colormaps: %s\n"), sizeu1(numcolormaplumps)); } +#endif // Search for flat name through all lumpnum_t R_GetFlatNumForName(const char *name) @@ -1291,7 +1293,9 @@ static void R_InitColormaps(void) // Init Boom colormaps. R_ClearColormaps(); +#ifdef EXTRACOLORMAPLUMPS R_InitExtraColormaps(); +#endif } void R_ReInitColormaps(UINT16 num) @@ -1354,6 +1358,7 @@ void R_AddColormapToList(extracolormap_t *extra_colormap) extra_colormap->next = 0; } +#ifdef EXTRACOLORMAPLUMPS extracolormap_t *R_ColormapForName(char *name) { lumpnum_t lump; @@ -1370,6 +1375,8 @@ extracolormap_t *R_ColormapForName(char *name) exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); exc->lump = lump; + strncpy(exc->lumpname, name, 9); + exc->lumpname[8] = 0; // aligned on 8 bit for asm code exc->colormap = Z_MallocAlign(W_LumpLength(lump), PU_LEVEL, NULL, 16); @@ -1377,15 +1384,21 @@ extracolormap_t *R_ColormapForName(char *name) // We set all params of the colormap to normal because there // is no real way to tell how GL should handle a colormap lump anyway.. - exc->maskcolor = 0xffff; - exc->fadecolor = 0x0; - exc->maskamt = 0x0; + exc->cr = exc->cg = exc->cb = 0xff; + exc->ca = 0; + exc->cfr = exc->cfg = exc->cfb = 0; + exc->cfa = 18; exc->fadestart = 0; exc->fadeend = 31; exc->fog = 0; + exc->rgba = 0; + exc->fadergba = 0x19000000; + + R_AddColormapToList(exc); return exc; } +#endif // // R_CreateColormap @@ -1402,21 +1415,58 @@ static int RoundUp(double number); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) { + double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb; + double maskamt = 0, othermask = 0; + + UINT8 cr = extra_colormap->cr, + cg = extra_colormap->cg, + cb = extra_colormap->cb, + ca = extra_colormap->ca, + cfr = extra_colormap->cfr, + cfg = extra_colormap->cfg, + cfb = extra_colormap->cfb; +// cfa = extra_colormap->cfa; // unused in software + UINT32 fadestart = (UINT16)extra_colormap->fadestart, fadedist = extra_colormap->fadedist; - double othermask = extra_colormap->othermask, - cmaskr = extra_colormap->cmaskr, - cmaskg = extra_colormap->cmaskg, - cmaskb = extra_colormap->cmaskb, - cdestr = extra_colormap->cdestr, - cdestg = extra_colormap->cdestg, - cdestb = extra_colormap->cdestb; - lighttable_t *lighttable = NULL; size_t i; + ///////////////////// + // Calc the RGBA mask + ///////////////////// + cmaskr = cr; + cmaskg = cg; + cmaskb = cb; + + maskamt = (double)(ca/24.0l); + othermask = 1 - maskamt; + maskamt /= 0xff; + + cmaskr *= maskamt; + cmaskg *= maskamt; + cmaskb *= maskamt; + + ///////////////////// + // Calc the RGBA fade mask + ///////////////////// + cdestr = cfr; + cdestg = cfg; + cdestb = cfb; + + // fade alpha unused in software + // maskamt = (double)(cfa/24.0l); + // othermask = 1 - maskamt; + // maskamt /= 0xff; + + // cdestr *= maskamt; + // cdestg *= maskamt; + // cdestb *= maskamt; + + ///////////////////// // This code creates the colormap array used by software renderer + ///////////////////// if (rendermode == render_soft) { double r, g, b, cbrightness; @@ -1494,12 +1544,10 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) { - double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb; - double maskamt = 0, othermask = 0; - int mask, fog = 0; + boolean fog = false; extracolormap_t *extra_colormap, *exc; - UINT32 cr, cg, cb, maskcolor, fadecolor; + UINT8 cr, cg, cb, ca, cfr, cfg, cfb, cfa; UINT32 fadestart = 0, fadeend = 31, fadedist = 31; INT32 rgba, fadergba; @@ -1509,27 +1557,15 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) if (p1[0] == '#') { cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2])); - cmaskr = cr; cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4])); - cmaskg = cg; cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6])); - cmaskb = cb; - // Create a rough approximation of the color (a 16 bit color) - maskcolor = ((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11); + if (p1[7] >= 'a' && p1[7] <= 'z') - mask = (p1[7] - 'a'); + ca = (p1[7] - 'a'); else if (p1[7] >= 'A' && p1[7] <= 'Z') - mask = (p1[7] - 'A'); + ca = (p1[7] - 'A'); else - mask = 24; - - maskamt = (double)(mask/24.0l); - - othermask = 1 - maskamt; - maskamt /= 0xff; - cmaskr *= maskamt; - cmaskg *= maskamt; - cmaskb *= maskamt; + ca = 24; // for opengl; generate on software too for netsync rgba = (HEX2INT(p1[1]) << 4) + (HEX2INT(p1[2]) << 0) + @@ -1543,9 +1579,8 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) } else { - cmaskr = cmaskg = cmaskb = 0xff; - maskamt = 0; - maskcolor = ((0xff) >> 3) + (((0xff) >> 2) << 5) + (((0xff) >> 3) << 11); + cr = cg = cb = 0xff; + ca = 0; rgba = 0; } @@ -1560,16 +1595,22 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) if (fadeend > 31 || fadeend < 1) fadeend = 31; fadedist = fadeend - fadestart; - fog = NUMFROMCHAR(p2[1]); + fog = (boolean)NUMFROMCHAR(p2[1]); } #undef NUMFROMCHAR if (p3[0] == '#') { - cdestr = cr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2])); - cdestg = cg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4])); - cdestb = cb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6])); - fadecolor = (((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11)); + cfr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2])); + cfg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4])); + cfb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6])); + + if (p1[7] >= 'a' && p1[7] <= 'z') + cfa = (p1[7] - 'a'); + else if (p1[7] >= 'A' && p1[7] <= 'Z') + cfa = (p1[7] - 'A'); + else + cfa = 18; // for opengl; generate on software too for netsync fadergba = (HEX2INT(p3[1]) << 4) + (HEX2INT(p3[2]) << 0) + @@ -1583,7 +1624,8 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) } else { - cdestr = cdestg = cdestb = fadecolor = 0; + cfr = cfg = cfb = 0; + cfa = 18; fadergba = 0x19000000; // default alpha for fade, (25 << 24) } #undef ALPHA2INT @@ -1591,40 +1633,41 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) for (exc = extra_colormaps; exc; exc = exc->next) { +#ifdef EXTRACOLORMAPLUMPS if (exc->lump != LUMPERROR) continue; - if (maskcolor == exc->maskcolor - && fadecolor == exc->fadecolor - && (float)maskamt == (float)exc->maskamt +#endif + if (cr == exc->cr && cg == exc->cg && cb == exc->cb && ca == exc->ca + && cfr == exc->cfr && cfg == exc->cfg && cfb == exc->cfb && cfa == exc->cfa && fadestart == exc->fadestart && fadeend == exc->fadeend && fog == exc->fog) - return exc; + break; } extra_colormap = Z_Calloc(sizeof (*extra_colormap), PU_LEVEL, NULL); - extra_colormap->maskcolor = (UINT16)maskcolor; - extra_colormap->fadecolor = (UINT16)fadecolor; - extra_colormap->maskamt = maskamt; - extra_colormap->othermask = othermask; extra_colormap->fadestart = (UINT16)fadestart; extra_colormap->fadeend = (UINT16)fadeend; extra_colormap->fadedist = fadedist; extra_colormap->fog = fog; - extra_colormap->cmaskr = cmaskr; - extra_colormap->cmaskg = cmaskg; - extra_colormap->cmaskb = cmaskb; - extra_colormap->cdestr = cdestr; - extra_colormap->cdestg = cdestg; - extra_colormap->cdestb = cdestb; + extra_colormap->cr = cr; + extra_colormap->cg = cg; + extra_colormap->cb = cb; + extra_colormap->ca = ca; + extra_colormap->cfr = cfr; + extra_colormap->cfg = cfg; + extra_colormap->cfb = cfb; + extra_colormap->cfa = cfa; extra_colormap->rgba = rgba; extra_colormap->fadergba = fadergba; +#ifdef EXTRACOLORMAPLUMPS extra_colormap->lump = LUMPERROR; - extra_colormap->next = extra_colormap->prev = NULL; + extra_colormap->lumpname[0] = 0; +#endif extra_colormap->colormap = R_CreateLightTable(extra_colormap); @@ -1673,7 +1716,8 @@ static int RoundUp(double number) return (int)number; } -const char *R_ColormapNameForColormap(extracolormap_t *extra_colormap) +#ifdef EXTRACOLORMAPLUMPS +const char *R_NameForColormap(extracolormap_t *extra_colormap) { if (!extra_colormap) return "NONE"; @@ -1681,9 +1725,9 @@ const char *R_ColormapNameForColormap(extracolormap_t *extra_colormap) if (extra_colormap->lump == LUMPERROR) return "INLEVEL"; - return W_CheckNameForNum(extra_colormap->lump); + return extra_colormap->lumpname; } - +#endif // // build a table for quick conversion from 8bpp to 15bpp diff --git a/src/r_data.h b/src/r_data.h index db2749834..5600d36dc 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -96,12 +96,19 @@ void R_ClearTextureNumCache(boolean btell); INT32 R_TextureNumForName(const char *name); INT32 R_CheckTextureNumForName(const char *name); +// Extra Colormap lumps (C_START/C_END) are not used anywhere +// Uncomment to enable +//#define EXTRACOLORMAPLUMPS + void R_ReInitColormaps(UINT16 num); void R_ClearColormaps(void); -extracolormap_t *R_ColormapForName(char *name); +void R_AddColormapToList(extracolormap_t *extra_colormap); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3); -const char *R_ColormapNameForNum(INT32 num); +#ifdef EXTRACOLORMAPLUMPS +extracolormap_t *R_ColormapForName(char *name); +const char *R_NameForColormap(extracolormap_t *extra_colormap); +#endif extern INT32 numtextures; diff --git a/src/r_defs.h b/src/r_defs.h index e81631eb9..8dd34cd15 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -52,15 +52,12 @@ typedef UINT8 lighttable_t; // ExtraColormap type. Use for extra_colormaps from now on. typedef struct extracolormap_s { - UINT16 maskcolor, fadecolor; - double maskamt, othermask; - UINT16 fadestart, fadeend; - UINT32 fadedist; - INT32 fog; + UINT8 fadestart, fadeend; + UINT8 fadedist; + boolean fog; - // mask rgb for colormap table generation - double cmaskr, cmaskg, cmaskb; - double cdestr, cdestg, cdestb; + // rgba for colormap table generation + UINT8 cr, cg, cb, ca, cfr, cfg, cfb, cfa; // rgba is used in hw mode for colored sector lighting INT32 rgba; // similar to maskcolor in sw mode @@ -68,7 +65,10 @@ typedef struct extracolormap_s lighttable_t *colormap; +#ifdef EXTRACOLORMAPLUMPS lumpnum_t lump; // for colormap lump matching, init to LUMPERROR + char lumpname[9]; // for netsyncing +#endif struct extracolormap_s *next; struct extracolormap_s *prev; From 1e4f5e8d45db305297c3f23088b8eec91d4d6274 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 20:41:12 -0400 Subject: [PATCH 112/306] Remove MAXCOLORMAPS --- src/r_state.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/r_state.h b/src/r_state.h index effa4e36c..91c2092e9 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -40,9 +40,6 @@ extern sprcache_t *spritecachedinfo; extern lighttable_t *colormaps; // Boom colormaps. -// Had to put a limit on colormaps :( -#define MAXCOLORMAPS 60 - extern extracolormap_t *extra_colormaps; // for global animation From 3da38f2a9be36ab980a61fae3a0b18dc58a7d1c0 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 20:52:37 -0400 Subject: [PATCH 113/306] Fixed colormap matching code again * Added debug messages for matching code --- src/p_saveg.c | 26 ++++++++++++++++++++++++++ src/r_data.c | 15 ++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 68d00a42c..137b4ffd0 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -877,6 +877,7 @@ static void P_NetUnArchiveWorld(void) if (diff3 & SD_COLORMAP) { extracolormap_t *exc; + size_t dbg_i = 0; UINT8 fadestart = READUINT8(get), fadeend = READUINT8(get), @@ -920,8 +921,33 @@ static void P_NetUnArchiveWorld(void) break; } + for (exc = extra_colormaps; exc; exc = exc->next) + { +#ifdef EXTRACOLORMAPLUMPS + if (exc->lump != LUMPERROR) + { + dbg_i++; + continue; + } +#endif + if (cr == exc->cr && cg == exc->cg && cb == exc->cb && ca == exc->ca + && cfr == exc->cfr && cfg == exc->cfg && cfb == exc->cfb && cfa == exc->cfa + && fadestart == exc->fadestart + && fadeend == exc->fadeend + && fog == exc->fog) + { + CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); + break; + } + dbg_i++; + } + if (!exc) { + CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); + exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); exc->fadestart = fadestart; diff --git a/src/r_data.c b/src/r_data.c index 32cf17fa9..e51eb32e9 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1552,6 +1552,8 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) INT32 rgba, fadergba; + size_t dbg_i = 0; + #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) #define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0) if (p1[0] == '#') @@ -1635,16 +1637,27 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) { #ifdef EXTRACOLORMAPLUMPS if (exc->lump != LUMPERROR) + { + dbg_i++; continue; + } #endif if (cr == exc->cr && cg == exc->cg && cb == exc->cb && ca == exc->ca && cfr == exc->cfr && cfg == exc->cfg && cfb == exc->cfb && cfa == exc->cfa && fadestart == exc->fadestart && fadeend == exc->fadeend && fog == exc->fog) - break; + { + CONS_Debug(DBG_RENDER, "R_CreateColormap: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); + return exc; + } + dbg_i++; } + CONS_Debug(DBG_RENDER, "R_CreateColormap: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); + extra_colormap = Z_Calloc(sizeof (*extra_colormap), PU_LEVEL, NULL); extra_colormap->fadestart = (UINT16)fadestart; From c007dfacecb8b392e2c063f1f73373d78a29322b Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 21:12:56 -0400 Subject: [PATCH 114/306] Savegame fixes --- src/p_saveg.c | 18 +++++++++--------- src/r_defs.h | 1 - 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index eb49e9730..33923551d 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -655,8 +655,6 @@ static void P_NetArchiveWorld(void) WRITEINT32(put, ss->firsttag); WRITEINT32(put, ss->nexttag); } - if (diff3 & SD_MIDMAP) - WRITEINT32(put, ss->midmap); if (diff3 & SD_COLORMAP) { @@ -938,8 +936,8 @@ static void P_NetUnArchiveWorld(void) && fadeend == exc->fadeend && fog == exc->fog) { - CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); + // CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + // dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); break; } dbg_i++; @@ -947,8 +945,8 @@ static void P_NetUnArchiveWorld(void) if (!exc) { - CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); + // CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + // dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); @@ -973,14 +971,16 @@ static void P_NetUnArchiveWorld(void) R_AddColormapToList(exc); - sectors[i].extra_colormap = exc; - #ifdef EXTRACOLORMAPLUMPS exc->lump = LUMPERROR; exc->lumpname[0] = 0; - } // if (!exc) // if (!lumpname[0] || !R_ColormapForName(lumpname)) #endif } + + sectors[i].extra_colormap = exc; +#ifdef EXTRACOLORMAPLUMPS + } +#endif } if (diff & SD_FFLOORS) diff --git a/src/r_defs.h b/src/r_defs.h index 77b56bd30..8dd34cd15 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -393,7 +393,6 @@ typedef struct sector_s // these are saved for netgames, so do not let Lua touch these! INT32 spawn_nexttag, spawn_firsttag; // the actual nexttag/firsttag values may differ if the sector's tag was changed - INT32 spawn_bottommap, spawn_midmap, spawn_topmap; // offsets sector spawned with (via linedef type 7) fixed_t spawn_flr_xoffs, spawn_flr_yoffs; From 22746c1d9140446edc1bac8b0a9358b273a43fd7 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 21:12:56 -0400 Subject: [PATCH 115/306] Savegame fixes --- src/p_saveg.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 137b4ffd0..66db8a383 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -877,7 +877,7 @@ static void P_NetUnArchiveWorld(void) if (diff3 & SD_COLORMAP) { extracolormap_t *exc; - size_t dbg_i = 0; + //size_t dbg_i = 0; UINT8 fadestart = READUINT8(get), fadeend = READUINT8(get), @@ -926,7 +926,7 @@ static void P_NetUnArchiveWorld(void) #ifdef EXTRACOLORMAPLUMPS if (exc->lump != LUMPERROR) { - dbg_i++; + //dbg_i++; continue; } #endif @@ -936,17 +936,17 @@ static void P_NetUnArchiveWorld(void) && fadeend == exc->fadeend && fog == exc->fog) { - CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); + // CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + // dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); break; } - dbg_i++; + //dbg_i++; } if (!exc) { - CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); + // CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + // dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); @@ -971,14 +971,16 @@ static void P_NetUnArchiveWorld(void) R_AddColormapToList(exc); - sectors[i].extra_colormap = exc; - #ifdef EXTRACOLORMAPLUMPS exc->lump = LUMPERROR; exc->lumpname[0] = 0; - } // if (!exc) // if (!lumpname[0] || !R_ColormapForName(lumpname)) #endif } + + sectors[i].extra_colormap = exc; +#ifdef EXTRACOLORMAPLUMPS + } +#endif } if (diff & SD_FFLOORS) From 53b92a16011a2e235c9f158c321886017956b080 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 21:56:09 -0400 Subject: [PATCH 116/306] Make default extracolormap on init * Calc fadedist in R_CreateLightTable --- src/p_saveg.c | 5 +---- src/r_data.c | 28 ++++++++++++++++++++++------ src/r_defs.h | 1 - 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 66db8a383..7ee41dffd 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -660,7 +660,6 @@ static void P_NetArchiveWorld(void) { WRITEUINT8(put, ss->extra_colormap->fadestart); WRITEUINT8(put, ss->extra_colormap->fadeend); - WRITEUINT8(put, ss->extra_colormap->fadedist); WRITEUINT8(put, (UINT8)ss->extra_colormap->fog); WRITEUINT8(put, ss->extra_colormap->cr); @@ -880,8 +879,7 @@ static void P_NetUnArchiveWorld(void) //size_t dbg_i = 0; UINT8 fadestart = READUINT8(get), - fadeend = READUINT8(get), - fadedist = READUINT8(get); + fadeend = READUINT8(get); boolean fog = (boolean)READUINT8(get); @@ -952,7 +950,6 @@ static void P_NetUnArchiveWorld(void) exc->fadestart = fadestart; exc->fadeend = fadeend; - exc->fadedist = fadedist; exc->fog = fog; exc->cr = cr; diff --git a/src/r_data.c b/src/r_data.c index e51eb32e9..f1f04b2d2 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1330,7 +1330,25 @@ void R_ClearColormaps(void) memset(exc, 0, sizeof(*exc)); } - extra_colormaps = NULL; + // make a default extra_colormap + exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); + exc->cr = exc->cg = exc->cb = 0xff; + exc->ca = 0; + exc->cfr = exc->cfg = exc->cfb = 0; + exc->cfa = 18; + exc->fadestart = 0; + exc->fadeend = 31; + exc->fog = 0; + exc->rgba = 0; + exc->fadergba = 0x19000000; + exc->colormap = R_CreateLightTable(exc); +#ifdef EXTRACOLORMAPLUMPS + exc->lump = LUMPERROR; + exc->lumpname[0] = 0; +#endif + exc->next = exc->prev = NULL; + + extra_colormaps = exc; } // @@ -1427,8 +1445,8 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) cfb = extra_colormap->cfb; // cfa = extra_colormap->cfa; // unused in software - UINT32 fadestart = (UINT16)extra_colormap->fadestart, - fadedist = extra_colormap->fadedist; + UINT8 fadestart = extra_colormap->fadestart, + fadedist = extra_colormap->fadeend - extra_colormap->fadestart; lighttable_t *lighttable = NULL; size_t i; @@ -1548,7 +1566,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) extracolormap_t *extra_colormap, *exc; UINT8 cr, cg, cb, ca, cfr, cfg, cfb, cfa; - UINT32 fadestart = 0, fadeend = 31, fadedist = 31; + UINT32 fadestart = 0, fadeend = 31; INT32 rgba, fadergba; @@ -1596,7 +1614,6 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) fadestart = 0; if (fadeend > 31 || fadeend < 1) fadeend = 31; - fadedist = fadeend - fadestart; fog = (boolean)NUMFROMCHAR(p2[1]); } #undef NUMFROMCHAR @@ -1662,7 +1679,6 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) extra_colormap->fadestart = (UINT16)fadestart; extra_colormap->fadeend = (UINT16)fadeend; - extra_colormap->fadedist = fadedist; extra_colormap->fog = fog; extra_colormap->cr = cr; diff --git a/src/r_defs.h b/src/r_defs.h index 8dd34cd15..22d4fdf14 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -53,7 +53,6 @@ typedef UINT8 lighttable_t; typedef struct extracolormap_s { UINT8 fadestart, fadeend; - UINT8 fadedist; boolean fog; // rgba for colormap table generation From 43ae25c4fd3b0e912e6ff433701aaa0c19f35224 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 21:56:09 -0400 Subject: [PATCH 117/306] Make default extracolormap on init * Calc fadedist in R_CreateLightTable --- src/p_saveg.c | 5 +---- src/r_data.c | 28 ++++++++++++++++++++++------ src/r_defs.h | 1 - 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 66db8a383..7ee41dffd 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -660,7 +660,6 @@ static void P_NetArchiveWorld(void) { WRITEUINT8(put, ss->extra_colormap->fadestart); WRITEUINT8(put, ss->extra_colormap->fadeend); - WRITEUINT8(put, ss->extra_colormap->fadedist); WRITEUINT8(put, (UINT8)ss->extra_colormap->fog); WRITEUINT8(put, ss->extra_colormap->cr); @@ -880,8 +879,7 @@ static void P_NetUnArchiveWorld(void) //size_t dbg_i = 0; UINT8 fadestart = READUINT8(get), - fadeend = READUINT8(get), - fadedist = READUINT8(get); + fadeend = READUINT8(get); boolean fog = (boolean)READUINT8(get); @@ -952,7 +950,6 @@ static void P_NetUnArchiveWorld(void) exc->fadestart = fadestart; exc->fadeend = fadeend; - exc->fadedist = fadedist; exc->fog = fog; exc->cr = cr; diff --git a/src/r_data.c b/src/r_data.c index e51eb32e9..f1f04b2d2 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1330,7 +1330,25 @@ void R_ClearColormaps(void) memset(exc, 0, sizeof(*exc)); } - extra_colormaps = NULL; + // make a default extra_colormap + exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); + exc->cr = exc->cg = exc->cb = 0xff; + exc->ca = 0; + exc->cfr = exc->cfg = exc->cfb = 0; + exc->cfa = 18; + exc->fadestart = 0; + exc->fadeend = 31; + exc->fog = 0; + exc->rgba = 0; + exc->fadergba = 0x19000000; + exc->colormap = R_CreateLightTable(exc); +#ifdef EXTRACOLORMAPLUMPS + exc->lump = LUMPERROR; + exc->lumpname[0] = 0; +#endif + exc->next = exc->prev = NULL; + + extra_colormaps = exc; } // @@ -1427,8 +1445,8 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) cfb = extra_colormap->cfb; // cfa = extra_colormap->cfa; // unused in software - UINT32 fadestart = (UINT16)extra_colormap->fadestart, - fadedist = extra_colormap->fadedist; + UINT8 fadestart = extra_colormap->fadestart, + fadedist = extra_colormap->fadeend - extra_colormap->fadestart; lighttable_t *lighttable = NULL; size_t i; @@ -1548,7 +1566,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) extracolormap_t *extra_colormap, *exc; UINT8 cr, cg, cb, ca, cfr, cfg, cfb, cfa; - UINT32 fadestart = 0, fadeend = 31, fadedist = 31; + UINT32 fadestart = 0, fadeend = 31; INT32 rgba, fadergba; @@ -1596,7 +1614,6 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) fadestart = 0; if (fadeend > 31 || fadeend < 1) fadeend = 31; - fadedist = fadeend - fadestart; fog = (boolean)NUMFROMCHAR(p2[1]); } #undef NUMFROMCHAR @@ -1662,7 +1679,6 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) extra_colormap->fadestart = (UINT16)fadestart; extra_colormap->fadeend = (UINT16)fadeend; - extra_colormap->fadedist = fadedist; extra_colormap->fog = fog; extra_colormap->cr = cr; diff --git a/src/r_defs.h b/src/r_defs.h index 8dd34cd15..22d4fdf14 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -53,7 +53,6 @@ typedef UINT8 lighttable_t; typedef struct extracolormap_s { UINT8 fadestart, fadeend; - UINT8 fadedist; boolean fog; // rgba for colormap table generation From 9038ba4d9c941d4ae0d06c418d115cbb7b3ffe75 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 22:35:03 -0400 Subject: [PATCH 118/306] Add COLORMAPREVERSELIST ifdef to toggle Newest -> Oldest extra_colormaps order --- src/r_data.c | 7 +++++++ src/r_data.h | 3 +++ 2 files changed, 10 insertions(+) diff --git a/src/r_data.c b/src/r_data.c index f1f04b2d2..160539437 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1369,11 +1369,18 @@ void R_AddColormapToList(extracolormap_t *extra_colormap) return; } +#ifdef COLORMAPREVERSELIST + extra_colormaps->prev = extra_colormap; + extra_colormap->next = extra_colormaps; + extra_colormaps = extra_colormap; + extra_colormap->prev = 0; +#else for (exc = extra_colormaps; exc->next; exc = exc->next); exc->next = extra_colormap; extra_colormap->prev = exc; extra_colormap->next = 0; +#endif } #ifdef EXTRACOLORMAPLUMPS diff --git a/src/r_data.h b/src/r_data.h index 5600d36dc..e6eec41b4 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -100,6 +100,9 @@ INT32 R_CheckTextureNumForName(const char *name); // Uncomment to enable //#define EXTRACOLORMAPLUMPS +// Uncomment to make extra_colormaps order Newest -> Oldest +//#define COLORMAPREVERSELIST + void R_ReInitColormaps(UINT16 num); void R_ClearColormaps(void); void R_AddColormapToList(extracolormap_t *extra_colormap); From 17e101a24b81f8baaa8382b4ae26f28842330d2f Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 22:35:03 -0400 Subject: [PATCH 119/306] Add COLORMAPREVERSELIST ifdef to toggle Newest -> Oldest extra_colormaps order --- src/r_data.c | 7 +++++++ src/r_data.h | 3 +++ 2 files changed, 10 insertions(+) diff --git a/src/r_data.c b/src/r_data.c index f1f04b2d2..160539437 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1369,11 +1369,18 @@ void R_AddColormapToList(extracolormap_t *extra_colormap) return; } +#ifdef COLORMAPREVERSELIST + extra_colormaps->prev = extra_colormap; + extra_colormap->next = extra_colormaps; + extra_colormaps = extra_colormap; + extra_colormap->prev = 0; +#else for (exc = extra_colormaps; exc->next; exc = exc->next); exc->next = extra_colormap; extra_colormap->prev = exc; extra_colormap->next = 0; +#endif } #ifdef EXTRACOLORMAPLUMPS diff --git a/src/r_data.h b/src/r_data.h index 5600d36dc..e6eec41b4 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -100,6 +100,9 @@ INT32 R_CheckTextureNumForName(const char *name); // Uncomment to enable //#define EXTRACOLORMAPLUMPS +// Uncomment to make extra_colormaps order Newest -> Oldest +//#define COLORMAPREVERSELIST + void R_ReInitColormaps(UINT16 num); void R_ClearColormaps(void); void R_AddColormapToList(extracolormap_t *extra_colormap); From b7a216c78b6121642a9a9dafc501cfe565ac2ca3 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 10 Sep 2018 22:35:03 -0400 Subject: [PATCH 120/306] Add COLORMAPREVERSELIST ifdef to toggle Newest -> Oldest extra_colormaps order --- src/r_data.c | 9 +++++++++ src/r_data.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/src/r_data.c b/src/r_data.c index f1f04b2d2..ffc6cc7fd 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1359,7 +1359,9 @@ void R_ClearColormaps(void) // void R_AddColormapToList(extracolormap_t *extra_colormap) { +#ifndef COLORMAPREVERSELIST extracolormap_t *exc; +#endif if (!extra_colormaps) { @@ -1369,11 +1371,18 @@ void R_AddColormapToList(extracolormap_t *extra_colormap) return; } +#ifdef COLORMAPREVERSELIST + extra_colormaps->prev = extra_colormap; + extra_colormap->next = extra_colormaps; + extra_colormaps = extra_colormap; + extra_colormap->prev = 0; +#else for (exc = extra_colormaps; exc->next; exc = exc->next); exc->next = extra_colormap; extra_colormap->prev = exc; extra_colormap->next = 0; +#endif } #ifdef EXTRACOLORMAPLUMPS diff --git a/src/r_data.h b/src/r_data.h index 5600d36dc..e6eec41b4 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -100,6 +100,9 @@ INT32 R_CheckTextureNumForName(const char *name); // Uncomment to enable //#define EXTRACOLORMAPLUMPS +// Uncomment to make extra_colormaps order Newest -> Oldest +//#define COLORMAPREVERSELIST + void R_ReInitColormaps(UINT16 num); void R_ClearColormaps(void); void R_AddColormapToList(extracolormap_t *extra_colormap); From 36923ae7b0ae7da2459af0ecee5cf231b0419369 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 10:05:25 -0400 Subject: [PATCH 121/306] Use percentage calc instead of interval decrement for tic-based timing --- src/p_lights.c | 32 ++++++++++++++++---------------- src/p_saveg.c | 12 ++++++------ src/p_spec.h | 8 ++++---- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/p_lights.c b/src/p_lights.c index 77d05dad3..95171155e 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -352,19 +352,17 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean P_AddThinker(&ll->thinker); // add thinker ll->sector = sector; + ll->sourcelevel = sector->lightlevel; ll->destlevel = destvalue; if (ticbased) { - ll->ticbased = ticbased; - ll->timer = abs(speed); - ll->speed = FixedFloor(FixedDiv(destvalue - sector->lightlevel, ll->timer))/FRACUNIT; - if (!ll->speed) - ll->speed = (destvalue < sector->lightlevel) ? -1 : 1; - ll->interval = max(FixedFloor(FixedDiv(ll->timer, abs(destvalue - sector->lightlevel)))/FRACUNIT, 1); + ll->ticbased = true; + ll->timer = ll->speed = abs(speed); // use ll->speed for total duration } else { + ll->ticbased = false; ll->timer = -1; ll->speed = abs(speed); } @@ -389,15 +387,17 @@ void T_LightFade(lightlevel_t *ll) { if (--ll->timer <= 0) { - ll->sector->lightlevel = (INT16)ll->destlevel; // set to dest lightlevel + ll->sector->lightlevel = ll->destlevel; // set to dest lightlevel P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker } - else if (!(ll->timer % ll->interval)) + else { - if (ll->speed < 0) - ll->sector->lightlevel = max(ll->sector->lightlevel + (INT16)ll->speed, (INT16)ll->destlevel); - else - ll->sector->lightlevel = min(ll->sector->lightlevel + (INT16)ll->speed, (INT16)ll->destlevel); + INT16 delta = abs(ll->destlevel - ll->sourcelevel); + fixed_t factor = min(FixedDiv(ll->speed - ll->timer, ll->speed), 1*FRACUNIT); + if (ll->destlevel < ll->sourcelevel) + ll->sector->lightlevel = max(min(ll->sector->lightlevel, ll->sourcelevel - (INT16)FixedMul(delta, factor)), ll->destlevel); + else if (ll->destlevel > ll->sourcelevel) + ll->sector->lightlevel = min(max(ll->sector->lightlevel, ll->sourcelevel + (INT16)FixedMul(delta, factor)), ll->destlevel); } return; } @@ -408,12 +408,12 @@ void T_LightFade(lightlevel_t *ll) if (ll->sector->lightlevel + ll->speed >= ll->destlevel) { // stop changing light level - ll->sector->lightlevel = (INT16)ll->destlevel; // set to dest lightlevel + ll->sector->lightlevel = ll->destlevel; // set to dest lightlevel P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker } else - ll->sector->lightlevel = (INT16)(ll->sector->lightlevel + (INT16)ll->speed); // move lightlevel + ll->sector->lightlevel += ll->speed; // move lightlevel } else { @@ -421,11 +421,11 @@ void T_LightFade(lightlevel_t *ll) if (ll->sector->lightlevel - ll->speed <= ll->destlevel) { // stop changing light level - ll->sector->lightlevel = (INT16)ll->destlevel; // set to dest lightlevel + ll->sector->lightlevel = ll->destlevel; // set to dest lightlevel P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker } else - ll->sector->lightlevel = (INT16)(ll->sector->lightlevel - (INT16)ll->speed); // move lightlevel + ll->sector->lightlevel -= ll->speed; // move lightlevel } } diff --git a/src/p_saveg.c b/src/p_saveg.c index eefee072d..e9f07de4c 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1537,11 +1537,11 @@ static void SaveLightlevelThinker(const thinker_t *th, const UINT8 type) const lightlevel_t *ht = (const void *)th; WRITEUINT8(save_p, type); WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT32(save_p, ht->destlevel); - WRITEINT32(save_p, ht->speed); + WRITEINT16(save_p, ht->sourcelevel); + WRITEINT16(save_p, ht->destlevel); + WRITEINT16(save_p, ht->speed); WRITEUINT8(save_p, (UINT8)ht->ticbased); WRITEINT32(save_p, ht->timer); - WRITEUINT32(save_p, ht->interval); } // @@ -2513,11 +2513,11 @@ static inline void LoadLightlevelThinker(actionf_p1 thinker) lightlevel_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; ht->sector = LoadSector(READUINT32(save_p)); - ht->destlevel = READINT32(save_p); - ht->speed = READINT32(save_p); + ht->sourcelevel = READINT16(save_p); + ht->destlevel = READINT16(save_p); + ht->speed = READINT16(save_p); ht->ticbased = (boolean)READUINT8(save_p); ht->timer = READINT32(save_p); - ht->interval = READUINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; P_AddThinker(&ht->thinker); diff --git a/src/p_spec.h b/src/p_spec.h index 1e327c5f2..69087d6c4 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -136,13 +136,13 @@ typedef struct { thinker_t thinker; ///< Thinker in use for the effect. sector_t *sector; ///< Sector where action is taking place. - INT32 destlevel; ///< Light level we're fading to. - INT32 speed; ///< Speed at which to change light level. + INT16 sourcelevel; ///< Light level we're fading from. + INT16 destlevel; ///< Light level we're fading to. + INT16 speed; ///< Speed at which to change light level. OR: Tic-based duration // Tic-based behavior boolean ticbased; ///< Tic-based logic - INT32 timer; ///< Tic-based timer - UINT32 interval; ///< Interval to deduct light level + INT32 timer; ///< Tic-based timer } lightlevel_t; #define GLOWSPEED 8 From 9a52816cb494a67ba45ecb6ddb50dcd36808c79b Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 10:28:24 -0400 Subject: [PATCH 122/306] Use percentage calc instead of interval decrement for tic-based fading --- src/p_saveg.c | 4 ++-- src/p_spec.c | 41 ++++++++++++++++++++++++----------------- src/p_spec.h | 2 +- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index cafd05ea3..5550c7a8b 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1590,12 +1590,12 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type) WRITEUINT32(save_p, ht->sectornum); WRITEUINT32(save_p, ht->ffloornum); WRITEINT32(save_p, ht->alpha); + WRITEINT16(save_p, ht->sourcevalue); WRITEINT16(save_p, ht->destvalue); WRITEINT16(save_p, ht->destlightlevel); WRITEINT16(save_p, ht->speed); WRITEUINT8(save_p, (UINT8)ht->ticbased); WRITEINT32(save_p, ht->timer); - WRITEUINT32(save_p, ht->interval); WRITEUINT8(save_p, ht->doexists); WRITEUINT8(save_p, ht->dotranslucent); WRITEUINT8(save_p, ht->dolighting); @@ -2602,12 +2602,12 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->sectornum = READUINT32(save_p); ht->ffloornum = READUINT32(save_p); ht->alpha = READINT32(save_p); + ht->sourcevalue = READINT16(save_p); ht->destvalue = READINT16(save_p); ht->destlightlevel = READINT16(save_p); ht->speed = READINT16(save_p); ht->ticbased = (boolean)READUINT8(save_p); ht->timer = READINT32(save_p); - ht->interval = READUINT32(save_p); ht->doexists = READUINT8(save_p); ht->dotranslucent = READUINT8(save_p); ht->dolighting = READUINT8(save_p); diff --git a/src/p_spec.c b/src/p_spec.c index 8d42ef575..cd63191c9 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -105,7 +105,7 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t * static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize); #define P_RemoveFakeFloorFader(l) P_ResetFakeFloorFader(l, NULL, false); -static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, boolean ticbased, INT32 *timer, UINT32 interval, +static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destvalue, INT16 speed, boolean ticbased, INT32 *timer, boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha); static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, INT16 destvalue, INT16 speed, boolean ticbased, boolean relative, @@ -3363,9 +3363,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_RemoveFakeFloorFader(rover); P_FadeFakeFloor(rover, + rover->alpha, max(1, min(256, (line->flags & ML_EFFECT3) ? rover->alpha + destvalue : destvalue)), 0, // set alpha immediately - false, NULL, 0, // tic-based logic + false, NULL, // tic-based logic false, // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // handle FF_TRANSLUCENT false, // do not handle lighting @@ -3437,9 +3438,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_RemoveFakeFloorFader(rover); P_FadeFakeFloor(rover, + rover->alpha, max(1, min(256, (line->flags & ML_EFFECT3) ? rover->alpha + destvalue : destvalue)), 0, // set alpha immediately - false, NULL, 0, // tic-based logic + false, NULL, // tic-based logic !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT !(line->flags & ML_EFFECT2), // do not handle lighting @@ -7513,13 +7515,13 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz { if (finalize) P_FadeFakeFloor(rover, + fadingdata->sourcevalue, fadingdata->alpha >= fadingdata->destvalue ? fadingdata->alpha - 1 : // trigger fade-out finish fadingdata->alpha + 1, // trigger fade-in finish 0, fadingdata->ticbased, &fadingdata->timer, - fadingdata->interval, fadingdata->doexists, fadingdata->dotranslucent, fadingdata->docollision, @@ -7538,7 +7540,7 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz } } -static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, boolean ticbased, INT32 *timer, UINT32 interval, +static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destvalue, INT16 speed, boolean ticbased, INT32 *timer, boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha) { boolean stillfading = false; @@ -7592,8 +7594,12 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, bo { if (!ticbased) alpha -= speed; - else if (ticbased && !((*timer) % interval)) - alpha = max(alpha - speed, destvalue); + else + { + INT16 delta = abs(destvalue - sourcevalue); + fixed_t factor = min(FixedDiv(speed - (*timer), speed), 1*FRACUNIT); + alpha = max(min(alpha, sourcevalue - (INT16)FixedMul(delta, factor)), destvalue); + } stillfading = true; } } @@ -7601,7 +7607,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, bo { // finish fading in if (speed < 1 || (!ticbased && alpha + speed >= destvalue - speed) || - (ticbased && (--(*timer) <= 0|| alpha >= destvalue))) + (ticbased && (--(*timer) <= 0 || alpha >= destvalue))) { alpha = destvalue; @@ -7623,8 +7629,12 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 destvalue, INT16 speed, bo { if (!ticbased) alpha += speed; - else if (ticbased && !((*timer) % interval)) - alpha = min(alpha + speed, destvalue); + else + { + INT16 delta = abs(destvalue - sourcevalue); + fixed_t factor = min(FixedDiv(speed - (*timer), speed), 1*FRACUNIT); + alpha = min(max(alpha, sourcevalue + (INT16)FixedMul(delta, factor)), destvalue); + } stillfading = true; } } @@ -7813,22 +7823,19 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor d->sectornum = (UINT32)sectornum; d->ffloornum = (UINT32)ffloornum; - d->alpha = rover->alpha; + d->alpha = d->sourcevalue = rover->alpha; d->destvalue = max(1, min(256, relative ? rover->alpha + destvalue : destvalue)); // ffloor->alpha is 1-256 if (ticbased) { d->ticbased = true; - d->timer = abs(speed); - d->speed = max(abs(FixedFloor(FixedDiv(d->destvalue - d->alpha, d->timer))/FRACUNIT), 1); - d->interval = max(FixedFloor(FixedDiv(d->timer, abs(d->destvalue - d->alpha)))/FRACUNIT, 1); + d->timer = d->speed = abs(speed); // use d->speed as total duration } else { - d->speed = max(1, speed); // minimum speed 1/tic // if speed < 1, alpha is set immediately in thinker d->ticbased = false; + d->speed = max(1, speed); // minimum speed 1/tic // if speed < 1, alpha is set immediately in thinker d->timer = -1; - d->interval = 0; } d->doexists = doexists; @@ -7872,7 +7879,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor */ void T_Fade(fade_t *d) { - if (d->rover && !P_FadeFakeFloor(d->rover, d->destvalue, d->speed, d->ticbased, &d->timer, d->interval, + if (d->rover && !P_FadeFakeFloor(d->rover, d->sourcevalue, d->destvalue, d->speed, d->ticbased, &d->timer, d->doexists, d->dotranslucent, d->dolighting, d->docollision, d->doghostfade, d->exactalpha)) { // Finalize lighting, copypasta from P_AddFakeFloorFader diff --git a/src/p_spec.h b/src/p_spec.h index 25f6218dd..1970aeb6b 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -469,12 +469,12 @@ typedef struct UINT32 sectornum; ///< Number of ffloor target sector UINT32 ffloornum; ///< Number of ffloor of target sector INT32 alpha; ///< Internal alpha counter + INT16 sourcevalue; ///< Transparency value to fade from INT16 destvalue; ///< Transparency value to fade to INT16 destlightlevel; ///< Light level to fade to INT16 speed; ///< Speed to fade by boolean ticbased; ///< Tic-based logic toggle INT32 timer; ///< Timer for tic-based logic - UINT32 interval; ///< Skip interval for tic-based logic boolean doexists; ///< Handle FF_EXISTS boolean dotranslucent; ///< Handle FF_TRANSLUCENT boolean dolighting; ///< Handle shadows and light blocks From 56b947ae95afe2ea1767ef3a82aac3fb4197e2e7 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 13:10:14 -0400 Subject: [PATCH 123/306] Remove cr/cg/cb/ca in favor of rgba * Change default colormap values to be in sync with rgba/fadergba --- src/p_saveg.c | 51 +++++---------------------------------- src/r_data.c | 66 +++++++++++++-------------------------------------- src/r_defs.h | 6 ++--- 3 files changed, 24 insertions(+), 99 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 7ee41dffd..710c24821 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -662,15 +662,6 @@ static void P_NetArchiveWorld(void) WRITEUINT8(put, ss->extra_colormap->fadeend); WRITEUINT8(put, (UINT8)ss->extra_colormap->fog); - WRITEUINT8(put, ss->extra_colormap->cr); - WRITEUINT8(put, ss->extra_colormap->cg); - WRITEUINT8(put, ss->extra_colormap->cb); - WRITEUINT8(put, ss->extra_colormap->ca); - WRITEUINT8(put, ss->extra_colormap->cfr); - WRITEUINT8(put, ss->extra_colormap->cfg); - WRITEUINT8(put, ss->extra_colormap->cfb); - WRITEUINT8(put, ss->extra_colormap->cfa); - WRITEINT32(put, ss->extra_colormap->rgba); WRITEINT32(put, ss->extra_colormap->fadergba); @@ -883,15 +874,6 @@ static void P_NetUnArchiveWorld(void) boolean fog = (boolean)READUINT8(get); - UINT8 cr = READUINT8(get), - cg = READUINT8(get), - cb = READUINT8(get), - ca = READUINT8(get), - cfr = READUINT8(get), - cfg = READUINT8(get), - cfb = READUINT8(get), - cfa = READUINT8(get); - INT32 rgba = READINT32(get), fadergba = READINT32(get); @@ -905,20 +887,6 @@ static void P_NetUnArchiveWorld(void) { #endif - for (exc = extra_colormaps; exc; exc = exc->next) - { -#ifdef EXTRACOLORMAPLUMPS - if (exc->lump != LUMPERROR) - continue; -#endif - if (cr == exc->cr && cg == exc->cg && cb == exc->cb && ca == exc->ca - && cfr == exc->cfr && cfg == exc->cfg && cfb == exc->cfb && cfa == exc->cfa - && fadestart == exc->fadestart - && fadeend == exc->fadeend - && fog == exc->fog) - break; - } - for (exc = extra_colormaps; exc; exc = exc->next) { #ifdef EXTRACOLORMAPLUMPS @@ -928,14 +896,15 @@ static void P_NetUnArchiveWorld(void) continue; } #endif - if (cr == exc->cr && cg == exc->cg && cb == exc->cb && ca == exc->ca - && cfr == exc->cfr && cfg == exc->cfg && cfb == exc->cfb && cfa == exc->cfa + if (rgba == exc->rgba + && fadergba == exc->fadergba && fadestart == exc->fadestart && fadeend == exc->fadeend && fog == exc->fog) { // CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - // dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); + // dbg_i, (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF, + // (fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF); break; } //dbg_i++; @@ -944,7 +913,8 @@ static void P_NetUnArchiveWorld(void) if (!exc) { // CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - // dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); + // dbg_i, (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF, + // (fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF); exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); @@ -952,15 +922,6 @@ static void P_NetUnArchiveWorld(void) exc->fadeend = fadeend; exc->fog = fog; - exc->cr = cr; - exc->cg = cg; - exc->cb = cb; - exc->ca = ca; - exc->cfr = cfr; - exc->cfg = cfg; - exc->cfb = cfb; - exc->cfa = cfa; - exc->rgba = rgba; exc->fadergba = fadergba; diff --git a/src/r_data.c b/src/r_data.c index ffc6cc7fd..005056ec0 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1332,10 +1332,6 @@ void R_ClearColormaps(void) // make a default extra_colormap exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); - exc->cr = exc->cg = exc->cb = 0xff; - exc->ca = 0; - exc->cfr = exc->cfg = exc->cfb = 0; - exc->cfa = 18; exc->fadestart = 0; exc->fadeend = 31; exc->fog = 0; @@ -1411,10 +1407,6 @@ extracolormap_t *R_ColormapForName(char *name) // We set all params of the colormap to normal because there // is no real way to tell how GL should handle a colormap lump anyway.. - exc->cr = exc->cg = exc->cb = 0xff; - exc->ca = 0; - exc->cfr = exc->cfg = exc->cfb = 0; - exc->cfa = 18; exc->fadestart = 0; exc->fadeend = 31; exc->fog = 0; @@ -1445,14 +1437,14 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb; double maskamt = 0, othermask = 0; - UINT8 cr = extra_colormap->cr, - cg = extra_colormap->cg, - cb = extra_colormap->cb, - ca = extra_colormap->ca, - cfr = extra_colormap->cfr, - cfg = extra_colormap->cfg, - cfb = extra_colormap->cfb; -// cfa = extra_colormap->cfa; // unused in software + UINT8 cr = (extra_colormap->rgba) & 0xFF, + cg = (extra_colormap->rgba >> 8) & 0xFF, + cb = (extra_colormap->rgba >> 16) & 0xFF, + ca = (extra_colormap->rgba >> 24) & 0xFF, + cfr = (extra_colormap->fadergba) & 0xFF, + cfg = (extra_colormap->fadergba >> 8) & 0xFF, + cfb = (extra_colormap->fadergba >> 16) & 0xFF; +// cfa = (extra_colormap->fadergba >> 24) & 0xFF; // unused in software UINT8 fadestart = extra_colormap->fadestart, fadedist = extra_colormap->fadeend - extra_colormap->fadestart; @@ -1594,22 +1586,13 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) else if (p1[7] >= 'A' && p1[7] <= 'Z') ca = (p1[7] - 'A'); else - ca = 24; + ca = 25; - // for opengl; generate on software too for netsync - rgba = (HEX2INT(p1[1]) << 4) + (HEX2INT(p1[2]) << 0) + - (HEX2INT(p1[3]) << 12) + (HEX2INT(p1[4]) << 8) + - (HEX2INT(p1[5]) << 20) + (HEX2INT(p1[6]) << 16); - - if ((p1[7] >= 'a' && p1[7] <= 'z') || (p1[7] >= 'A' && p1[7] <= 'Z')) - rgba += (ALPHA2INT(p1[7]) << 24); - else - rgba += (25 << 24); + rgba = cr + (cg << 8) + (cb << 16) + (ca << 24); } else { - cr = cg = cb = 0xff; - ca = 0; + cr = cg = cb = ca = 0; rgba = 0; } @@ -1638,22 +1621,14 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) else if (p1[7] >= 'A' && p1[7] <= 'Z') cfa = (p1[7] - 'A'); else - cfa = 18; + cfa = 25; - // for opengl; generate on software too for netsync - fadergba = (HEX2INT(p3[1]) << 4) + (HEX2INT(p3[2]) << 0) + - (HEX2INT(p3[3]) << 12) + (HEX2INT(p3[4]) << 8) + - (HEX2INT(p3[5]) << 20) + (HEX2INT(p3[6]) << 16); - - if ((p3[7] >= 'a' && p3[7] <= 'z') || (p3[7] >= 'A' && p3[7] <= 'Z')) - fadergba += (ALPHA2INT(p3[7]) << 24); - else - fadergba += (25 << 24); + fadergba = cfr + (cfg << 8) + (cfb << 16) + (cfa << 24); } else { cfr = cfg = cfb = 0; - cfa = 18; + cfa = 25; fadergba = 0x19000000; // default alpha for fade, (25 << 24) } #undef ALPHA2INT @@ -1668,8 +1643,8 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) continue; } #endif - if (cr == exc->cr && cg == exc->cg && cb == exc->cb && ca == exc->ca - && cfr == exc->cfr && cfg == exc->cfg && cfb == exc->cfb && cfa == exc->cfa + if (rgba == exc->rgba + && fadergba == exc->fadergba && fadestart == exc->fadestart && fadeend == exc->fadeend && fog == exc->fog) @@ -1690,15 +1665,6 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) extra_colormap->fadeend = (UINT16)fadeend; extra_colormap->fog = fog; - extra_colormap->cr = cr; - extra_colormap->cg = cg; - extra_colormap->cb = cb; - extra_colormap->ca = ca; - extra_colormap->cfr = cfr; - extra_colormap->cfg = cfg; - extra_colormap->cfb = cfb; - extra_colormap->cfa = cfa; - extra_colormap->rgba = rgba; extra_colormap->fadergba = fadergba; diff --git a/src/r_defs.h b/src/r_defs.h index 22d4fdf14..99fad2b44 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -55,10 +55,8 @@ typedef struct extracolormap_s UINT8 fadestart, fadeend; boolean fog; - // rgba for colormap table generation - UINT8 cr, cg, cb, ca, cfr, cfg, cfb, cfa; - - // rgba is used in hw mode for colored sector lighting + // store rgba values in combined bitwise + // also used in OpenGL instead lighttables INT32 rgba; // similar to maskcolor in sw mode INT32 fadergba; // The colour the colourmaps fade to From a818b9a1dc0598e88eb24d912979f0cfcff0c06d Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 13:10:14 -0400 Subject: [PATCH 124/306] Remove cr/cg/cb/ca in favor of rgba * Change default colormap values to be in sync with rgba/fadergba --- src/p_saveg.c | 51 +++++---------------------------------- src/r_data.c | 66 +++++++++++++-------------------------------------- src/r_defs.h | 6 ++--- 3 files changed, 24 insertions(+), 99 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 7ee41dffd..710c24821 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -662,15 +662,6 @@ static void P_NetArchiveWorld(void) WRITEUINT8(put, ss->extra_colormap->fadeend); WRITEUINT8(put, (UINT8)ss->extra_colormap->fog); - WRITEUINT8(put, ss->extra_colormap->cr); - WRITEUINT8(put, ss->extra_colormap->cg); - WRITEUINT8(put, ss->extra_colormap->cb); - WRITEUINT8(put, ss->extra_colormap->ca); - WRITEUINT8(put, ss->extra_colormap->cfr); - WRITEUINT8(put, ss->extra_colormap->cfg); - WRITEUINT8(put, ss->extra_colormap->cfb); - WRITEUINT8(put, ss->extra_colormap->cfa); - WRITEINT32(put, ss->extra_colormap->rgba); WRITEINT32(put, ss->extra_colormap->fadergba); @@ -883,15 +874,6 @@ static void P_NetUnArchiveWorld(void) boolean fog = (boolean)READUINT8(get); - UINT8 cr = READUINT8(get), - cg = READUINT8(get), - cb = READUINT8(get), - ca = READUINT8(get), - cfr = READUINT8(get), - cfg = READUINT8(get), - cfb = READUINT8(get), - cfa = READUINT8(get); - INT32 rgba = READINT32(get), fadergba = READINT32(get); @@ -905,20 +887,6 @@ static void P_NetUnArchiveWorld(void) { #endif - for (exc = extra_colormaps; exc; exc = exc->next) - { -#ifdef EXTRACOLORMAPLUMPS - if (exc->lump != LUMPERROR) - continue; -#endif - if (cr == exc->cr && cg == exc->cg && cb == exc->cb && ca == exc->ca - && cfr == exc->cfr && cfg == exc->cfg && cfb == exc->cfb && cfa == exc->cfa - && fadestart == exc->fadestart - && fadeend == exc->fadeend - && fog == exc->fog) - break; - } - for (exc = extra_colormaps; exc; exc = exc->next) { #ifdef EXTRACOLORMAPLUMPS @@ -928,14 +896,15 @@ static void P_NetUnArchiveWorld(void) continue; } #endif - if (cr == exc->cr && cg == exc->cg && cb == exc->cb && ca == exc->ca - && cfr == exc->cfr && cfg == exc->cfg && cfb == exc->cfb && cfa == exc->cfa + if (rgba == exc->rgba + && fadergba == exc->fadergba && fadestart == exc->fadestart && fadeend == exc->fadeend && fog == exc->fog) { // CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - // dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); + // dbg_i, (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF, + // (fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF); break; } //dbg_i++; @@ -944,7 +913,8 @@ static void P_NetUnArchiveWorld(void) if (!exc) { // CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - // dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); + // dbg_i, (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF, + // (fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF); exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); @@ -952,15 +922,6 @@ static void P_NetUnArchiveWorld(void) exc->fadeend = fadeend; exc->fog = fog; - exc->cr = cr; - exc->cg = cg; - exc->cb = cb; - exc->ca = ca; - exc->cfr = cfr; - exc->cfg = cfg; - exc->cfb = cfb; - exc->cfa = cfa; - exc->rgba = rgba; exc->fadergba = fadergba; diff --git a/src/r_data.c b/src/r_data.c index ffc6cc7fd..005056ec0 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1332,10 +1332,6 @@ void R_ClearColormaps(void) // make a default extra_colormap exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); - exc->cr = exc->cg = exc->cb = 0xff; - exc->ca = 0; - exc->cfr = exc->cfg = exc->cfb = 0; - exc->cfa = 18; exc->fadestart = 0; exc->fadeend = 31; exc->fog = 0; @@ -1411,10 +1407,6 @@ extracolormap_t *R_ColormapForName(char *name) // We set all params of the colormap to normal because there // is no real way to tell how GL should handle a colormap lump anyway.. - exc->cr = exc->cg = exc->cb = 0xff; - exc->ca = 0; - exc->cfr = exc->cfg = exc->cfb = 0; - exc->cfa = 18; exc->fadestart = 0; exc->fadeend = 31; exc->fog = 0; @@ -1445,14 +1437,14 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb; double maskamt = 0, othermask = 0; - UINT8 cr = extra_colormap->cr, - cg = extra_colormap->cg, - cb = extra_colormap->cb, - ca = extra_colormap->ca, - cfr = extra_colormap->cfr, - cfg = extra_colormap->cfg, - cfb = extra_colormap->cfb; -// cfa = extra_colormap->cfa; // unused in software + UINT8 cr = (extra_colormap->rgba) & 0xFF, + cg = (extra_colormap->rgba >> 8) & 0xFF, + cb = (extra_colormap->rgba >> 16) & 0xFF, + ca = (extra_colormap->rgba >> 24) & 0xFF, + cfr = (extra_colormap->fadergba) & 0xFF, + cfg = (extra_colormap->fadergba >> 8) & 0xFF, + cfb = (extra_colormap->fadergba >> 16) & 0xFF; +// cfa = (extra_colormap->fadergba >> 24) & 0xFF; // unused in software UINT8 fadestart = extra_colormap->fadestart, fadedist = extra_colormap->fadeend - extra_colormap->fadestart; @@ -1594,22 +1586,13 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) else if (p1[7] >= 'A' && p1[7] <= 'Z') ca = (p1[7] - 'A'); else - ca = 24; + ca = 25; - // for opengl; generate on software too for netsync - rgba = (HEX2INT(p1[1]) << 4) + (HEX2INT(p1[2]) << 0) + - (HEX2INT(p1[3]) << 12) + (HEX2INT(p1[4]) << 8) + - (HEX2INT(p1[5]) << 20) + (HEX2INT(p1[6]) << 16); - - if ((p1[7] >= 'a' && p1[7] <= 'z') || (p1[7] >= 'A' && p1[7] <= 'Z')) - rgba += (ALPHA2INT(p1[7]) << 24); - else - rgba += (25 << 24); + rgba = cr + (cg << 8) + (cb << 16) + (ca << 24); } else { - cr = cg = cb = 0xff; - ca = 0; + cr = cg = cb = ca = 0; rgba = 0; } @@ -1638,22 +1621,14 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) else if (p1[7] >= 'A' && p1[7] <= 'Z') cfa = (p1[7] - 'A'); else - cfa = 18; + cfa = 25; - // for opengl; generate on software too for netsync - fadergba = (HEX2INT(p3[1]) << 4) + (HEX2INT(p3[2]) << 0) + - (HEX2INT(p3[3]) << 12) + (HEX2INT(p3[4]) << 8) + - (HEX2INT(p3[5]) << 20) + (HEX2INT(p3[6]) << 16); - - if ((p3[7] >= 'a' && p3[7] <= 'z') || (p3[7] >= 'A' && p3[7] <= 'Z')) - fadergba += (ALPHA2INT(p3[7]) << 24); - else - fadergba += (25 << 24); + fadergba = cfr + (cfg << 8) + (cfb << 16) + (cfa << 24); } else { cfr = cfg = cfb = 0; - cfa = 18; + cfa = 25; fadergba = 0x19000000; // default alpha for fade, (25 << 24) } #undef ALPHA2INT @@ -1668,8 +1643,8 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) continue; } #endif - if (cr == exc->cr && cg == exc->cg && cb == exc->cb && ca == exc->ca - && cfr == exc->cfr && cfg == exc->cfg && cfb == exc->cfb && cfa == exc->cfa + if (rgba == exc->rgba + && fadergba == exc->fadergba && fadestart == exc->fadestart && fadeend == exc->fadeend && fog == exc->fog) @@ -1690,15 +1665,6 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) extra_colormap->fadeend = (UINT16)fadeend; extra_colormap->fog = fog; - extra_colormap->cr = cr; - extra_colormap->cg = cg; - extra_colormap->cb = cb; - extra_colormap->ca = ca; - extra_colormap->cfr = cfr; - extra_colormap->cfg = cfg; - extra_colormap->cfb = cfb; - extra_colormap->cfa = cfa; - extra_colormap->rgba = rgba; extra_colormap->fadergba = fadergba; diff --git a/src/r_defs.h b/src/r_defs.h index 22d4fdf14..99fad2b44 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -55,10 +55,8 @@ typedef struct extracolormap_s UINT8 fadestart, fadeend; boolean fog; - // rgba for colormap table generation - UINT8 cr, cg, cb, ca, cfr, cfg, cfb, cfa; - - // rgba is used in hw mode for colored sector lighting + // store rgba values in combined bitwise + // also used in OpenGL instead lighttables INT32 rgba; // similar to maskcolor in sw mode INT32 fadergba; // The colour the colourmaps fade to From 506ce43627c2d954da8f12bb1c76b2828a116189 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 13:31:09 -0400 Subject: [PATCH 125/306] Initialize extra_colormaps to NULL on program start --- src/r_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_main.c b/src/r_main.c index 281058362..bfca180d0 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -118,7 +118,7 @@ lighttable_t *scalelightfixed[MAXLIGHTSCALE]; lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; // Hack to support extra boom colormaps. -extracolormap_t *extra_colormaps; +extracolormap_t *extra_colormaps = NULL; static CV_PossibleValue_t drawdist_cons_t[] = { {256, "256"}, {512, "512"}, {768, "768"}, From 4ef016e40fe9fdb5b0abb9fd3e101e0efd2f7a98 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 13:46:34 -0400 Subject: [PATCH 126/306] Clear colormaps properly (resolve sigsegv crash) --- src/r_data.c | 23 +++++++++++------------ src/r_data.h | 1 + 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 005056ec0..4358f7536 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1322,29 +1322,28 @@ void R_ReInitColormaps(UINT16 num) // void R_ClearColormaps(void) { - extracolormap_t *exc, *exc_next; + // Purged by PU_LEVEL, just overwrite the pointer + extra_colormaps = R_CreateDefaultColormap(true); +} - for (exc = extra_colormaps; exc; exc = exc_next) - { - exc_next = exc->next; - memset(exc, 0, sizeof(*exc)); - } - - // make a default extra_colormap - exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); +// +// R_CreateDefaultColormap() +// +extracolormap_t *R_CreateDefaultColormap(boolean lighttable) +{ + extracolormap_t *exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); exc->fadestart = 0; exc->fadeend = 31; exc->fog = 0; exc->rgba = 0; exc->fadergba = 0x19000000; - exc->colormap = R_CreateLightTable(exc); + exc->colormap = lighttable ? R_CreateLightTable(exc) : NULL; #ifdef EXTRACOLORMAPLUMPS exc->lump = LUMPERROR; exc->lumpname[0] = 0; #endif exc->next = exc->prev = NULL; - - extra_colormaps = exc; + return exc; } // diff --git a/src/r_data.h b/src/r_data.h index e6eec41b4..718abeccc 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -105,6 +105,7 @@ INT32 R_CheckTextureNumForName(const char *name); void R_ReInitColormaps(UINT16 num); void R_ClearColormaps(void); +extracolormap_t *R_CreateDefaultColormap(boolean lighttable); void R_AddColormapToList(extracolormap_t *extra_colormap); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3); From ba88f8ebb66a55bf6d4966e72649f5151195e258 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 15:01:05 -0400 Subject: [PATCH 127/306] Smarter string digit parsing; allow alpha-only values * GetDefaultColormap and CheckDefaultColormapValues methods --- src/p_setup.c | 11 ++- src/r_data.c | 182 +++++++++++++++++++++++++++++++++++++++----------- src/r_data.h | 2 + 3 files changed, 149 insertions(+), 46 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index b503b6a58..77d53812c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1472,12 +1472,11 @@ static void P_LoadRawSideDefs2(void *data) case 606: //SoM: 4/4/2000: Just colormap transfer // SoM: R_CreateColormap will only create a colormap in software mode... // Perhaps we should just call it instead of doing the calculations here. - if ( - ((rendermode == render_soft || rendermode == render_none) && (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#')) -#ifdef HWRENDER - || (msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6]) - || (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6]) -#endif + if (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#' + || (msd->toptexture[0] >= 'a' && msd->toptexture[0] <= 'z' && !msd->toptexture[1]) + || (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'Z' && !msd->toptexture[1]) + || (msd->bottomtexture[0] >= 'a' && msd->bottomtexture[0] <= 'z' && !msd->bottomtexture[1]) + || (msd->bottomtexture[0] >= 'A' && msd->bottomtexture[0] <= 'Z' && !msd->bottomtexture[1]) ) { sec->extra_colormap = sec->spawn_extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture, diff --git a/src/r_data.c b/src/r_data.c index 4358f7536..958eeeb37 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1346,6 +1346,49 @@ extracolormap_t *R_CreateDefaultColormap(boolean lighttable) return exc; } +// +// R_GetDefaultColormap() +// +extracolormap_t *R_GetDefaultColormap(void) +{ +#ifdef COLORMAPREVERSELIST + extracolormap_t *exc; +#endif + + if (!extra_colormaps) + return (extra_colormaps = R_CreateDefaultColormap(true)); + +#ifdef COLORMAPREVERSELIST + for (exc = extra_colormaps; exc->next; exc = exc->next); + return exc; +#else + return extra_colormaps; +#endif +} + +// +// R_CheckDefaultColormap() +// +boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams) +{ + if (!extra_colormap) + return true; + else + return ( + (!checkparams ? true : + (extra_colormap->fadestart == 0 + && extra_colormap->fadeend == 31 + && !extra_colormap->fog) + ) + && (!checkrgba ? true : extra_colormap->rgba == 0) + && (!checkfadergba ? true : extra_colormap->fadergba == 0x19000000) +#ifdef EXTRACOLORMAPLUMPS + && extra_colormap->lump == LUMPERROR + && extra_colormap->lumpname[0] == 0 +#endif + ); +} + // // R_AddColormapToList // @@ -1562,77 +1605,133 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) { - boolean fog = false; extracolormap_t *extra_colormap, *exc; - UINT8 cr, cg, cb, ca, cfr, cfg, cfb, cfa; + // default values + UINT8 cr = 0, cg = 0, cb = 0, ca = 0, cfr = 0, cfg = 0, cfb = 0, cfa = 25; UINT32 fadestart = 0, fadeend = 31; - - INT32 rgba, fadergba; + boolean fog = false; + INT32 rgba = 0, fadergba = 0x19000000; size_t dbg_i = 0; #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) #define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0) - if (p1[0] == '#') - { - cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2])); - cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4])); - cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6])); - if (p1[7] >= 'a' && p1[7] <= 'z') - ca = (p1[7] - 'a'); - else if (p1[7] >= 'A' && p1[7] <= 'Z') - ca = (p1[7] - 'A'); + // Get base colormap value + // First alpha-only, then full value + if (p1[0] >= 'a' && p1[0] <= 'z' && !p1[1]) + ca = (p1[0] - 'a'); + else if (p1[0] == '#' && p1[1] >= 'a' && p1[1] <= 'z' && !p1[2]) + ca = (p1[1] - 'a'); + else if (p1[0] >= 'A' && p1[0] <= 'Z' && !p1[1]) + ca = (p1[0] - 'A'); + else if (p1[0] == '#' && p1[1] >= 'A' && p1[1] <= 'Z' && !p1[2]) + ca = (p1[1] - 'A'); + else if (p1[0] == '#') + { + // For each subsequent value, the value before it must exist + // If we don't get every value, then set alpha to max + if (p1[1] && p1[2]) + { + cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2])); + if (p1[3] && p1[4]) + { + cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4])); + if (p1[5] && p1[6]) + { + cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6])); + + if (p1[7] >= 'a' && p1[7] <= 'z') + ca = (p1[7] - 'a'); + else if (p1[7] >= 'A' && p1[7] <= 'Z') + ca = (p1[7] - 'A'); + else + ca = 25; + } + else + ca = 25; + } + else + ca = 25; + } else ca = 25; - - rgba = cr + (cg << 8) + (cb << 16) + (ca << 24); - } - else - { - cr = cg = cb = ca = 0; - rgba = 0; } #define NUMFROMCHAR(c) (c >= '0' && c <= '9' ? c - '0' : 0) + + // Get parameters like fadestart, fadeend, and the fogflag if (p2[0] == '#') { - // Get parameters like fadestart, fadeend, and the fogflag - fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10); - fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10); + if (p2[1]) + { + fog = (boolean)NUMFROMCHAR(p2[1]); + if (p2[2] && p2[3]) + { + fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10); + if (p2[4] && p2[5]) + fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10); + } + } + if (fadestart > 30) fadestart = 0; if (fadeend > 31 || fadeend < 1) fadeend = 31; - fog = (boolean)NUMFROMCHAR(p2[1]); } + #undef NUMFROMCHAR - if (p3[0] == '#') + // Get fade (dark) colormap value + // First alpha-only, then full value + if (p3[0] >= 'a' && p3[0] <= 'z' && !p3[1]) + cfa = (p3[0] - 'a'); + else if (p3[0] == '#' && p3[1] >= 'a' && p3[1] <= 'z' && !p3[2]) + cfa = (p3[1] - 'a'); + else if (p3[0] >= 'A' && p3[0] <= 'Z' && !p3[1]) + cfa = (p3[0] - 'A'); + else if (p3[0] == '#' && p3[1] >= 'A' && p3[1] <= 'Z' && !p3[2]) + cfa = (p3[1] - 'A'); + else if (p3[0] == '#') { - cfr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2])); - cfg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4])); - cfb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6])); + // For each subsequent value, the value before it must exist + // If we don't get every value, then set alpha to max + if (p3[1] && p3[2]) + { + cfr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2])); + if (p3[3] && p3[4]) + { + cfg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4])); + if (p3[5] && p3[6]) + { + cfb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6])); - if (p1[7] >= 'a' && p1[7] <= 'z') - cfa = (p1[7] - 'a'); - else if (p1[7] >= 'A' && p1[7] <= 'Z') - cfa = (p1[7] - 'A'); + if (p3[7] >= 'a' && p3[7] <= 'z') + cfa = (p3[7] - 'a'); + else if (p3[7] >= 'A' && p3[7] <= 'Z') + cfa = (p3[7] - 'A'); + else + cfa = 25; + } + else + cfa = 25; + } + else + cfa = 25; + } else cfa = 25; - - fadergba = cfr + (cfg << 8) + (cfb << 16) + (cfa << 24); - } - else - { - cfr = cfg = cfb = 0; - cfa = 25; - fadergba = 0x19000000; // default alpha for fade, (25 << 24) } #undef ALPHA2INT #undef HEX2INT + // Pack rgba values into combined var + // OpenGL also uses this instead of lighttables for rendering + rgba = cr + (cg << 8) + (cb << 16) + (ca << 24); + fadergba = cfr + (cfg << 8) + (cfb << 16) + (cfa << 24); + + // Look for existing colormaps for (exc = extra_colormaps; exc; exc = exc->next) { #ifdef EXTRACOLORMAPLUMPS @@ -1672,6 +1771,9 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) extra_colormap->lumpname[0] = 0; #endif + // Having lighttables for alpha-only entries is kind of pointless, + // but if there happens to be a matching rgba entry that is NOT alpha-only (but has same rgb values), + // then it needs this lighttable because we share matching entries. extra_colormap->colormap = R_CreateLightTable(extra_colormap); R_AddColormapToList(extra_colormap); diff --git a/src/r_data.h b/src/r_data.h index 718abeccc..95ea44a83 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -106,6 +106,8 @@ INT32 R_CheckTextureNumForName(const char *name); void R_ReInitColormaps(UINT16 num); void R_ClearColormaps(void); extracolormap_t *R_CreateDefaultColormap(boolean lighttable); +extracolormap_t *R_GetDefaultColormap(void); +boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams); void R_AddColormapToList(extracolormap_t *extra_colormap); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3); From 85d89287de8521fe320275716b1e924b177e3a6d Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 15:20:30 -0400 Subject: [PATCH 128/306] Add R_CopyColormap --- src/r_data.c | 62 +++++++++++++++++++++++++++++++++++++++------------- src/r_data.h | 3 ++- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 958eeeb37..ad27b442f 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1367,26 +1367,35 @@ extracolormap_t *R_GetDefaultColormap(void) } // -// R_CheckDefaultColormap() +// R_CopyColormap() // -boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams) +extracolormap_t *R_CopyColormap(extracolormap_t *extra_colormap, boolean lighttable) { + extracolormap_t *exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); + if (!extra_colormap) - return true; - else - return ( - (!checkparams ? true : - (extra_colormap->fadestart == 0 - && extra_colormap->fadeend == 31 - && !extra_colormap->fog) - ) - && (!checkrgba ? true : extra_colormap->rgba == 0) - && (!checkfadergba ? true : extra_colormap->fadergba == 0x19000000) + extra_colormap = R_GetDefaultColormap(); + + *exc = *extra_colormap; + exc->next = exc->prev = NULL; + #ifdef EXTRACOLORMAPLUMPS - && extra_colormap->lump == LUMPERROR - && extra_colormap->lumpname[0] == 0 + strncpy(exc->lumpname, extra_colormap->lumpname, 9); + + if (exc->lump != LUMPERROR && lighttable) + { + // aligned on 8 bit for asm code + exc->colormap = Z_MallocAlign(W_LumpLength(lump), PU_LEVEL, NULL, 16); + W_ReadLump(lump, exc->colormap); + } + else #endif - ); + if (lighttable) + exc->colormap = R_CreateLightTable(exc); + else + exc->colormap = NULL; + + return exc; } // @@ -1423,6 +1432,29 @@ void R_AddColormapToList(extracolormap_t *extra_colormap) #endif } +// +// R_CheckDefaultColormap() +// +boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams) +{ + if (!extra_colormap) + return true; + else + return ( + (!checkparams ? true : + (extra_colormap->fadestart == 0 + && extra_colormap->fadeend == 31 + && !extra_colormap->fog) + ) + && (!checkrgba ? true : extra_colormap->rgba == 0) + && (!checkfadergba ? true : extra_colormap->fadergba == 0x19000000) +#ifdef EXTRACOLORMAPLUMPS + && extra_colormap->lump == LUMPERROR + && extra_colormap->lumpname[0] == 0 +#endif + ); +} + #ifdef EXTRACOLORMAPLUMPS extracolormap_t *R_ColormapForName(char *name) { diff --git a/src/r_data.h b/src/r_data.h index 95ea44a83..fc6d71299 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -107,8 +107,9 @@ void R_ReInitColormaps(UINT16 num); void R_ClearColormaps(void); extracolormap_t *R_CreateDefaultColormap(boolean lighttable); extracolormap_t *R_GetDefaultColormap(void); -boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams); +extracolormap_t *R_CopyColormap(extracolormap_t *extra_colormap, boolean lighttable); void R_AddColormapToList(extracolormap_t *extra_colormap); +boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3); #ifdef EXTRACOLORMAPLUMPS From 78aefc05cf8c871392ddb03ff7cc4b955202ce71 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 15:50:12 -0400 Subject: [PATCH 129/306] Consolidate colormap matching into R_GetExistingColormap --- src/p_saveg.c | 30 +++---------------- src/r_data.c | 82 +++++++++++++++++++++++++++++++++++---------------- src/r_data.h | 5 ++++ 3 files changed, 65 insertions(+), 52 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 710c24821..d9158d99c 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -886,35 +886,13 @@ static void P_NetUnArchiveWorld(void) else { #endif - - for (exc = extra_colormaps; exc; exc = exc->next) - { -#ifdef EXTRACOLORMAPLUMPS - if (exc->lump != LUMPERROR) - { - //dbg_i++; - continue; - } -#endif - if (rgba == exc->rgba - && fadergba == exc->fadergba - && fadestart == exc->fadestart - && fadeend == exc->fadeend - && fog == exc->fog) - { - // CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - // dbg_i, (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF, - // (fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF); - break; - } - //dbg_i++; - } + exc = R_GetExistingColormapByValues(rgba, fadergba, fadestart, fadeend, fog); if (!exc) { - // CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - // dbg_i, (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF, - // (fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF); + // CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + // (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF, + // (fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF); exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); diff --git a/src/r_data.c b/src/r_data.c index ad27b442f..0e4a67e2d 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1328,6 +1328,7 @@ void R_ClearColormaps(void) // // R_CreateDefaultColormap() +// NOTE: The result colormap is not added to the extra_colormaps chain. You must do that yourself! // extracolormap_t *R_CreateDefaultColormap(boolean lighttable) { @@ -1368,6 +1369,7 @@ extracolormap_t *R_GetDefaultColormap(void) // // R_CopyColormap() +// NOTE: The result colormap is not added to the extra_colormaps chain. You must do that yourself! // extracolormap_t *R_CopyColormap(extracolormap_t *extra_colormap, boolean lighttable) { @@ -1455,6 +1457,50 @@ boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean ch ); } +// +// R_GetExistingColormapByValues() +// NOTE: Returns NULL if no match is found +// +#ifdef EXTRACOLORMAPLUMPS +extracolormap_t *R_GetExistingColormapByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump) +#else +extracolormap_t *R_GetExistingColormapByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog) +#endif +{ + extracolormap_t *exc; + size_t dbg_i = 0; + + for (exc = extra_colormaps; exc; exc = exc->next) + { + if (rgba == exc->rgba + && fadergba == exc->fadergba + && fadestart == exc->fadestart + && fadeend == exc->fadeend + && fog == exc->fog +#ifdef EXTRACOLORMAPLUMPS + && (lump != LUMPERROR && lump == exc->lump) +#endif + ) + { + CONS_Debug(DBG_RENDER, "Found Colormap %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + dbg_i, (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF, + (fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF); + return exc; + } + dbg_i++; + } + return NULL; +} + +extracolormap_t *R_GetExistingColormap(extracolormap_t *extra_colormap) +{ +#ifdef EXTRACOLORMAPLUMPS + return R_GetExistingColormapByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog, extra_colormap->lump); +else + return R_GetExistingColormapByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog); +#endif +} + #ifdef EXTRACOLORMAPLUMPS extracolormap_t *R_ColormapForName(char *name) { @@ -1465,9 +1511,9 @@ extracolormap_t *R_ColormapForName(char *name) if (lump == LUMPERROR) I_Error("R_ColormapForName: Cannot find colormap lump %.8s\n", name); - for (exc = extra_colormaps; exc; exc = exc->next) - if (lump == exc->lump) - return exc; + exc = R_GetExistingColormapByValues(0, 0x19000000, 0, 31, 0, lump); + if (exc) + return exc; exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); @@ -1645,8 +1691,6 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) boolean fog = false; INT32 rgba = 0, fadergba = 0x19000000; - size_t dbg_i = 0; - #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) #define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0) @@ -1764,30 +1808,16 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) fadergba = cfr + (cfg << 8) + (cfb << 16) + (cfa << 24); // Look for existing colormaps - for (exc = extra_colormaps; exc; exc = exc->next) - { #ifdef EXTRACOLORMAPLUMPS - if (exc->lump != LUMPERROR) - { - dbg_i++; - continue; - } + exc = R_GetExistingColormapByValues(rgba, fadergba, fadestart, fadeend, fog, LUMPERROR); +#else + exc = R_GetExistingColormapByValues(rgba, fadergba, fadestart, fadeend, fog); #endif - if (rgba == exc->rgba - && fadergba == exc->fadergba - && fadestart == exc->fadestart - && fadeend == exc->fadeend - && fog == exc->fog) - { - CONS_Debug(DBG_RENDER, "R_CreateColormap: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); - return exc; - } - dbg_i++; - } + if (exc) + return exc; - CONS_Debug(DBG_RENDER, "R_CreateColormap: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); + CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + cr, cg, cb, ca, cfr, cfg, cfb, cfa); extra_colormap = Z_Calloc(sizeof (*extra_colormap), PU_LEVEL, NULL); diff --git a/src/r_data.h b/src/r_data.h index fc6d71299..a2db8ba5c 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -110,6 +110,11 @@ extracolormap_t *R_GetDefaultColormap(void); extracolormap_t *R_CopyColormap(extracolormap_t *extra_colormap, boolean lighttable); void R_AddColormapToList(extracolormap_t *extra_colormap); boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams); +#ifdef EXTRACOLORMAPLUMPS +extracolormap_t *R_GetExistingColormapByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump); +#else +extracolormap_t *R_GetExistingColormapByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog); +#endif lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3); #ifdef EXTRACOLORMAPLUMPS From c920827032429c013e410881f12102c7179b5e6e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 15:50:12 -0400 Subject: [PATCH 130/306] Consolidate colormap matching into R_GetColormapFromList --- src/p_saveg.c | 30 +++---------------- src/r_data.c | 82 +++++++++++++++++++++++++++++++++++---------------- src/r_data.h | 6 ++++ 3 files changed, 66 insertions(+), 52 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 710c24821..b887b8a73 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -886,35 +886,13 @@ static void P_NetUnArchiveWorld(void) else { #endif - - for (exc = extra_colormaps; exc; exc = exc->next) - { -#ifdef EXTRACOLORMAPLUMPS - if (exc->lump != LUMPERROR) - { - //dbg_i++; - continue; - } -#endif - if (rgba == exc->rgba - && fadergba == exc->fadergba - && fadestart == exc->fadestart - && fadeend == exc->fadeend - && fog == exc->fog) - { - // CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - // dbg_i, (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF, - // (fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF); - break; - } - //dbg_i++; - } + exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog); if (!exc) { - // CONS_Debug(DBG_RENDER, "P_NetUnArchiveWorld: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - // dbg_i, (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF, - // (fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF); + // CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + // (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF, + // (fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF); exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); diff --git a/src/r_data.c b/src/r_data.c index ad27b442f..e679f27ba 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1328,6 +1328,7 @@ void R_ClearColormaps(void) // // R_CreateDefaultColormap() +// NOTE: The result colormap is not added to the extra_colormaps chain. You must do that yourself! // extracolormap_t *R_CreateDefaultColormap(boolean lighttable) { @@ -1368,6 +1369,7 @@ extracolormap_t *R_GetDefaultColormap(void) // // R_CopyColormap() +// NOTE: The result colormap is not added to the extra_colormaps chain. You must do that yourself! // extracolormap_t *R_CopyColormap(extracolormap_t *extra_colormap, boolean lighttable) { @@ -1455,6 +1457,50 @@ boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean ch ); } +// +// R_GetColormapFromListByValues() +// NOTE: Returns NULL if no match is found +// +#ifdef EXTRACOLORMAPLUMPS +extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump) +#else +extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog) +#endif +{ + extracolormap_t *exc; + size_t dbg_i = 0; + + for (exc = extra_colormaps; exc; exc = exc->next) + { + if (rgba == exc->rgba + && fadergba == exc->fadergba + && fadestart == exc->fadestart + && fadeend == exc->fadeend + && fog == exc->fog +#ifdef EXTRACOLORMAPLUMPS + && (lump != LUMPERROR && lump == exc->lump) +#endif + ) + { + CONS_Debug(DBG_RENDER, "Found Colormap %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + dbg_i, (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF, + (fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF); + return exc; + } + dbg_i++; + } + return NULL; +} + +extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap) +{ +#ifdef EXTRACOLORMAPLUMPS + return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog, extra_colormap->lump); +else + return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog); +#endif +} + #ifdef EXTRACOLORMAPLUMPS extracolormap_t *R_ColormapForName(char *name) { @@ -1465,9 +1511,9 @@ extracolormap_t *R_ColormapForName(char *name) if (lump == LUMPERROR) I_Error("R_ColormapForName: Cannot find colormap lump %.8s\n", name); - for (exc = extra_colormaps; exc; exc = exc->next) - if (lump == exc->lump) - return exc; + exc = R_GetColormapFromListByValues(0, 0x19000000, 0, 31, 0, lump); + if (exc) + return exc; exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); @@ -1645,8 +1691,6 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) boolean fog = false; INT32 rgba = 0, fadergba = 0x19000000; - size_t dbg_i = 0; - #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) #define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0) @@ -1764,30 +1808,16 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) fadergba = cfr + (cfg << 8) + (cfb << 16) + (cfa << 24); // Look for existing colormaps - for (exc = extra_colormaps; exc; exc = exc->next) - { #ifdef EXTRACOLORMAPLUMPS - if (exc->lump != LUMPERROR) - { - dbg_i++; - continue; - } + exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog, LUMPERROR); +#else + exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog); #endif - if (rgba == exc->rgba - && fadergba == exc->fadergba - && fadestart == exc->fadestart - && fadeend == exc->fadeend - && fog == exc->fog) - { - CONS_Debug(DBG_RENDER, "R_CreateColormap: Found map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); - return exc; - } - dbg_i++; - } + if (exc) + return exc; - CONS_Debug(DBG_RENDER, "R_CreateColormap: Creating map %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - dbg_i, cr, cg, cb, ca, cfr, cfg, cfb, cfa); + CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + cr, cg, cb, ca, cfr, cfg, cfb, cfa); extra_colormap = Z_Calloc(sizeof (*extra_colormap), PU_LEVEL, NULL); diff --git a/src/r_data.h b/src/r_data.h index fc6d71299..17d85fd8b 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -110,6 +110,12 @@ extracolormap_t *R_GetDefaultColormap(void); extracolormap_t *R_CopyColormap(extracolormap_t *extra_colormap, boolean lighttable); void R_AddColormapToList(extracolormap_t *extra_colormap); boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams); +#ifdef EXTRACOLORMAPLUMPS +extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump); +#else +extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog); +#endif +extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3); #ifdef EXTRACOLORMAPLUMPS From fb7ac4ccae6a345da7f716cbddde1eea737b06d1 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 15:59:13 -0400 Subject: [PATCH 131/306] Ifdef typo --- src/r_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_data.c b/src/r_data.c index e679f27ba..e08600cae 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1496,7 +1496,7 @@ extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap) { #ifdef EXTRACOLORMAPLUMPS return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog, extra_colormap->lump); -else +#else return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog); #endif } From 71ade23739a6eddce5b4c1c2d1b4210b4103a25d Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 15:59:13 -0400 Subject: [PATCH 132/306] Ifdef typo --- src/r_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_data.c b/src/r_data.c index e679f27ba..e08600cae 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1496,7 +1496,7 @@ extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap) { #ifdef EXTRACOLORMAPLUMPS return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog, extra_colormap->lump); -else +#else return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog); #endif } From bb6cf6a807f6946de1a8cfcc6b848fcec2daf351 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 16:50:35 -0400 Subject: [PATCH 133/306] Added alpha-only, relative calc, and offset params to 447 Change Colormap --- src/p_spec.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 21380584b..8d17c6de3 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3256,7 +3256,43 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // This could even override existing colormaps I believe // -- Monster Iestyn 14/06/18 for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;) - sectors[secnum].extra_colormap = line->frontsector->extra_colormap; + { + if (line->flags & ML_NOCLIMB) // set alpha only + { + if (sectors[secnum].extra_colormap) // does nothing without an existing colormap + { + extracolormap_t *dest_colormap = R_CopyColormap(sectors[secnum].extra_colormap, false); + INT16 alpha; + + // base rgba + alpha = (line->flags & ML_DONTPEGBOTTOM && line->sidenum[1] != 0xFFFF) ? + (sides[line->sidenum[1]].textureoffset >> FRACBITS) + : R_GetRgbaA(line->frontsector->extra_colormap->rgba); + if (line->flags & ML_EFFECT3) // relative calc + alpha = max(min(R_GetRgbaA(sectors[secnum].extra_colormap->rgba) + alpha, 25), 0); + dest_colormap->rgba = (dest_colormap->rgba & 0xFFFFFF) + (alpha << 24); + + // fade rgba + alpha = (line->flags & ML_DONTPEGBOTTOM && line->sidenum[1] != 0xFFFF) ? + (sides[line->sidenum[1]].rowoffset >> FRACBITS) + : R_GetRgbaA(line->frontsector->extra_colormap->fadergba); + if (line->flags & ML_EFFECT3) // relative calc + alpha = max(min(R_GetRgbaA(sectors[secnum].extra_colormap->fadergba) + alpha, 25), 0); + dest_colormap->fadergba = (dest_colormap->fadergba & 0xFFFFFF) + (alpha << 24); + + if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(dest_colormap))) + { + dest_colormap->colormap = R_CreateLightTable(dest_colormap); + R_AddColormapToList(dest_colormap); + sectors[secnum].extra_colormap = dest_colormap; + } + else + memset(dest_colormap, 0, sizeof(*dest_colormap)); + } + } + else + sectors[secnum].extra_colormap = line->frontsector->extra_colormap; + } break; case 448: // Change skybox viewpoint/centerpoint From f703c195027c4c5c6b798ffb043ba5a50c591998 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 17:06:44 -0400 Subject: [PATCH 134/306] Don't set sector's extra_colormap if we just made a default clone * Allow colormap parsing to proceed in p_setup always * Add R_CheckDefaultColormap * Add R_GetRgbaR/G/B/A macros --- src/p_setup.c | 30 +++-------------------- src/r_data.c | 68 ++++++++++++++++++++++++++++++++++----------------- src/r_data.h | 13 +++++++++- 3 files changed, 61 insertions(+), 50 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 0f4a267ad..498b9cb61 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1438,7 +1438,6 @@ static inline void P_LoadSideDefs(lumpnum_t lumpnum) static void P_LoadRawSideDefs2(void *data) { UINT16 i; - INT32 num; for (i = 0; i < numsides; i++) { @@ -1473,32 +1472,9 @@ static void P_LoadRawSideDefs2(void *data) case 447: // Change colormap of tagged sectors! -- Monster Iestyn 14/06/18 // SoM: R_CreateColormap will only create a colormap in software mode... // Perhaps we should just call it instead of doing the calculations here. - if (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#' - || (msd->toptexture[0] >= 'a' && msd->toptexture[0] <= 'z' && !msd->toptexture[1]) - || (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'Z' && !msd->toptexture[1]) - || (msd->bottomtexture[0] >= 'a' && msd->bottomtexture[0] <= 'z' && !msd->bottomtexture[1]) - || (msd->bottomtexture[0] >= 'A' && msd->bottomtexture[0] <= 'Z' && !msd->bottomtexture[1]) - ) - { - sec->extra_colormap = sec->spawn_extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture, - msd->bottomtexture); - sd->toptexture = sd->bottomtexture = 0; - } - else - { - if ((num = R_CheckTextureNumForName(msd->toptexture)) == -1) - sd->toptexture = 0; - else - sd->toptexture = num; - if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1) - sd->midtexture = 0; - else - sd->midtexture = num; - if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1) - sd->bottomtexture = 0; - else - sd->bottomtexture = num; - } + sec->extra_colormap = sec->spawn_extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture, + msd->bottomtexture); + sd->toptexture = sd->midtexture = sd->bottomtexture = 0; break; case 413: // Change music diff --git a/src/r_data.c b/src/r_data.c index e08600cae..529507e9a 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1435,26 +1435,41 @@ void R_AddColormapToList(extracolormap_t *extra_colormap) } // -// R_CheckDefaultColormap() +// R_CheckDefaultColormapByValues() // -boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams) +#ifdef EXTRACOLORMAPLUMPS +boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams, + INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump) +#else +boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams, + INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog) +#endif +{ + return ( + (!checkparams ? true : + (fadestart == 0 + && fadeend == 31 + && !fog) + ) + && (!checkrgba ? true : rgba == 0) + && (!checkfadergba ? true : fadergba == 0x19000000) +#ifdef EXTRACOLORMAPLUMPS + && lump == LUMPERROR + && extra_colormap->lumpname[0] == 0 +#endif + ); +} + +boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams) { if (!extra_colormap) return true; - else - return ( - (!checkparams ? true : - (extra_colormap->fadestart == 0 - && extra_colormap->fadeend == 31 - && !extra_colormap->fog) - ) - && (!checkrgba ? true : extra_colormap->rgba == 0) - && (!checkfadergba ? true : extra_colormap->fadergba == 0x19000000) + #ifdef EXTRACOLORMAPLUMPS - && extra_colormap->lump == LUMPERROR - && extra_colormap->lumpname[0] == 0 + return R_CheckDefaultColormapByValues(checkrgba, checkfadergba, checkparams, extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog, extra_colormap->lump); +#else + return R_CheckDefaultColormapByValues(checkrgba, checkfadergba, checkparams, extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog); #endif - ); } // @@ -1557,14 +1572,14 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb; double maskamt = 0, othermask = 0; - UINT8 cr = (extra_colormap->rgba) & 0xFF, - cg = (extra_colormap->rgba >> 8) & 0xFF, - cb = (extra_colormap->rgba >> 16) & 0xFF, - ca = (extra_colormap->rgba >> 24) & 0xFF, - cfr = (extra_colormap->fadergba) & 0xFF, - cfg = (extra_colormap->fadergba >> 8) & 0xFF, - cfb = (extra_colormap->fadergba >> 16) & 0xFF; -// cfa = (extra_colormap->fadergba >> 24) & 0xFF; // unused in software + UINT8 cr = R_GetRgbaR(extra_colormap->rgba), + cg = R_GetRgbaG(extra_colormap->rgba), + cb = R_GetRgbaB(extra_colormap->rgba), + ca = R_GetRgbaA(extra_colormap->rgba), + cfr = R_GetRgbaR(extra_colormap->fadergba), + cfg = R_GetRgbaG(extra_colormap->fadergba), + cfb = R_GetRgbaB(extra_colormap->fadergba); +// cfa = R_GetRgbaA(extra_colormap->fadergba); // unused in software UINT8 fadestart = extra_colormap->fadestart, fadedist = extra_colormap->fadeend - extra_colormap->fadestart; @@ -1807,6 +1822,15 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) rgba = cr + (cg << 8) + (cb << 16) + (ca << 24); fadergba = cfr + (cfg << 8) + (cfb << 16) + (cfa << 24); + // Did we just make a default colormap? +#ifdef EXTRACOLORMAPLUMPS + if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, fog, LUMPERROR)) + return NULL; +#else + if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, fog)) + return NULL; +#endif + // Look for existing colormaps #ifdef EXTRACOLORMAPLUMPS exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog, LUMPERROR); diff --git a/src/r_data.h b/src/r_data.h index 17d85fd8b..ee497d155 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -109,13 +109,19 @@ extracolormap_t *R_CreateDefaultColormap(boolean lighttable); extracolormap_t *R_GetDefaultColormap(void); extracolormap_t *R_CopyColormap(extracolormap_t *extra_colormap, boolean lighttable); void R_AddColormapToList(extracolormap_t *extra_colormap); -boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams); + #ifdef EXTRACOLORMAPLUMPS +boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams, + INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump); extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump); #else +boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams, + INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog); extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog); #endif +boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams); extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap); + lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3); #ifdef EXTRACOLORMAPLUMPS @@ -123,6 +129,11 @@ extracolormap_t *R_ColormapForName(char *name); const char *R_NameForColormap(extracolormap_t *extra_colormap); #endif +#define R_GetRgbaR(rgba) (rgba & 0xFF) +#define R_GetRgbaG(rgba) ((rgba >> 8) & 0xFF) +#define R_GetRgbaB(rgba) ((rgba >> 16) & 0xFF) +#define R_GetRgbaA(rgba) ((rgba >> 24) & 0xFF) + extern INT32 numtextures; #endif From 5523fc3a8d43e69dcc77f55b4d762c3c738c6931 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 17:07:50 -0400 Subject: [PATCH 135/306] Account for NULL colormaps in alpha-only code 447 --- src/p_spec.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 8d17c6de3..adcd46462 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3267,7 +3267,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // base rgba alpha = (line->flags & ML_DONTPEGBOTTOM && line->sidenum[1] != 0xFFFF) ? (sides[line->sidenum[1]].textureoffset >> FRACBITS) - : R_GetRgbaA(line->frontsector->extra_colormap->rgba); + : line->frontsector->extra_colormap ? + R_GetRgbaA(line->frontsector->extra_colormap->rgba) + : 0; if (line->flags & ML_EFFECT3) // relative calc alpha = max(min(R_GetRgbaA(sectors[secnum].extra_colormap->rgba) + alpha, 25), 0); dest_colormap->rgba = (dest_colormap->rgba & 0xFFFFFF) + (alpha << 24); @@ -3275,7 +3277,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // fade rgba alpha = (line->flags & ML_DONTPEGBOTTOM && line->sidenum[1] != 0xFFFF) ? (sides[line->sidenum[1]].rowoffset >> FRACBITS) - : R_GetRgbaA(line->frontsector->extra_colormap->fadergba); + : line->frontsector->extra_colormap ? + R_GetRgbaA(line->frontsector->extra_colormap->fadergba) + : 0; if (line->flags & ML_EFFECT3) // relative calc alpha = max(min(R_GetRgbaA(sectors[secnum].extra_colormap->fadergba) + alpha, 25), 0); dest_colormap->fadergba = (dest_colormap->fadergba & 0xFFFFFF) + (alpha << 24); From 5975f261773418cd6eba4247582798e7d11ce0ec Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 17:06:44 -0400 Subject: [PATCH 136/306] Don't set sector's extra_colormap if we just made a default clone * Allow colormap parsing to proceed in p_setup always * Add R_CheckDefaultColormap * Add R_GetRgbaR/G/B/A macros --- src/p_setup.c | 30 +++-------------------- src/r_data.c | 68 ++++++++++++++++++++++++++++++++++----------------- src/r_data.h | 13 +++++++++- 3 files changed, 61 insertions(+), 50 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 77d53812c..edde5e701 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1438,7 +1438,6 @@ static inline void P_LoadSideDefs(lumpnum_t lumpnum) static void P_LoadRawSideDefs2(void *data) { UINT16 i; - INT32 num; for (i = 0; i < numsides; i++) { @@ -1472,32 +1471,9 @@ static void P_LoadRawSideDefs2(void *data) case 606: //SoM: 4/4/2000: Just colormap transfer // SoM: R_CreateColormap will only create a colormap in software mode... // Perhaps we should just call it instead of doing the calculations here. - if (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#' - || (msd->toptexture[0] >= 'a' && msd->toptexture[0] <= 'z' && !msd->toptexture[1]) - || (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'Z' && !msd->toptexture[1]) - || (msd->bottomtexture[0] >= 'a' && msd->bottomtexture[0] <= 'z' && !msd->bottomtexture[1]) - || (msd->bottomtexture[0] >= 'A' && msd->bottomtexture[0] <= 'Z' && !msd->bottomtexture[1]) - ) - { - sec->extra_colormap = sec->spawn_extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture, - msd->bottomtexture); - sd->toptexture = sd->bottomtexture = 0; - } - else - { - if ((num = R_CheckTextureNumForName(msd->toptexture)) == -1) - sd->toptexture = 0; - else - sd->toptexture = num; - if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1) - sd->midtexture = 0; - else - sd->midtexture = num; - if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1) - sd->bottomtexture = 0; - else - sd->bottomtexture = num; - } + sec->extra_colormap = sec->spawn_extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture, + msd->bottomtexture); + sd->toptexture = sd->midtexture = sd->bottomtexture = 0; break; case 413: // Change music diff --git a/src/r_data.c b/src/r_data.c index e08600cae..529507e9a 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1435,26 +1435,41 @@ void R_AddColormapToList(extracolormap_t *extra_colormap) } // -// R_CheckDefaultColormap() +// R_CheckDefaultColormapByValues() // -boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams) +#ifdef EXTRACOLORMAPLUMPS +boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams, + INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump) +#else +boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams, + INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog) +#endif +{ + return ( + (!checkparams ? true : + (fadestart == 0 + && fadeend == 31 + && !fog) + ) + && (!checkrgba ? true : rgba == 0) + && (!checkfadergba ? true : fadergba == 0x19000000) +#ifdef EXTRACOLORMAPLUMPS + && lump == LUMPERROR + && extra_colormap->lumpname[0] == 0 +#endif + ); +} + +boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams) { if (!extra_colormap) return true; - else - return ( - (!checkparams ? true : - (extra_colormap->fadestart == 0 - && extra_colormap->fadeend == 31 - && !extra_colormap->fog) - ) - && (!checkrgba ? true : extra_colormap->rgba == 0) - && (!checkfadergba ? true : extra_colormap->fadergba == 0x19000000) + #ifdef EXTRACOLORMAPLUMPS - && extra_colormap->lump == LUMPERROR - && extra_colormap->lumpname[0] == 0 + return R_CheckDefaultColormapByValues(checkrgba, checkfadergba, checkparams, extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog, extra_colormap->lump); +#else + return R_CheckDefaultColormapByValues(checkrgba, checkfadergba, checkparams, extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog); #endif - ); } // @@ -1557,14 +1572,14 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb; double maskamt = 0, othermask = 0; - UINT8 cr = (extra_colormap->rgba) & 0xFF, - cg = (extra_colormap->rgba >> 8) & 0xFF, - cb = (extra_colormap->rgba >> 16) & 0xFF, - ca = (extra_colormap->rgba >> 24) & 0xFF, - cfr = (extra_colormap->fadergba) & 0xFF, - cfg = (extra_colormap->fadergba >> 8) & 0xFF, - cfb = (extra_colormap->fadergba >> 16) & 0xFF; -// cfa = (extra_colormap->fadergba >> 24) & 0xFF; // unused in software + UINT8 cr = R_GetRgbaR(extra_colormap->rgba), + cg = R_GetRgbaG(extra_colormap->rgba), + cb = R_GetRgbaB(extra_colormap->rgba), + ca = R_GetRgbaA(extra_colormap->rgba), + cfr = R_GetRgbaR(extra_colormap->fadergba), + cfg = R_GetRgbaG(extra_colormap->fadergba), + cfb = R_GetRgbaB(extra_colormap->fadergba); +// cfa = R_GetRgbaA(extra_colormap->fadergba); // unused in software UINT8 fadestart = extra_colormap->fadestart, fadedist = extra_colormap->fadeend - extra_colormap->fadestart; @@ -1807,6 +1822,15 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) rgba = cr + (cg << 8) + (cb << 16) + (ca << 24); fadergba = cfr + (cfg << 8) + (cfb << 16) + (cfa << 24); + // Did we just make a default colormap? +#ifdef EXTRACOLORMAPLUMPS + if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, fog, LUMPERROR)) + return NULL; +#else + if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, fog)) + return NULL; +#endif + // Look for existing colormaps #ifdef EXTRACOLORMAPLUMPS exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog, LUMPERROR); diff --git a/src/r_data.h b/src/r_data.h index 17d85fd8b..ee497d155 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -109,13 +109,19 @@ extracolormap_t *R_CreateDefaultColormap(boolean lighttable); extracolormap_t *R_GetDefaultColormap(void); extracolormap_t *R_CopyColormap(extracolormap_t *extra_colormap, boolean lighttable); void R_AddColormapToList(extracolormap_t *extra_colormap); -boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams); + #ifdef EXTRACOLORMAPLUMPS +boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams, + INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump); extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump); #else +boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams, + INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog); extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog); #endif +boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams); extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap); + lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3); #ifdef EXTRACOLORMAPLUMPS @@ -123,6 +129,11 @@ extracolormap_t *R_ColormapForName(char *name); const char *R_NameForColormap(extracolormap_t *extra_colormap); #endif +#define R_GetRgbaR(rgba) (rgba & 0xFF) +#define R_GetRgbaG(rgba) ((rgba >> 8) & 0xFF) +#define R_GetRgbaB(rgba) ((rgba >> 16) & 0xFF) +#define R_GetRgbaA(rgba) ((rgba >> 24) & 0xFF) + extern INT32 numtextures; #endif From 548f02eea14ab963fa2e4519740c927bef2ae3f5 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 17:30:43 -0400 Subject: [PATCH 137/306] Extra macros R_GetRgbaRGB; R_PutRgbaR/G/B/A/RGB/RGBA --- src/r_data.c | 4 ++-- src/r_data.h | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 529507e9a..e0899e4cf 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1819,8 +1819,8 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) // Pack rgba values into combined var // OpenGL also uses this instead of lighttables for rendering - rgba = cr + (cg << 8) + (cb << 16) + (ca << 24); - fadergba = cfr + (cfg << 8) + (cfb << 16) + (cfa << 24); + rgba = R_PutRgbaRGBA(cr, cg, cb, ca); + fadergba = R_PutRgbaRGBA(cfr, cfg, cfb, cfa); // Did we just make a default colormap? #ifdef EXTRACOLORMAPLUMPS diff --git a/src/r_data.h b/src/r_data.h index ee497d155..d980e9c56 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -133,6 +133,13 @@ const char *R_NameForColormap(extracolormap_t *extra_colormap); #define R_GetRgbaG(rgba) ((rgba >> 8) & 0xFF) #define R_GetRgbaB(rgba) ((rgba >> 16) & 0xFF) #define R_GetRgbaA(rgba) ((rgba >> 24) & 0xFF) +#define R_GetRgbaRGB(rgba) (rgba & 0xFFFFFF) +#define R_PutRgbaR(r) (r) +#define R_PutRgbaG(g) (g << 8) +#define R_PutRgbaB(b) (b << 16) +#define R_PutRgbaA(a) (a << 24) +#define R_PutRgbaRGB(r, g, b) (R_PutRgbaR(r) + R_PutRgbaG(g) + R_PutRgbaB(b)) +#define R_PutRgbaRGBA(r, g, b, a) (R_PutRgbaRGB(r, g, b) + R_PutRgbaA(a)) extern INT32 numtextures; From b9e4cd40ca45936428467dcf7eaa7eb31679d946 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 17:32:43 -0400 Subject: [PATCH 138/306] Use RGB/RGBA macros in 447 code --- src/p_spec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index adcd46462..f119c3e2f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3272,7 +3272,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) : 0; if (line->flags & ML_EFFECT3) // relative calc alpha = max(min(R_GetRgbaA(sectors[secnum].extra_colormap->rgba) + alpha, 25), 0); - dest_colormap->rgba = (dest_colormap->rgba & 0xFFFFFF) + (alpha << 24); + dest_colormap->rgba = R_GetRgbaRGB(dest_colormap->rgba) + R_PutRgbaA(alpha); // fade rgba alpha = (line->flags & ML_DONTPEGBOTTOM && line->sidenum[1] != 0xFFFF) ? @@ -3282,7 +3282,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) : 0; if (line->flags & ML_EFFECT3) // relative calc alpha = max(min(R_GetRgbaA(sectors[secnum].extra_colormap->fadergba) + alpha, 25), 0); - dest_colormap->fadergba = (dest_colormap->fadergba & 0xFFFFFF) + (alpha << 24); + dest_colormap->fadergba = R_GetRgbaRGB(dest_colormap->fadergba) + R_PutRgbaA(alpha); if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(dest_colormap))) { From a1a05c99721eb65da73ec822f3e32de97dd23112 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 19:11:50 -0400 Subject: [PATCH 139/306] Add relative color change to 447 --- src/p_spec.c | 85 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 24 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index f119c3e2f..4a23902c7 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3257,41 +3257,78 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // -- Monster Iestyn 14/06/18 for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;) { - if (line->flags & ML_NOCLIMB) // set alpha only + if (line->flags & ML_EFFECT3) // relative calc { if (sectors[secnum].extra_colormap) // does nothing without an existing colormap { - extracolormap_t *dest_colormap = R_CopyColormap(sectors[secnum].extra_colormap, false); - INT16 alpha; + extracolormap_t *target_colormap = R_CopyColormap(sectors[secnum].extra_colormap, false); + extracolormap_t *source_colormap = line->frontsector->extra_colormap ? line->frontsector->extra_colormap + : R_GetDefaultColormap(); + + INT16 red, green, blue, alpha; // base rgba - alpha = (line->flags & ML_DONTPEGBOTTOM && line->sidenum[1] != 0xFFFF) ? - (sides[line->sidenum[1]].textureoffset >> FRACBITS) - : line->frontsector->extra_colormap ? - R_GetRgbaA(line->frontsector->extra_colormap->rgba) - : 0; - if (line->flags & ML_EFFECT3) // relative calc - alpha = max(min(R_GetRgbaA(sectors[secnum].extra_colormap->rgba) + alpha, 25), 0); - dest_colormap->rgba = R_GetRgbaRGB(dest_colormap->rgba) + R_PutRgbaA(alpha); + red = max(min( + R_GetRgbaR(target_colormap->rgba) + + ((line->flags & ML_EFFECT1) ? -1 : 1) // subtract R + * R_GetRgbaR(source_colormap->rgba) + , 255), 0); + + green = max(min( + R_GetRgbaG(target_colormap->rgba) + + ((line->flags & ML_NOCLIMB) ? -1 : 1) // subtract G + * R_GetRgbaG(source_colormap->rgba) + , 255), 0); + + blue = max(min( + R_GetRgbaB(target_colormap->rgba) + + ((line->flags & ML_EFFECT2) ? -1 : 1) // subtract B + * R_GetRgbaB(source_colormap->rgba) + , 255), 0); + + alpha = (line->flags & ML_DONTPEGBOTTOM) ? // front (or back!) X offset; needed to subtract A + (sides[line->sidenum[line->sidenum[1] != 0xFFFF ? 1 : 0]].textureoffset >> FRACBITS) + : R_GetRgbaA(source_colormap->rgba); + alpha = max(min(R_GetRgbaA(target_colormap->rgba) + alpha, 25), 0); + + target_colormap->rgba = R_PutRgbaRGBA(red, green, blue, alpha); // fade rgba - alpha = (line->flags & ML_DONTPEGBOTTOM && line->sidenum[1] != 0xFFFF) ? - (sides[line->sidenum[1]].rowoffset >> FRACBITS) - : line->frontsector->extra_colormap ? - R_GetRgbaA(line->frontsector->extra_colormap->fadergba) - : 0; - if (line->flags & ML_EFFECT3) // relative calc - alpha = max(min(R_GetRgbaA(sectors[secnum].extra_colormap->fadergba) + alpha, 25), 0); - dest_colormap->fadergba = R_GetRgbaRGB(dest_colormap->fadergba) + R_PutRgbaA(alpha); + red = max(min( + R_GetRgbaR(target_colormap->fadergba) + + ((line->flags & ML_EFFECT1) ? -1 : 1) // subtract R + * R_GetRgbaR(source_colormap->fadergba) + , 255), 0); - if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(dest_colormap))) + green = max(min( + R_GetRgbaG(target_colormap->fadergba) + + ((line->flags & ML_NOCLIMB) ? -1 : 1) // subtract G + * R_GetRgbaG(source_colormap->fadergba) + , 255), 0); + + blue = max(min( + R_GetRgbaB(target_colormap->fadergba) + + ((line->flags & ML_EFFECT2) ? -1 : 1) // subtract B + * R_GetRgbaB(source_colormap->fadergba) + , 255), 0); + + alpha = (line->flags & ML_DONTPEGBOTTOM) ? // front (or back!) Y offset; needed to subtract A + (sides[line->sidenum[line->sidenum[1] != 0xFFFF ? 1 : 0]].rowoffset >> FRACBITS) + : R_GetRgbaA(source_colormap->fadergba); + if (alpha == 25) + alpha = 0; // HACK: fadergba A defaults at 25, so don't add anything in this case + alpha = max(min(R_GetRgbaA(target_colormap->fadergba) + alpha, 25), 0); + + target_colormap->fadergba = R_PutRgbaRGBA(red, green, blue, alpha); + + if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(target_colormap))) { - dest_colormap->colormap = R_CreateLightTable(dest_colormap); - R_AddColormapToList(dest_colormap); - sectors[secnum].extra_colormap = dest_colormap; + target_colormap->colormap = R_CreateLightTable(target_colormap); + R_AddColormapToList(target_colormap); + sectors[secnum].extra_colormap = target_colormap; } else - memset(dest_colormap, 0, sizeof(*dest_colormap)); + memset(target_colormap, 0, sizeof(*target_colormap)); } } else From 0fb594ad5829274ddff998cb393d2c1af07bd403 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 21:02:58 -0400 Subject: [PATCH 140/306] R_AddColormaps method --- src/r_data.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/r_data.h | 5 +++ 2 files changed, 91 insertions(+) diff --git a/src/r_data.c b/src/r_data.c index 949a842cc..03de15d85 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1876,6 +1876,92 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) return extra_colormap; } +// +// R_AddColormaps() +// NOTE: The result colormap DOES get added to the extra_colormaps chain! +// +extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend, + boolean subR, boolean subG, boolean subB, boolean subA, + boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA, + boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha, + boolean lighttable) +{ + extracolormap_t *exc; + + // exc_augend is added (or subtracted) onto by exc_addend + // In Rennaisance times, the first number was considered the augend, the second number the addend + // But since the commutative property was discovered, today they're both called addends! + // So let's be Olde English for a hot second. + + exc_augend = R_CopyColormap(exc_augend, false); + if(!exc_addend) + exc_addend = R_GetDefaultColormap(); + + INT16 red, green, blue, alpha; + + // base rgba + red = max(min( + R_GetRgbaR(exc_augend->rgba) + + (subR ? -1 : 1) // subtract R + * R_GetRgbaR(exc_addend->rgba) + , 255), 0); + + green = max(min( + R_GetRgbaG(exc_augend->rgba) + + (subG ? -1 : 1) // subtract G + * R_GetRgbaG(exc_addend->rgba) + , 255), 0); + + blue = max(min( + R_GetRgbaB(exc_augend->rgba) + + (subB ? -1 : 1) // subtract B + * R_GetRgbaB(exc_addend->rgba) + , 255), 0); + + alpha = useAltAlpha ? altAlpha : R_GetRgbaA(exc_addend->rgba); + alpha = max(min(R_GetRgbaA(exc_augend->rgba) + (subA ? -1 : 1) * alpha, 25), 0); + + exc_augend->rgba = R_PutRgbaRGBA(red, green, blue, alpha); + + // fade rgba + red = max(min( + R_GetRgbaR(exc_augend->fadergba) + + (subFadeR ? -1 : 1) // subtract R + * R_GetRgbaR(exc_addend->fadergba) + , 255), 0); + + green = max(min( + R_GetRgbaG(exc_augend->fadergba) + + (subFadeG ? -1 : 1) // subtract G + * R_GetRgbaG(exc_addend->fadergba) + , 255), 0); + + blue = max(min( + R_GetRgbaB(exc_augend->fadergba) + + (subFadeB ? -1 : 1) // subtract B + * R_GetRgbaB(exc_addend->fadergba) + , 255), 0); + + alpha = useAltAlpha ? altFadeAlpha : R_GetRgbaA(exc_addend->fadergba); + if (alpha == 25) + alpha = 0; // HACK: fadergba A defaults at 25, so don't add anything in this case + alpha = max(min(R_GetRgbaA(exc_augend->fadergba) + (subFadeA ? -1 : 1) * alpha, 25), 0); + + exc_augend->fadergba = R_PutRgbaRGBA(red, green, blue, alpha); + + if (!(exc = R_GetColormapFromList(exc_augend))) + { + exc_augend->colormap = lighttable ? R_CreateLightTable(exc_augend) : NULL; + R_AddColormapToList(exc_augend); + return exc_augend; + } + else + { + Z_Free(exc_augend); + return exc; + } +} + // Thanks to quake2 source! // utils3/qdata/images.c static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) diff --git a/src/r_data.h b/src/r_data.h index d980e9c56..6f8d08120 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -124,6 +124,11 @@ extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3); +extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend, + boolean subR, boolean subG, boolean subB, boolean subA, + boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA, + boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha, + boolean lighttable); #ifdef EXTRACOLORMAPLUMPS extracolormap_t *R_ColormapForName(char *name); const char *R_NameForColormap(extracolormap_t *extra_colormap); From 54669a6cc83fca0b8793e867113cc16e3bb8ee40 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 21:03:13 -0400 Subject: [PATCH 141/306] Use R_AddColormaps method in 447 relative calc --- src/p_spec.c | 87 +++++++++------------------------------------------- 1 file changed, 14 insertions(+), 73 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 4a23902c7..2c607f74e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3258,79 +3258,20 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;) { if (line->flags & ML_EFFECT3) // relative calc - { - if (sectors[secnum].extra_colormap) // does nothing without an existing colormap - { - extracolormap_t *target_colormap = R_CopyColormap(sectors[secnum].extra_colormap, false); - extracolormap_t *source_colormap = line->frontsector->extra_colormap ? line->frontsector->extra_colormap - : R_GetDefaultColormap(); - - INT16 red, green, blue, alpha; - - // base rgba - red = max(min( - R_GetRgbaR(target_colormap->rgba) - + ((line->flags & ML_EFFECT1) ? -1 : 1) // subtract R - * R_GetRgbaR(source_colormap->rgba) - , 255), 0); - - green = max(min( - R_GetRgbaG(target_colormap->rgba) - + ((line->flags & ML_NOCLIMB) ? -1 : 1) // subtract G - * R_GetRgbaG(source_colormap->rgba) - , 255), 0); - - blue = max(min( - R_GetRgbaB(target_colormap->rgba) - + ((line->flags & ML_EFFECT2) ? -1 : 1) // subtract B - * R_GetRgbaB(source_colormap->rgba) - , 255), 0); - - alpha = (line->flags & ML_DONTPEGBOTTOM) ? // front (or back!) X offset; needed to subtract A - (sides[line->sidenum[line->sidenum[1] != 0xFFFF ? 1 : 0]].textureoffset >> FRACBITS) - : R_GetRgbaA(source_colormap->rgba); - alpha = max(min(R_GetRgbaA(target_colormap->rgba) + alpha, 25), 0); - - target_colormap->rgba = R_PutRgbaRGBA(red, green, blue, alpha); - - // fade rgba - red = max(min( - R_GetRgbaR(target_colormap->fadergba) - + ((line->flags & ML_EFFECT1) ? -1 : 1) // subtract R - * R_GetRgbaR(source_colormap->fadergba) - , 255), 0); - - green = max(min( - R_GetRgbaG(target_colormap->fadergba) - + ((line->flags & ML_NOCLIMB) ? -1 : 1) // subtract G - * R_GetRgbaG(source_colormap->fadergba) - , 255), 0); - - blue = max(min( - R_GetRgbaB(target_colormap->fadergba) - + ((line->flags & ML_EFFECT2) ? -1 : 1) // subtract B - * R_GetRgbaB(source_colormap->fadergba) - , 255), 0); - - alpha = (line->flags & ML_DONTPEGBOTTOM) ? // front (or back!) Y offset; needed to subtract A - (sides[line->sidenum[line->sidenum[1] != 0xFFFF ? 1 : 0]].rowoffset >> FRACBITS) - : R_GetRgbaA(source_colormap->fadergba); - if (alpha == 25) - alpha = 0; // HACK: fadergba A defaults at 25, so don't add anything in this case - alpha = max(min(R_GetRgbaA(target_colormap->fadergba) + alpha, 25), 0); - - target_colormap->fadergba = R_PutRgbaRGBA(red, green, blue, alpha); - - if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(target_colormap))) - { - target_colormap->colormap = R_CreateLightTable(target_colormap); - R_AddColormapToList(target_colormap); - sectors[secnum].extra_colormap = target_colormap; - } - else - memset(target_colormap, 0, sizeof(*target_colormap)); - } - } + sectors[secnum].extra_colormap = R_AddColormaps( + sectors[secnum].extra_colormap, line->frontsector->extra_colormap, + line->flags & ML_EFFECT1, // subtract R + line->flags & ML_NOCLIMB, // subtract G + line->flags & ML_EFFECT2, // subtract B + false, // subtract A (no flag for this, just pass negative alpha) + line->flags & ML_EFFECT1, // subtract FadeR + line->flags & ML_NOCLIMB, // subtract FadeG + line->flags & ML_EFFECT2, // subtract FadeB + false, // subtract FadeA (no flag for this, just pass negative alpha) + line->flags & ML_DONTPEGBOTTOM, + (line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].textureoffset >> FRACBITS) : 0, + (line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].rowoffset >> FRACBITS) : 0, + true); else sectors[secnum].extra_colormap = line->frontsector->extra_colormap; } From f0c11eb13572e041b1f7762d569f9e821c336d10 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 21:02:58 -0400 Subject: [PATCH 142/306] R_AddColormaps method --- src/r_data.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/r_data.h | 5 +++ 2 files changed, 91 insertions(+) diff --git a/src/r_data.c b/src/r_data.c index e0899e4cf..c84e61fce 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1867,6 +1867,92 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) return extra_colormap; } +// +// R_AddColormaps() +// NOTE: The result colormap DOES get added to the extra_colormaps chain! +// +extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend, + boolean subR, boolean subG, boolean subB, boolean subA, + boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA, + boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha, + boolean lighttable) +{ + extracolormap_t *exc; + + // exc_augend is added (or subtracted) onto by exc_addend + // In Rennaisance times, the first number was considered the augend, the second number the addend + // But since the commutative property was discovered, today they're both called addends! + // So let's be Olde English for a hot second. + + exc_augend = R_CopyColormap(exc_augend, false); + if(!exc_addend) + exc_addend = R_GetDefaultColormap(); + + INT16 red, green, blue, alpha; + + // base rgba + red = max(min( + R_GetRgbaR(exc_augend->rgba) + + (subR ? -1 : 1) // subtract R + * R_GetRgbaR(exc_addend->rgba) + , 255), 0); + + green = max(min( + R_GetRgbaG(exc_augend->rgba) + + (subG ? -1 : 1) // subtract G + * R_GetRgbaG(exc_addend->rgba) + , 255), 0); + + blue = max(min( + R_GetRgbaB(exc_augend->rgba) + + (subB ? -1 : 1) // subtract B + * R_GetRgbaB(exc_addend->rgba) + , 255), 0); + + alpha = useAltAlpha ? altAlpha : R_GetRgbaA(exc_addend->rgba); + alpha = max(min(R_GetRgbaA(exc_augend->rgba) + (subA ? -1 : 1) * alpha, 25), 0); + + exc_augend->rgba = R_PutRgbaRGBA(red, green, blue, alpha); + + // fade rgba + red = max(min( + R_GetRgbaR(exc_augend->fadergba) + + (subFadeR ? -1 : 1) // subtract R + * R_GetRgbaR(exc_addend->fadergba) + , 255), 0); + + green = max(min( + R_GetRgbaG(exc_augend->fadergba) + + (subFadeG ? -1 : 1) // subtract G + * R_GetRgbaG(exc_addend->fadergba) + , 255), 0); + + blue = max(min( + R_GetRgbaB(exc_augend->fadergba) + + (subFadeB ? -1 : 1) // subtract B + * R_GetRgbaB(exc_addend->fadergba) + , 255), 0); + + alpha = useAltAlpha ? altFadeAlpha : R_GetRgbaA(exc_addend->fadergba); + if (alpha == 25) + alpha = 0; // HACK: fadergba A defaults at 25, so don't add anything in this case + alpha = max(min(R_GetRgbaA(exc_augend->fadergba) + (subFadeA ? -1 : 1) * alpha, 25), 0); + + exc_augend->fadergba = R_PutRgbaRGBA(red, green, blue, alpha); + + if (!(exc = R_GetColormapFromList(exc_augend))) + { + exc_augend->colormap = lighttable ? R_CreateLightTable(exc_augend) : NULL; + R_AddColormapToList(exc_augend); + return exc_augend; + } + else + { + Z_Free(exc_augend); + return exc; + } +} + // Thanks to quake2 source! // utils3/qdata/images.c static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) diff --git a/src/r_data.h b/src/r_data.h index d980e9c56..6f8d08120 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -124,6 +124,11 @@ extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3); +extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend, + boolean subR, boolean subG, boolean subB, boolean subA, + boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA, + boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha, + boolean lighttable); #ifdef EXTRACOLORMAPLUMPS extracolormap_t *R_ColormapForName(char *name); const char *R_NameForColormap(extracolormap_t *extra_colormap); From ead14becd7184340102fbf5d5fc0d72a8be85053 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 22:34:29 -0400 Subject: [PATCH 143/306] Add R_CheckEqualColormaps comparison method --- src/r_data.c | 27 +++++++++++++++++++++++++++ src/r_data.h | 1 + 2 files changed, 28 insertions(+) diff --git a/src/r_data.c b/src/r_data.c index c84e61fce..1de51fedd 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1472,6 +1472,33 @@ boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgb #endif } +boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, boolean checkrgba, boolean checkfadergba, boolean checkparams) +{ + // Treat NULL as default colormap + // We need this because what if one exc is a default colormap, and the other is NULL? They're really both equal. + if (!exc_a) + exc_a = R_GetDefaultColormap(); + if (!exc_b) + exc_b = R_GetDefaultColormap(); + + if (exc_a == exc_b) + return true; + + return ( + (!checkparams ? true : + (exc_a->fadestart == exc_b->fadestart + && exc_a->fadeend == exc_b->fadeend + && exc_a->fog == exc_b->fog) + ) + && (!checkrgba ? true : exc_a->rgba == exc_b->rgba) + && (!checkfadergba ? true : exc_a->fadergba == exc_b->fadergba) +#ifdef EXTRACOLORMAPLUMPS + && exc_a->lump == exc_b->lump + && !strncmp(exc_a->lumpname, exc_b->lumpname, 9) +#endif + ); +} + // // R_GetColormapFromListByValues() // NOTE: Returns NULL if no match is found diff --git a/src/r_data.h b/src/r_data.h index 6f8d08120..f6db2953d 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -120,6 +120,7 @@ boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog); #endif boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams); +boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b); extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); From 90aeac5058bae5cdc6c7097ce13bc1f4dd688df3 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 22:34:29 -0400 Subject: [PATCH 144/306] Add R_CheckEqualColormaps comparison method --- src/r_data.c | 27 +++++++++++++++++++++++++++ src/r_data.h | 1 + 2 files changed, 28 insertions(+) diff --git a/src/r_data.c b/src/r_data.c index c84e61fce..1de51fedd 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1472,6 +1472,33 @@ boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgb #endif } +boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, boolean checkrgba, boolean checkfadergba, boolean checkparams) +{ + // Treat NULL as default colormap + // We need this because what if one exc is a default colormap, and the other is NULL? They're really both equal. + if (!exc_a) + exc_a = R_GetDefaultColormap(); + if (!exc_b) + exc_b = R_GetDefaultColormap(); + + if (exc_a == exc_b) + return true; + + return ( + (!checkparams ? true : + (exc_a->fadestart == exc_b->fadestart + && exc_a->fadeend == exc_b->fadeend + && exc_a->fog == exc_b->fog) + ) + && (!checkrgba ? true : exc_a->rgba == exc_b->rgba) + && (!checkfadergba ? true : exc_a->fadergba == exc_b->fadergba) +#ifdef EXTRACOLORMAPLUMPS + && exc_a->lump == exc_b->lump + && !strncmp(exc_a->lumpname, exc_b->lumpname, 9) +#endif + ); +} + // // R_GetColormapFromListByValues() // NOTE: Returns NULL if no match is found diff --git a/src/r_data.h b/src/r_data.h index 6f8d08120..df0fe75b3 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -120,6 +120,7 @@ boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog); #endif boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams); +boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, boolean checkrgba, boolean checkfadergba, boolean checkparams); extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); From 92a97fb1a64ec3e2b88203011a5ca11abfeacef8 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 22:44:31 -0400 Subject: [PATCH 145/306] Split colormap netsync to Load/SaveExtraColormap methods --- src/p_saveg.c | 131 +++++++++++++++++++++++++------------------------- 1 file changed, 66 insertions(+), 65 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index b887b8a73..fc767d9cf 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -474,6 +474,70 @@ static void P_NetUnArchivePlayers(void) } } +static void SaveExtraColormap(UINT8 *put, extracolormap_t *exc) +{ + WRITEUINT8(put, exc->fadestart); + WRITEUINT8(put, exc->fadeend); + WRITEUINT8(put, (UINT8)exc->fog); + + WRITEINT32(put, exc->rgba); + WRITEINT32(put, exc->fadergba); + +#ifdef EXTRACOLORMAPLUMPS + WRITESTRINGN(put, exc->lumpname, 9); +#endif +} + +static extracolormap_t *LoadExtraColormap(UINT8 *get) +{ + extracolormap_t *exc; + //size_t dbg_i = 0; + + UINT8 fadestart = READUINT8(get), + fadeend = READUINT8(get); + + boolean fog = (boolean)READUINT8(get); + + INT32 rgba = READINT32(get), + fadergba = READINT32(get); + +#ifdef EXTRACOLORMAPLUMPS + char lumpname[9]; + READSTRINGN(get, lumpname, 9); + + if (lumpname[0]) + return R_ColormapForName(lumpname); +#endif + exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog); + + if (!exc) + { + // CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + // (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF, + // (fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF); + + exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); + + exc->fadestart = fadestart; + exc->fadeend = fadeend; + exc->fog = fog; + + exc->rgba = rgba; + exc->fadergba = fadergba; + + exc->colormap = R_CreateLightTable(exc); + + R_AddColormapToList(exc); + +#ifdef EXTRACOLORMAPLUMPS + exc->lump = LUMPERROR; + exc->lumpname[0] = 0; +#endif + } + + return exc; +} + #define SD_FLOORHT 0x01 #define SD_CEILHT 0x02 #define SD_FLOORPIC 0x04 @@ -657,18 +721,7 @@ static void P_NetArchiveWorld(void) } if (diff3 & SD_COLORMAP) - { - WRITEUINT8(put, ss->extra_colormap->fadestart); - WRITEUINT8(put, ss->extra_colormap->fadeend); - WRITEUINT8(put, (UINT8)ss->extra_colormap->fog); - - WRITEINT32(put, ss->extra_colormap->rgba); - WRITEINT32(put, ss->extra_colormap->fadergba); - -#ifdef EXTRACOLORMAPLUMPS - WRITESTRINGN(put, ss->extra_colormap->lumpname, 9); -#endif - } + SaveExtraColormap(put, ss->extra_colormap); // Special case: save the stats of all modified ffloors along with their ffloor "number"s // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed @@ -865,59 +918,7 @@ static void P_NetUnArchiveWorld(void) } if (diff3 & SD_COLORMAP) - { - extracolormap_t *exc; - //size_t dbg_i = 0; - - UINT8 fadestart = READUINT8(get), - fadeend = READUINT8(get); - - boolean fog = (boolean)READUINT8(get); - - INT32 rgba = READINT32(get), - fadergba = READINT32(get); - -#ifdef EXTRACOLORMAPLUMPS - char lumpname[9]; - READSTRINGN(get, lumpname, 9); - - if (lumpname[0]) - sectors[i].extra_colormap = R_ColormapForName(lumpname); - else - { -#endif - exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog); - - if (!exc) - { - // CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - // (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF, - // (fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF); - - exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); - - exc->fadestart = fadestart; - exc->fadeend = fadeend; - exc->fog = fog; - - exc->rgba = rgba; - exc->fadergba = fadergba; - - exc->colormap = R_CreateLightTable(exc); - - R_AddColormapToList(exc); - -#ifdef EXTRACOLORMAPLUMPS - exc->lump = LUMPERROR; - exc->lumpname[0] = 0; -#endif - } - - sectors[i].extra_colormap = exc; -#ifdef EXTRACOLORMAPLUMPS - } -#endif - } + sectors[i].extra_colormap = LoadExtraColormap(get); if (diff & SD_FFLOORS) { From 5e59b8c55af1e79c1f5bf10ceb52676ed9b2624d Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 11 Sep 2018 22:49:32 -0400 Subject: [PATCH 146/306] Duplicate lines --- src/r_data.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 5598dafcd..1de51fedd 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1849,15 +1849,6 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) rgba = R_PutRgbaRGBA(cr, cg, cb, ca); fadergba = R_PutRgbaRGBA(cfr, cfg, cfb, cfa); - // Did we just make a default colormap? -#ifdef EXTRACOLORMAPLUMPS - if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, fog, LUMPERROR)) - return NULL; -#else - if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, fog)) - return NULL; -#endif - // Did we just make a default colormap? #ifdef EXTRACOLORMAPLUMPS if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, fog, LUMPERROR)) From 8754268abe34f70a3b71be70808c39351aed3f64 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 07:06:45 -0400 Subject: [PATCH 147/306] Add fadestart/fadeend/fog to R_AddColormaps --- src/r_data.c | 32 +++++++++++++++++++++++++++++++- src/r_data.h | 1 + 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/r_data.c b/src/r_data.c index 1de51fedd..53044bc2e 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1901,6 +1901,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend, boolean subR, boolean subG, boolean subB, boolean subA, boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA, + boolean subFadeStart, boolean subFadeEnd, boolean ignoreFog, boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha, boolean lighttable) { @@ -1917,7 +1918,10 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex INT16 red, green, blue, alpha; + /////////////////// // base rgba + /////////////////// + red = max(min( R_GetRgbaR(exc_augend->rgba) + (subR ? -1 : 1) // subtract R @@ -1941,7 +1945,10 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex exc_augend->rgba = R_PutRgbaRGBA(red, green, blue, alpha); - // fade rgba + /////////////////// + // fade/dark rgba + /////////////////// + red = max(min( R_GetRgbaR(exc_augend->fadergba) + (subFadeR ? -1 : 1) // subtract R @@ -1967,6 +1974,29 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex exc_augend->fadergba = R_PutRgbaRGBA(red, green, blue, alpha); + /////////////////// + // parameters + /////////////////// + + exc_augend->fadestart = max(min( + exc_augend->fadestart + + (subFadeStart ? -1 : 1) // subtract fadestart + * exc_addend->fadestart + , 31), 0); + + exc_augend->fadeend = max(min( + exc_augend->fadeend + + (subFadeEnd ? -1 : 1) // subtract fadeend + * exc_addend->fadeend + , 31), 0); + + if (!ignoreFog) // overwrite fog with new value + exc_augend->fog = exc_addend->fog; + + /////////////////// + // put it together + /////////////////// + if (!(exc = R_GetColormapFromList(exc_augend))) { exc_augend->colormap = lighttable ? R_CreateLightTable(exc_augend) : NULL; diff --git a/src/r_data.h b/src/r_data.h index df0fe75b3..3a7740c96 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -128,6 +128,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3); extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend, boolean subR, boolean subG, boolean subB, boolean subA, boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA, + boolean subFadeStart, boolean subFadeEnd, boolean ignoreFog, boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha, boolean lighttable); #ifdef EXTRACOLORMAPLUMPS From 6059b8edc909b1ac5cbbf65c6b821852c69f53cf Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 07:06:58 -0400 Subject: [PATCH 148/306] 447: Extra params for R_AddColormaps --- src/p_spec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_spec.c b/src/p_spec.c index 2c607f74e..41756423a 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3268,6 +3268,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) line->flags & ML_NOCLIMB, // subtract FadeG line->flags & ML_EFFECT2, // subtract FadeB false, // subtract FadeA (no flag for this, just pass negative alpha) + false, // subtract FadeStart (we ran out of flags) + false, // subtract FadeEnd (we ran out of flags) + false, // ignore Fog (we ran out of flags) line->flags & ML_DONTPEGBOTTOM, (line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].textureoffset >> FRACBITS) : 0, (line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].rowoffset >> FRACBITS) : 0, From 133c3598a79828bbf140f844e306517a9aa79725 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 07:06:45 -0400 Subject: [PATCH 149/306] Add fadestart/fadeend/fog to R_AddColormaps --- src/r_data.c | 32 +++++++++++++++++++++++++++++++- src/r_data.h | 1 + 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/r_data.c b/src/r_data.c index 1de51fedd..53044bc2e 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1901,6 +1901,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend, boolean subR, boolean subG, boolean subB, boolean subA, boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA, + boolean subFadeStart, boolean subFadeEnd, boolean ignoreFog, boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha, boolean lighttable) { @@ -1917,7 +1918,10 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex INT16 red, green, blue, alpha; + /////////////////// // base rgba + /////////////////// + red = max(min( R_GetRgbaR(exc_augend->rgba) + (subR ? -1 : 1) // subtract R @@ -1941,7 +1945,10 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex exc_augend->rgba = R_PutRgbaRGBA(red, green, blue, alpha); - // fade rgba + /////////////////// + // fade/dark rgba + /////////////////// + red = max(min( R_GetRgbaR(exc_augend->fadergba) + (subFadeR ? -1 : 1) // subtract R @@ -1967,6 +1974,29 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex exc_augend->fadergba = R_PutRgbaRGBA(red, green, blue, alpha); + /////////////////// + // parameters + /////////////////// + + exc_augend->fadestart = max(min( + exc_augend->fadestart + + (subFadeStart ? -1 : 1) // subtract fadestart + * exc_addend->fadestart + , 31), 0); + + exc_augend->fadeend = max(min( + exc_augend->fadeend + + (subFadeEnd ? -1 : 1) // subtract fadeend + * exc_addend->fadeend + , 31), 0); + + if (!ignoreFog) // overwrite fog with new value + exc_augend->fog = exc_addend->fog; + + /////////////////// + // put it together + /////////////////// + if (!(exc = R_GetColormapFromList(exc_augend))) { exc_augend->colormap = lighttable ? R_CreateLightTable(exc_augend) : NULL; diff --git a/src/r_data.h b/src/r_data.h index df0fe75b3..3a7740c96 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -128,6 +128,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3); extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend, boolean subR, boolean subG, boolean subB, boolean subA, boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA, + boolean subFadeStart, boolean subFadeEnd, boolean ignoreFog, boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha, boolean lighttable); #ifdef EXTRACOLORMAPLUMPS From 87ad2a87f79cb9fbfabee5a8dc8550c1f3305f2e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 07:14:23 -0400 Subject: [PATCH 150/306] Smarter default fadergbaA and fadeend for relative calc --- src/r_data.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 53044bc2e..5a642f1b2 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1968,7 +1968,7 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex , 255), 0); alpha = useAltAlpha ? altFadeAlpha : R_GetRgbaA(exc_addend->fadergba); - if (alpha == 25) + if (alpha == 25 && !useAltAlpha && !R_GetRgbaRGB(exc_addend->fadergba)) alpha = 0; // HACK: fadergba A defaults at 25, so don't add anything in this case alpha = max(min(R_GetRgbaA(exc_augend->fadergba) + (subFadeA ? -1 : 1) * alpha, 25), 0); @@ -1987,7 +1987,8 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex exc_augend->fadeend = max(min( exc_augend->fadeend + (subFadeEnd ? -1 : 1) // subtract fadeend - * exc_addend->fadeend + * (exc_addend->fadeend == 31 && !exc_addend->fadestart ? 0 : exc_addend->fadeend) + // HACK: fadeend defaults to 31, so don't add anything in this case , 31), 0); if (!ignoreFog) // overwrite fog with new value From 55c43a2161201ae4382565f3fd4616c0faddbca1 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 07:24:22 -0400 Subject: [PATCH 151/306] R_AddColormap will not return an existing colormap, and new colormap is not added to chain --- src/r_data.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 5a642f1b2..c8a648a0f 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1896,7 +1896,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) // // R_AddColormaps() -// NOTE: The result colormap DOES get added to the extra_colormaps chain! +// NOTE: The result colormap is not added to the extra_colormaps chain. You must do that yourself! // extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend, boolean subR, boolean subG, boolean subB, boolean subA, @@ -1998,17 +1998,9 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex // put it together /////////////////// - if (!(exc = R_GetColormapFromList(exc_augend))) - { - exc_augend->colormap = lighttable ? R_CreateLightTable(exc_augend) : NULL; - R_AddColormapToList(exc_augend); - return exc_augend; - } - else - { - Z_Free(exc_augend); - return exc; - } + exc_augend->colormap = lighttable ? R_CreateLightTable(exc_augend) : NULL; + exc_augend->next = exc_augend->prev = NULL; + return exc_augend; } // Thanks to quake2 source! From 9a388af8ec6a38e6f3e90b3dee0b6b153612278b Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 07:31:10 -0400 Subject: [PATCH 152/306] 447: AddColormap no longer returns chained colormap, so chain it ourselves --- src/p_spec.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 41756423a..2742f1b44 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3258,7 +3258,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;) { if (line->flags & ML_EFFECT3) // relative calc - sectors[secnum].extra_colormap = R_AddColormaps( + { + extracolormap_t *exc = R_AddColormaps( sectors[secnum].extra_colormap, line->frontsector->extra_colormap, line->flags & ML_EFFECT1, // subtract R line->flags & ML_NOCLIMB, // subtract G @@ -3274,7 +3275,17 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) line->flags & ML_DONTPEGBOTTOM, (line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].textureoffset >> FRACBITS) : 0, (line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].rowoffset >> FRACBITS) : 0, - true); + false); + + if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(exc))) + { + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + sectors[secnum].extra_colormap = exc; + } + else + Z_Free(exc); + } else sectors[secnum].extra_colormap = line->frontsector->extra_colormap; } From 6f0b28c48f0256c6194dee11d7714a31f51eff59 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 07:38:51 -0400 Subject: [PATCH 153/306] 447: Allow alternate alpha without relative calc --- src/p_spec.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 2742f1b44..637f90af8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3287,7 +3287,25 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) Z_Free(exc); } else - sectors[secnum].extra_colormap = line->frontsector->extra_colormap; + { + if (line->flags & ML_DONTPEGBOTTOM) // alternate alpha (by texture offsets) + { + extracolormap_t *exc = R_CopyColormap(line->frontsector->extra_colormap, false); + exc->rgba = R_GetRgbaRGB(exc->rgba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].textureoffset >> FRACBITS, 25), 0)); + exc->fadergba = R_GetRgbaRGB(exc->fadergba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].rowoffset >> FRACBITS, 25), 0)); + + if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(exc))) + { + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + sectors[secnum].extra_colormap = exc; + } + else + Z_Free(exc); + } + else + sectors[secnum].extra_colormap = line->frontsector->extra_colormap; + } } break; From 4d26cf63304005ac745909ace8b85bbde6fa1425 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 07:55:47 -0400 Subject: [PATCH 154/306] 447: Allow relative calc from backside colormap (ML_TFERLINE) --- src/p_spec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 637f90af8..914c9821e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3260,7 +3260,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (line->flags & ML_EFFECT3) // relative calc { extracolormap_t *exc = R_AddColormaps( - sectors[secnum].extra_colormap, line->frontsector->extra_colormap, + (line->flags & ML_TFERLINE) ? line->backsector->extra_colormap : sectors[secnum].extra_colormap, // use back colormap instead of target sector + line->frontsector->extra_colormap, line->flags & ML_EFFECT1, // subtract R line->flags & ML_NOCLIMB, // subtract G line->flags & ML_EFFECT2, // subtract B From cb2ac9b4d3943ab9c569afcb52a9d4a76a75edc1 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 08:06:44 -0400 Subject: [PATCH 155/306] Formatting --- src/p_spec.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 914c9821e..fd02803cc 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3287,26 +3287,23 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) else Z_Free(exc); } - else + else if (line->flags & ML_DONTPEGBOTTOM) // alternate alpha (by texture offsets) { - if (line->flags & ML_DONTPEGBOTTOM) // alternate alpha (by texture offsets) - { - extracolormap_t *exc = R_CopyColormap(line->frontsector->extra_colormap, false); - exc->rgba = R_GetRgbaRGB(exc->rgba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].textureoffset >> FRACBITS, 25), 0)); - exc->fadergba = R_GetRgbaRGB(exc->fadergba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].rowoffset >> FRACBITS, 25), 0)); + extracolormap_t *exc = R_CopyColormap(line->frontsector->extra_colormap, false); + exc->rgba = R_GetRgbaRGB(exc->rgba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].textureoffset >> FRACBITS, 25), 0)); + exc->fadergba = R_GetRgbaRGB(exc->fadergba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].rowoffset >> FRACBITS, 25), 0)); - if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(exc))) - { - exc->colormap = R_CreateLightTable(exc); - R_AddColormapToList(exc); - sectors[secnum].extra_colormap = exc; - } - else - Z_Free(exc); + if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(exc))) + { + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + sectors[secnum].extra_colormap = exc; } else - sectors[secnum].extra_colormap = line->frontsector->extra_colormap; + Z_Free(exc); } + else + sectors[secnum].extra_colormap = line->frontsector->extra_colormap; } break; From 9a6a8b0b8255a34c6b85d31887cc2390a640c500 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 08:07:34 -0400 Subject: [PATCH 156/306] Outdated comment; unused var --- src/p_setup.c | 3 --- src/r_data.c | 2 -- 2 files changed, 5 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index edde5e701..c08c2ac58 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1459,9 +1459,6 @@ static void P_LoadRawSideDefs2(void *data) sd->sector = sec = §ors[sector_num]; } - // refined to allow colormaps to work as wall textures if invalid as colormaps - // but valid as textures. - sd->sector = sec = §ors[SHORT(msd->sector)]; // Colormaps! diff --git a/src/r_data.c b/src/r_data.c index c8a648a0f..c2e28fe9f 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1905,8 +1905,6 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha, boolean lighttable) { - extracolormap_t *exc; - // exc_augend is added (or subtracted) onto by exc_addend // In Rennaisance times, the first number was considered the augend, the second number the addend // But since the commutative property was discovered, today they're both called addends! From 14b71bdbc574c9255fb7a2eca5cfca3ba24ad36b Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 09:06:38 -0400 Subject: [PATCH 157/306] Fade colormap special 455! And stop fade colormap 456 * Added T_FadeColormap thinker and netsync * Added sector_t fadecolormapdata property --- src/p_saveg.c | 47 ++++++++++++- src/p_setup.c | 1 + src/p_spec.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/p_spec.h | 14 ++++ src/r_defs.h | 1 + 5 files changed, 251 insertions(+), 1 deletion(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index fc767d9cf..b3953c53c 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1099,6 +1099,7 @@ typedef enum tc_noenemies, tc_eachtime, tc_disappear, + tc_fadecolormap, tc_planedisplace, #ifdef POLYOBJECTS tc_polyrotate, // haleyjd 03/26/06: polyobjects @@ -1663,6 +1664,22 @@ static void SaveDisappearThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->exists); } +// +// SaveFadeColormapThinker +// +// Saves a fadecolormap_t thinker +// +static void SaveFadeColormapThinker(const thinker_t *th, const UINT8 type) +{ + const fadecolormap_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, SaveSector(ht->sector)); + SaveExtraColormap(save_p, ht->source_exc); + SaveExtraColormap(save_p, ht->dest_exc); + WRITEINT32(save_p, ht->duration); + WRITEINT32(save_p, ht->timer); +} + // // SavePlaneDisplaceThinker // @@ -1965,6 +1982,11 @@ static void P_NetArchiveThinkers(void) SaveDisappearThinker(th, tc_disappear); continue; } + else if (th->function.acp1 == (actionf_p1)T_FadeColormap) + { + SaveFadeColormapThinker(th, tc_fadecolormap); + continue; + } else if (th->function.acp1 == (actionf_p1)T_PlaneDisplace) { @@ -2641,6 +2663,25 @@ static inline void LoadDisappearThinker(actionf_p1 thinker) P_AddThinker(&ht->thinker); } +// +// LoadFadeColormapThinker +// +// Loads a fadecolormap_t from a save game +// +static inline void LoadFadeColormapThinker(actionf_p1 thinker) +{ + fadecolormap_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->sector = LoadSector(READUINT32(save_p)); + ht->source_exc = LoadExtraColormap(save_p); + ht->dest_exc = LoadExtraColormap(save_p); + ht->duration = READINT32(save_p); + ht->timer = READINT32(save_p); + if (ht->sector) + ht->sector->fadecolormapdata = ht; + P_AddThinker(&ht->thinker); +} + // // LoadPlaneDisplaceThinker // @@ -2827,7 +2868,7 @@ static void P_NetUnArchiveThinkers(void) // clear sector thinker pointers so they don't point to non-existant thinkers for all of eternity for (i = 0; i < numsectors; i++) { - sectors[i].floordata = sectors[i].ceilingdata = sectors[i].lightingdata = NULL; + sectors[i].floordata = sectors[i].ceilingdata = sectors[i].lightingdata = sectors[i].fadecolormapdata = NULL; } // read in saved thinkers @@ -2944,6 +2985,10 @@ static void P_NetUnArchiveThinkers(void) LoadDisappearThinker((actionf_p1)T_Disappear); break; + case tc_fadecolormap: + LoadFadeColormapThinker((actionf_p1)T_FadeColormap); + break; + case tc_planedisplace: LoadPlaneDisplaceThinker((actionf_p1)T_PlaneDisplace); break; diff --git a/src/p_setup.c b/src/p_setup.c index c08c2ac58..b26459759 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1466,6 +1466,7 @@ static void P_LoadRawSideDefs2(void *data) { case 63: // variable colormap via 242 linedef case 606: //SoM: 4/4/2000: Just colormap transfer + case 455: // Fade colormaps! mazmazz 9/12/2018 (:flag_us:) // SoM: R_CreateColormap will only create a colormap in software mode... // Perhaps we should just call it instead of doing the calculations here. sec->extra_colormap = sec->spawn_extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture, diff --git a/src/p_spec.c b/src/p_spec.c index 5135676ab..e20d85af6 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -103,6 +103,9 @@ static void P_SpawnFriction(void); static void P_SpawnPushers(void); static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000 static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); +static void P_ResetColormapFader(sector_t *sector); +static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, extracolormap_t *dest_exc, + INT32 duration); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); @@ -3310,6 +3313,82 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; } + case 455: // Fade colormap + for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;) + { + extracolormap_t *source_exc, *dest_exc, *exc; + + exc = (line->flags & ML_TFERLINE) ? line->backsector->extra_colormap // TFERLINE: use back colormap instead of target sector + : sectors[secnum].extra_colormap; + + if (!(line->flags & ML_BOUNCY) // BOUNCY: Do not override fade from default rgba + && !R_CheckDefaultColormap(line->frontsector->extra_colormap, true, false, false) + && R_CheckDefaultColormap(exc, true, false, false)) + { + exc = R_CopyColormap(exc, false); + exc->rgba = R_GetRgbaRGB(line->frontsector->extra_colormap->rgba) + R_PutRgbaA(R_GetRgbaA(exc->rgba)); + exc->fadergba = R_GetRgbaRGB(line->frontsector->extra_colormap->rgba) + R_PutRgbaA(R_GetRgbaA(exc->fadergba)); + + if (!(source_exc = R_GetColormapFromList(exc))) + { + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + source_exc = exc; + } + else + Z_Free(exc); + } + else + source_exc = exc; + + if (line->flags & ML_EFFECT3) // relative calc + { + exc = R_AddColormaps( + source_exc, + line->frontsector->extra_colormap, + line->flags & ML_EFFECT1, // subtract R + line->flags & ML_NOCLIMB, // subtract G + line->flags & ML_EFFECT2, // subtract B + false, // subtract A (no flag for this, just pass negative alpha) + line->flags & ML_EFFECT1, // subtract FadeR + line->flags & ML_NOCLIMB, // subtract FadeG + line->flags & ML_EFFECT2, // subtract FadeB + false, // subtract FadeA (no flag for this, just pass negative alpha) + false, // subtract FadeStart (we ran out of flags) + false, // subtract FadeEnd (we ran out of flags) + false, // ignore Fog (we ran out of flags) + line->flags & ML_DONTPEGBOTTOM, + (line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].textureoffset >> FRACBITS) : 0, + (line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].rowoffset >> FRACBITS) : 0, + false); + } + else if (line->flags & ML_DONTPEGBOTTOM) // alternate alpha (by texture offsets) + { + exc = R_CopyColormap(line->frontsector->extra_colormap, false); + exc->rgba = R_GetRgbaRGB(exc->rgba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].textureoffset >> FRACBITS, 25), 0)); + exc->fadergba = R_GetRgbaRGB(exc->fadergba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].rowoffset >> FRACBITS, 25), 0)); + } + else + exc = R_CopyColormap(line->frontsector->extra_colormap, false); + + if (!(dest_exc = R_GetColormapFromList(exc))) + { + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + dest_exc = exc; + } + else + Z_Free(exc); + + Add_ColormapFader(§ors[secnum], source_exc, dest_exc, + (line->sidenum[1] != 0xFFFF ? abs(sides[line->sidenum[1]].rowoffset >> FRACBITS) : abs(P_AproxDistance(line->dx, line->dy) >> FRACBITS))); + } + break; + + case 456: // Stop fade colormap + for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;) + P_ResetColormapFader(§ors[secnum]); + #ifdef POLYOBJECTS case 480: // Polyobj_DoorSlide case 481: // Polyobj_DoorSwing @@ -7322,6 +7401,116 @@ void T_Disappear(disappear_t *d) } } +static void P_ResetColormapFader(sector_t *sector) +{ + if (sector->fadecolormapdata) + { + // The thinker is the first member in all the action structs, + // so just let the thinker get freed, and that will free the whole + // structure. + P_RemoveThinker(&((elevator_t *)sector->fadecolormapdata)->thinker); + sector->fadecolormapdata = NULL; + } +} + +static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, extracolormap_t *dest_exc, + INT32 duration) +{ + P_ResetColormapFader(sector); + + // nothing to do, set immediately + if (!duration || R_CheckEqualColormaps(source_exc, dest_exc, true, true, true)) + { + sector->extra_colormap = dest_exc; + return; + } + + fadecolormap_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); + d->thinker.function.acp1 = (actionf_p1)T_FadeColormap; + d->sector = sector; + d->source_exc = source_exc; + d->dest_exc = dest_exc; + d->duration = d->timer = duration; + + sector->fadecolormapdata = d; + P_AddThinker(&d->thinker); // add thinker +} + +void T_FadeColormap(fadecolormap_t *d) +{ + if (--d->timer <= 0) + { + d->sector->extra_colormap = d->dest_exc; + P_ResetColormapFader(d->sector); + } + else + { + extracolormap_t *exc; + fixed_t factor = min(FixedDiv(d->duration - d->timer, d->duration), 1*FRACUNIT); + INT16 cr, cg, cb, ca, fadestart, fadeend, fog; + INT32 rgba, fadergba; + + // For each var (rgba + fadergba + params = 11 vars), we apply + // percentage fading: currentval = sourceval + (delta * percent of duration elapsed) + // delta is negative when fading out (destval is lower) + // max/min are used to ensure progressive calcs don't go backwards and to cap values to dest. + +#define APPLYFADE(dest, src, cur) (\ +(dest-src < 0) ? \ + max(\ + min(cur,\ + src + (UINT8)FixedMul(dest-src, factor)),\ + dest)\ +: (dest-src > 0) ? \ + min(\ + max(cur,\ + src + (UINT8)FixedMul(dest-src, factor)),\ + dest)\ +: \ + dest\ +) + + cr = APPLYFADE(R_GetRgbaR(d->dest_exc->rgba), R_GetRgbaR(d->source_exc->rgba), R_GetRgbaR(d->sector->extra_colormap->rgba)); + cg = APPLYFADE(R_GetRgbaG(d->dest_exc->rgba), R_GetRgbaG(d->source_exc->rgba), R_GetRgbaG(d->sector->extra_colormap->rgba)); + cb = APPLYFADE(R_GetRgbaB(d->dest_exc->rgba), R_GetRgbaB(d->source_exc->rgba), R_GetRgbaB(d->sector->extra_colormap->rgba)); + ca = APPLYFADE(R_GetRgbaA(d->dest_exc->rgba), R_GetRgbaA(d->source_exc->rgba), R_GetRgbaA(d->sector->extra_colormap->rgba)); + + rgba = R_PutRgbaRGBA(cr, cg, cb, ca); + + cr = APPLYFADE(R_GetRgbaR(d->dest_exc->fadergba), R_GetRgbaR(d->source_exc->fadergba), R_GetRgbaR(d->sector->extra_colormap->fadergba)); + cg = APPLYFADE(R_GetRgbaG(d->dest_exc->fadergba), R_GetRgbaG(d->source_exc->fadergba), R_GetRgbaG(d->sector->extra_colormap->fadergba)); + cb = APPLYFADE(R_GetRgbaB(d->dest_exc->fadergba), R_GetRgbaB(d->source_exc->fadergba), R_GetRgbaB(d->sector->extra_colormap->fadergba)); + ca = APPLYFADE(R_GetRgbaA(d->dest_exc->fadergba), R_GetRgbaA(d->source_exc->fadergba), R_GetRgbaA(d->sector->extra_colormap->fadergba)); + + fadergba = R_PutRgbaRGBA(cr, cg, cb, ca); + + fadestart = APPLYFADE(d->dest_exc->fadestart, d->source_exc->fadestart, d->sector->extra_colormap->fadestart); + fadeend = APPLYFADE(d->dest_exc->fadeend, d->source_exc->fadeend, d->sector->extra_colormap->fadeend); + // fog: essentially we're switching from source_exc->fog to dest_exc->fog with a delta + // of 1 or -1, and hoping the factor rounds appropriately in the timing. + fog = APPLYFADE(d->dest_exc->fog, d->source_exc->fog, d->sector->extra_colormap->fog); + +#undef APPLYFADE + + ////////////////// + // setup new colormap + ////////////////// + + if (!(d->sector->extra_colormap = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog))) + { + exc = R_CreateDefaultColormap(false); + exc->fadestart = fadestart; + exc->fadeend = fadeend; + exc->fog = (boolean)fog; + exc->rgba = rgba; + exc->fadergba = fadergba; + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + d->sector->extra_colormap = exc; + } + } +} + /* SoM: 3/8/2000: Friction functions start. Add_Friction, diff --git a/src/p_spec.h b/src/p_spec.h index e0bcc18eb..9e0b7d5c4 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -453,6 +453,20 @@ typedef struct void T_Disappear(disappear_t *d); +// Model for fading colormaps + +typedef struct +{ + thinker_t thinker; ///< Thinker structure for effect. + sector_t *sector; ///< Sector where action is taking place. + extracolormap_t *source_exc; + extracolormap_t *dest_exc; + INT32 duration; ///< Total duration for tic-based logic + INT32 timer; ///< Timer for tic-based logic +} fadecolormap_t; + +void T_FadeColormap(fadecolormap_t *d); + // Prototype functions for pushers void T_Pusher(pusher_t *p); mobj_t *P_GetPushThing(UINT32 s); diff --git a/src/r_defs.h b/src/r_defs.h index 99fad2b44..8c610cd4d 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -315,6 +315,7 @@ typedef struct sector_s void *floordata; // floor move thinker void *ceilingdata; // ceiling move thinker void *lightingdata; // lighting change thinker + void *fadecolormapdata; // fade colormap thinker // floor and ceiling texture offsets fixed_t floor_xoffs, floor_yoffs; From 4d9925e8cf2459d8a4e8e81fddd3761dff914aab Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 09:09:10 -0400 Subject: [PATCH 158/306] 447: ResetColormapFader when changing colormap explicitly --- src/p_spec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_spec.c b/src/p_spec.c index 7d6ffaf2a..b38fa37c4 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3260,6 +3260,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // -- Monster Iestyn 14/06/18 for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;) { + P_ResetColormapFader(§ors[secnum]); + if (line->flags & ML_EFFECT3) // relative calc { extracolormap_t *exc = R_AddColormaps( From 8190433b71fdf258280bb99724d5287259674c45 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 09:42:51 -0400 Subject: [PATCH 159/306] 456: Missing break --- src/p_spec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_spec.c b/src/p_spec.c index b38fa37c4..e8f1c3cb8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3447,6 +3447,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 456: // Stop fade colormap for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;) P_ResetColormapFader(§ors[secnum]); + break; #ifdef POLYOBJECTS case 480: // Polyobj_DoorSlide From e95cd0f962f2567bc060ff981a6f01d1fe81f6fd Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 11:01:12 -0400 Subject: [PATCH 160/306] Colormap savegame failsafe - Handle NULL (default colormap) --- src/p_saveg.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index b3953c53c..c18837e17 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -476,6 +476,9 @@ static void P_NetUnArchivePlayers(void) static void SaveExtraColormap(UINT8 *put, extracolormap_t *exc) { + if (!exc) // Just give it default values, we done goofed. (or sector->extra_colormap was intentionally set to default (NULL)) + exc = R_GetDefaultColormap(); + WRITEUINT8(put, exc->fadestart); WRITEUINT8(put, exc->fadeend); WRITEUINT8(put, (UINT8)exc->fog); @@ -490,7 +493,7 @@ static void SaveExtraColormap(UINT8 *put, extracolormap_t *exc) static extracolormap_t *LoadExtraColormap(UINT8 *get) { - extracolormap_t *exc; + extracolormap_t *exc, *exc_exist; //size_t dbg_i = 0; UINT8 fadestart = READUINT8(get), @@ -525,14 +528,21 @@ static extracolormap_t *LoadExtraColormap(UINT8 *get) exc->rgba = rgba; exc->fadergba = fadergba; - exc->colormap = R_CreateLightTable(exc); - - R_AddColormapToList(exc); - #ifdef EXTRACOLORMAPLUMPS exc->lump = LUMPERROR; exc->lumpname[0] = 0; #endif + + if (!(exc_exist = R_GetColormapFromList(exc))) + { + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + } + else + { + Z_Free(exc); + exc = R_CheckDefaultColormap(exc_exist, true, true, true) ? NULL : exc_exist; + } } return exc; From d85019b4e4db8b9e2806b5a859a12b8ed325a6e7 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 11:11:22 -0400 Subject: [PATCH 161/306] More NULL failsafes --- src/p_spec.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index e8f1c3cb8..7ae3c7871 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3396,9 +3396,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } else Z_Free(exc); + + sectors[secnum].extra_colormap = source_exc; } else - source_exc = exc; + source_exc = exc ? exc : R_GetDefaultColormap(); if (line->flags & ML_EFFECT3) // relative calc { @@ -7510,6 +7512,16 @@ void T_FadeColormap(fadecolormap_t *d) INT16 cr, cg, cb, ca, fadestart, fadeend, fog; INT32 rgba, fadergba; + // NULL failsafes (or intentionally set to signify default) + if (!d->sector->extra_colormap) + d->sector->extra_colormap = R_GetDefaultColormap(); + + if (!d->source_exc) + d->source_exc = R_GetDefaultColormap(); + + if (!d->dest_exc) + d->dest_exc = R_GetDefaultColormap(); + // For each var (rgba + fadergba + params = 11 vars), we apply // percentage fading: currentval = sourceval + (delta * percent of duration elapsed) // delta is negative when fading out (destval is lower) From 92c5cb82334a3066fd38c6881b236478611eca36 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 11:01:12 -0400 Subject: [PATCH 162/306] Colormap savegame failsafe - Handle NULL (default colormap) --- src/p_saveg.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index fc767d9cf..4084d8c13 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -476,6 +476,9 @@ static void P_NetUnArchivePlayers(void) static void SaveExtraColormap(UINT8 *put, extracolormap_t *exc) { + if (!exc) // Just give it default values, we done goofed. (or sector->extra_colormap was intentionally set to default (NULL)) + exc = R_GetDefaultColormap(); + WRITEUINT8(put, exc->fadestart); WRITEUINT8(put, exc->fadeend); WRITEUINT8(put, (UINT8)exc->fog); @@ -490,7 +493,7 @@ static void SaveExtraColormap(UINT8 *put, extracolormap_t *exc) static extracolormap_t *LoadExtraColormap(UINT8 *get) { - extracolormap_t *exc; + extracolormap_t *exc, *exc_exist; //size_t dbg_i = 0; UINT8 fadestart = READUINT8(get), @@ -525,14 +528,21 @@ static extracolormap_t *LoadExtraColormap(UINT8 *get) exc->rgba = rgba; exc->fadergba = fadergba; - exc->colormap = R_CreateLightTable(exc); - - R_AddColormapToList(exc); - #ifdef EXTRACOLORMAPLUMPS exc->lump = LUMPERROR; exc->lumpname[0] = 0; #endif + + if (!(exc_exist = R_GetColormapFromList(exc))) + { + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + } + else + { + Z_Free(exc); + exc = R_CheckDefaultColormap(exc_exist, true, true, true) ? NULL : exc_exist; + } } return exc; From 51a298222649e6e5f7b4564c20c45b57663b0e8e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 11:21:49 -0400 Subject: [PATCH 163/306] 455: TFERLINE - Set target sector's colormap first to control backsector's colormap --- src/p_spec.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 7ae3c7871..9e4d38f97 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3377,8 +3377,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { extracolormap_t *source_exc, *dest_exc, *exc; - exc = (line->flags & ML_TFERLINE) ? line->backsector->extra_colormap // TFERLINE: use back colormap instead of target sector - : sectors[secnum].extra_colormap; + if (line->flags & ML_TFERLINE) // use back colormap instead of target sector + sectors[secnum].extra_colormap = line->backsector->extra_colormap; + + exc = sectors[secnum].extra_colormap; if (!(line->flags & ML_BOUNCY) // BOUNCY: Do not override fade from default rgba && !R_CheckDefaultColormap(line->frontsector->extra_colormap, true, false, false) From d2f636d5a2fcc678bbd0018dad00ca235a6f2fb6 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 11:33:44 -0400 Subject: [PATCH 164/306] T_FadeColormap: Fade subtraction error --- src/p_spec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 9e4d38f97..3e428c1f6 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7533,12 +7533,12 @@ void T_FadeColormap(fadecolormap_t *d) (dest-src < 0) ? \ max(\ min(cur,\ - src + (UINT8)FixedMul(dest-src, factor)),\ + src + (INT16)FixedMul(dest-src, factor)),\ dest)\ : (dest-src > 0) ? \ min(\ max(cur,\ - src + (UINT8)FixedMul(dest-src, factor)),\ + src + (INT16)FixedMul(dest-src, factor)),\ dest)\ : \ dest\ From 42f1f0acdb3b3c7ed4152cac3ff66b5910a3d13e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 12:40:56 -0400 Subject: [PATCH 165/306] P_ResetFakeFloorFader: Argument order error with dolighting --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index cd63191c9..56c10a4a1 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7524,8 +7524,8 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz &fadingdata->timer, fadingdata->doexists, fadingdata->dotranslucent, - fadingdata->docollision, fadingdata->dolighting, + fadingdata->docollision, fadingdata->doghostfade, fadingdata->exactalpha); rover->alpha = fadingdata->alpha; From 7d36aae7c404b29f71dafacce4f09355e9a30de0 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 16:06:56 -0400 Subject: [PATCH 166/306] Make lightlists react to control sector colormap changes (double pointer) --- src/r_bsp.c | 14 +++++++------- src/r_defs.h | 2 +- src/r_segs.c | 6 +++--- src/r_things.c | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/r_bsp.c b/src/r_bsp.c index 01676572e..cbb012b28 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -925,11 +925,11 @@ static void R_Subsector(size_t num) light = R_GetPlaneLight(frontsector, floorcenterz, false); if (frontsector->floorlightsec == -1) floorlightlevel = *frontsector->lightlist[light].lightlevel; - floorcolormap = frontsector->lightlist[light].extra_colormap; + floorcolormap = *frontsector->lightlist[light].extra_colormap; light = R_GetPlaneLight(frontsector, ceilingcenterz, false); if (frontsector->ceilinglightsec == -1) ceilinglightlevel = *frontsector->lightlist[light].lightlevel; - ceilingcolormap = frontsector->lightlist[light].extra_colormap; + ceilingcolormap = *frontsector->lightlist[light].extra_colormap; } sub->sector->extra_colormap = frontsector->extra_colormap; @@ -1026,7 +1026,7 @@ static void R_Subsector(size_t num) ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic, *frontsector->lightlist[light].lightlevel, *rover->bottomxoffs, - *rover->bottomyoffs, *rover->bottomangle, frontsector->lightlist[light].extra_colormap, rover + *rover->bottomyoffs, *rover->bottomangle, *frontsector->lightlist[light].extra_colormap, rover #ifdef POLYOBJECTS_PLANES , NULL #endif @@ -1072,7 +1072,7 @@ static void R_Subsector(size_t num) ffloor[numffloors].plane = R_FindPlane(*rover->topheight, *rover->toppic, *frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *rover->topangle, - frontsector->lightlist[light].extra_colormap, rover + *frontsector->lightlist[light].extra_colormap, rover #ifdef POLYOBJECTS_PLANES , NULL #endif @@ -1264,7 +1264,7 @@ void R_Prep3DFloors(sector_t *sector) #endif sector->lightlist[0].lightlevel = §or->lightlevel; sector->lightlist[0].caster = NULL; - sector->lightlist[0].extra_colormap = sector->extra_colormap; + sector->lightlist[0].extra_colormap = §or->extra_colormap; sector->lightlist[0].flags = 0; maxheight = INT32_MAX; @@ -1339,12 +1339,12 @@ void R_Prep3DFloors(sector_t *sector) else if (best->flags & FF_COLORMAPONLY) { sector->lightlist[i].lightlevel = sector->lightlist[i-1].lightlevel; - sector->lightlist[i].extra_colormap = sec->extra_colormap; + sector->lightlist[i].extra_colormap = &sec->extra_colormap; } else { sector->lightlist[i].lightlevel = best->toplightlevel; - sector->lightlist[i].extra_colormap = sec->extra_colormap; + sector->lightlist[i].extra_colormap = &sec->extra_colormap; } if (best->flags & FF_DOUBLESHADOW) diff --git a/src/r_defs.h b/src/r_defs.h index 99fad2b44..63ca29aa1 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -194,7 +194,7 @@ typedef struct lightlist_s { fixed_t height; INT16 *lightlevel; - extracolormap_t *extra_colormap; + extracolormap_t **extra_colormap; // pointer-to-a-pointer, so we can react to colormap changes INT32 flags; ffloor_t *caster; #ifdef ESLOPE diff --git a/src/r_segs.c b/src/r_segs.c index a52b7cb61..cde019f66 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -413,7 +413,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) #endif rlight->startheight = rlight->height; // keep starting value here to reset for each repeat rlight->lightlevel = *light->lightlevel; - rlight->extra_colormap = light->extra_colormap; + rlight->extra_colormap = *light->extra_colormap; rlight->flags = light->flags; if (rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog)) @@ -944,7 +944,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) } rlight->lightlevel = *light->lightlevel; - rlight->extra_colormap = light->extra_colormap; + rlight->extra_colormap = *light->extra_colormap; // Check if the current light effects the colormap/lightlevel if (pfloor->flags & FF_FOG) @@ -2808,7 +2808,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) } rlight->lightlevel = *light->lightlevel; - rlight->extra_colormap = light->extra_colormap; + rlight->extra_colormap = *light->extra_colormap; p++; } diff --git a/src/r_things.c b/src/r_things.c index fb4664d90..f4a0fd28c 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -981,7 +981,7 @@ static void R_SplitSprite(vissprite_t *sprite) else spritelights = scalelight[lightnum]; - newsprite->extra_colormap = sector->lightlist[i].extra_colormap; + newsprite->extra_colormap = *sector->lightlist[i].extra_colormap; if (!((newsprite->cut & SC_FULLBRIGHT) && (!newsprite->extra_colormap || !(newsprite->extra_colormap->fog & 1)))) @@ -1360,7 +1360,7 @@ static void R_ProjectSprite(mobj_t *thing) vis->sz = (INT16)((centeryfrac - FixedMul(vis->gz - viewz, sortscale))>>FRACBITS); vis->cut = cut; if (thing->subsector->sector->numlights) - vis->extra_colormap = thing->subsector->sector->lightlist[light].extra_colormap; + vis->extra_colormap = *thing->subsector->sector->lightlist[light].extra_colormap; else vis->extra_colormap = thing->subsector->sector->extra_colormap; From 62b6950e3324e550a63234ef9c7aed5ef798b5e2 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 16:28:55 -0400 Subject: [PATCH 167/306] Use lightlist.extra_colormap double pointers in OpenGL --- src/hardware/hw_main.c | 30 +++++++++++++++--------------- src/hardware/hw_md2.c | 4 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 119be6b46..50399dbd6 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1126,7 +1126,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, else { lightnum = *list[i].lightlevel; - colormap = list[i].extra_colormap; + colormap = *list[i].extra_colormap; } } @@ -3486,12 +3486,12 @@ static void HWR_Subsector(size_t num) light = R_GetPlaneLight(gr_frontsector, locFloorHeight, false); if (gr_frontsector->floorlightsec == -1) floorlightlevel = *gr_frontsector->lightlist[light].lightlevel; - floorcolormap = gr_frontsector->lightlist[light].extra_colormap; + floorcolormap = *gr_frontsector->lightlist[light].extra_colormap; light = R_GetPlaneLight(gr_frontsector, locCeilingHeight, false); if (gr_frontsector->ceilinglightsec == -1) ceilinglightlevel = *gr_frontsector->lightlist[light].lightlevel; - ceilingcolormap = gr_frontsector->lightlist[light].extra_colormap; + ceilingcolormap = *gr_frontsector->lightlist[light].extra_colormap; } sub->sector->extra_colormap = gr_frontsector->extra_colormap; @@ -3617,7 +3617,7 @@ static void HWR_Subsector(size_t num) *rover->bottomheight, *gr_frontsector->lightlist[light].lightlevel, rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, PF_Translucent, - false, gr_frontsector->lightlist[light].extra_colormap); + false, *gr_frontsector->lightlist[light].extra_colormap); #endif } else @@ -3625,7 +3625,7 @@ static void HWR_Subsector(size_t num) HWR_GetFlat(levelflats[*rover->bottompic].lumpnum); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, - rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap); + rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap); } } @@ -3680,7 +3680,7 @@ static void HWR_Subsector(size_t num) *rover->topheight, *gr_frontsector->lightlist[light].lightlevel, rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, PF_Translucent, - false, gr_frontsector->lightlist[light].extra_colormap); + false, *gr_frontsector->lightlist[light].extra_colormap); #endif } @@ -3689,7 +3689,7 @@ static void HWR_Subsector(size_t num) HWR_GetFlat(levelflats[*rover->toppic].lumpnum); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, - rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap); + rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap); } } } @@ -4200,8 +4200,8 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t if (!(spr->mobj->frame & FF_FULLBRIGHT)) lightlevel = *sector->lightlist[light].lightlevel; - if (sector->lightlist[light].extra_colormap) - colormap = sector->lightlist[light].extra_colormap; + if (*sector->lightlist[light].extra_colormap) + colormap = *sector->lightlist[light].extra_colormap; } else { @@ -4362,7 +4362,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) // Start with the lightlevel and colormap from the top of the sprite lightlevel = *list[sector->numlights - 1].lightlevel; - colormap = list[sector->numlights - 1].extra_colormap; + colormap = *list[sector->numlights - 1].extra_colormap; i = 0; temp = FLOAT_TO_FIXED(realtop); @@ -4378,7 +4378,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) { if (!(spr->mobj->frame & FF_FULLBRIGHT)) lightlevel = *list[i-1].lightlevel; - colormap = list[i-1].extra_colormap; + colormap = *list[i-1].extra_colormap; break; } } @@ -4386,7 +4386,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) i = R_GetPlaneLight(sector, temp, false); if (!(spr->mobj->frame & FF_FULLBRIGHT)) lightlevel = *list[i].lightlevel; - colormap = list[i].extra_colormap; + colormap = *list[i].extra_colormap; #endif for (i = 0; i < sector->numlights; i++) @@ -4402,7 +4402,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) { if (!(spr->mobj->frame & FF_FULLBRIGHT)) lightlevel = *list[i].lightlevel; - colormap = list[i].extra_colormap; + colormap = *list[i].extra_colormap; } #ifdef ESLOPE @@ -4734,8 +4734,8 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) if (!(spr->mobj->frame & FF_FULLBRIGHT)) lightlevel = *sector->lightlist[light].lightlevel; - if (sector->lightlist[light].extra_colormap) - colormap = sector->lightlist[light].extra_colormap; + if (*sector->lightlist[light].extra_colormap) + colormap = *sector->lightlist[light].extra_colormap; } else { diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index bfb2638ee..d69233a9b 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1194,8 +1194,8 @@ void HWR_DrawMD2(gr_vissprite_t *spr) if (!(spr->mobj->frame & FF_FULLBRIGHT)) lightlevel = *sector->lightlist[light].lightlevel; - if (sector->lightlist[light].extra_colormap) - colormap = sector->lightlist[light].extra_colormap; + if (*sector->lightlist[light].extra_colormap) + colormap = *sector->lightlist[light].extra_colormap; } else { From 9fb9b4438319b06f5ea8ecfc6977294b30f005d9 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 16:57:35 -0400 Subject: [PATCH 168/306] Fade FOF colormap support --- src/p_saveg.c | 4 +++ src/p_spec.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++---- src/p_spec.h | 2 ++ 3 files changed, 78 insertions(+), 5 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 5550c7a8b..0f81da5ac 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1587,6 +1587,7 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type) { const fade_t *ht = (const void *)th; WRITEUINT8(save_p, type); + SaveExtraColormap(save_p, ht->dest_exc); WRITEUINT32(save_p, ht->sectornum); WRITEUINT32(save_p, ht->ffloornum); WRITEINT32(save_p, ht->alpha); @@ -1599,6 +1600,7 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type) WRITEUINT8(save_p, ht->doexists); WRITEUINT8(save_p, ht->dotranslucent); WRITEUINT8(save_p, ht->dolighting); + WRITEUINT8(save_p, ht->docolormap); WRITEUINT8(save_p, ht->docollision); WRITEUINT8(save_p, ht->doghostfade); WRITEUINT8(save_p, ht->exactalpha); @@ -2599,6 +2601,7 @@ static inline void LoadFadeThinker(actionf_p1 thinker) { fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; + ht->dest_exc = LoadExtraColormap(save_p); ht->sectornum = READUINT32(save_p); ht->ffloornum = READUINT32(save_p); ht->alpha = READINT32(save_p); @@ -2611,6 +2614,7 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->doexists = READUINT8(save_p); ht->dotranslucent = READUINT8(save_p); ht->dolighting = READUINT8(save_p); + ht->docolormap = READUINT8(save_p); ht->docollision = READUINT8(save_p); ht->doghostfade = READUINT8(save_p); ht->exactalpha = READUINT8(save_p); diff --git a/src/p_spec.c b/src/p_spec.c index 56c10a4a1..c37ee954c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -106,10 +106,15 @@ static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t o static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize); #define P_RemoveFakeFloorFader(l) P_ResetFakeFloorFader(l, NULL, false); static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destvalue, INT16 speed, boolean ticbased, INT32 *timer, - boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha); + boolean doexists, boolean dotranslucent, boolean dolighting, boolean docolormap, + boolean docollision, boolean doghostfade, boolean exactalpha); static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, INT16 destvalue, INT16 speed, boolean ticbased, boolean relative, - boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha); + boolean doexists, boolean dotranslucent, boolean dolighting, boolean docolormap, + boolean docollision, boolean doghostfade, boolean exactalpha); +static void P_ResetColormapFader(sector_t *sector); +static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, extracolormap_t *dest_exc, + INT32 duration); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); @@ -3370,6 +3375,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) false, // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // handle FF_TRANSLUCENT false, // do not handle lighting + false, // do not handle colormap false, // do not handle collision false, // do not do ghost fade (no collision during fade) true); // use exact alpha values (for opengl) @@ -3421,6 +3427,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT !(line->flags & ML_EFFECT2), // do not handle lighting + !(line->flags & ML_EFFECT2), // do not handle colormap (ran out of flags) !(line->flags & ML_BOUNCY), // do not handle collision (line->flags & ML_EFFECT1), // do ghost fade (no collision during fade) (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) @@ -3445,6 +3452,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT !(line->flags & ML_EFFECT2), // do not handle lighting + !(line->flags & ML_EFFECT2), // do not handle colormap (ran out of flags) !(line->flags & ML_BOUNCY), // do not handle collision (line->flags & ML_EFFECT1), // do ghost fade (no collision during fade) (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) @@ -7525,6 +7533,7 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz fadingdata->doexists, fadingdata->dotranslucent, fadingdata->dolighting, + fadingdata->docolormap, fadingdata->docollision, fadingdata->doghostfade, fadingdata->exactalpha); @@ -7533,6 +7542,9 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz if (fadingdata->dolighting) P_RemoveLighting(§ors[rover->secnum]); + if (fadingdata->docolormap) + P_ResetColormapFader(§ors[rover->secnum]); + P_RemoveThinker(&fadingdata->thinker); } @@ -7541,7 +7553,8 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz } static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destvalue, INT16 speed, boolean ticbased, INT32 *timer, - boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha) + boolean doexists, boolean dotranslucent, boolean dolighting, boolean docolormap, + boolean docollision, boolean doghostfade, boolean exactalpha) { boolean stillfading = false; INT32 alpha; @@ -7801,7 +7814,8 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destval */ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, INT16 destvalue, INT16 speed, boolean ticbased, boolean relative, - boolean doexists, boolean dotranslucent, boolean dolighting, boolean docollision, boolean doghostfade, boolean exactalpha) + boolean doexists, boolean dotranslucent, boolean dolighting, boolean docolormap, + boolean docollision, boolean doghostfade, boolean exactalpha) { // If fading an invisible FOF whose render flags we did not yet set, // initialize its alpha to 1 @@ -7841,6 +7855,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor d->doexists = doexists; d->dotranslucent = dotranslucent; d->dolighting = dolighting; + d->docolormap = docolormap; d->docollision = docollision; d->doghostfade = doghostfade; d->exactalpha = exactalpha; @@ -7869,6 +7884,54 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor else d->destlightlevel = -1; + // Set a separate thinker for colormap fading + if (docolormap && !(rover->flags & FF_NOSHADE) && sectors[rover->secnum].spawn_extra_colormap) + { + extracolormap_t *dest_exc, + *source_exc = sectors[rover->secnum].extra_colormap ? sectors[rover->secnum].extra_colormap : R_GetDefaultColormap(); + + INT32 colordelta = R_GetRgbaA(sectors[rover->secnum].spawn_extra_colormap->rgba); // alpha is from 0 + fixed_t alphapercent = min(FixedDiv(d->destvalue, rover->spawnalpha), 1*FRACUNIT); // don't make darker than spawn_lightlevel + fixed_t adjustedcolordelta = FixedMul(colordelta, alphapercent); + INT32 coloralpha; + + coloralpha = adjustedcolordelta; + + dest_exc = R_CopyColormap(sectors[rover->secnum].spawn_extra_colormap, false); + dest_exc->rgba = R_GetRgbaRGB(dest_exc->rgba) + R_PutRgbaA(coloralpha); + + if (!(d->dest_exc = R_GetColormapFromList(dest_exc))) + { + dest_exc->colormap = R_CreateLightTable(dest_exc); + R_AddColormapToList(dest_exc); + d->dest_exc = dest_exc; + } + else + Z_Free(dest_exc); + + // If fading from 0, set source_exc rgb same to dest_exc + if (!R_CheckDefaultColormap(d->dest_exc, true, false, false) + && R_CheckDefaultColormap(source_exc, true, false, false)) + { + extracolormap_t *exc = R_CopyColormap(source_exc, false); + exc->rgba = R_GetRgbaRGB(d->dest_exc->rgba) + R_PutRgbaA(R_GetRgbaA(source_exc->rgba)); + exc->fadergba = R_GetRgbaRGB(d->dest_exc->rgba) + R_PutRgbaA(R_GetRgbaA(source_exc->fadergba)); + + if (!(source_exc = R_GetColormapFromList(exc))) + { + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + source_exc = exc; + } + else + Z_Free(exc); + } + + Add_ColormapFader(§ors[rover->secnum], source_exc, d->dest_exc, + ticbased ? d->timer : + FixedFloor(FixedDiv(abs(d->destvalue - d->alpha), d->speed))/FRACUNIT); + } + P_AddThinker(&d->thinker); } @@ -7880,12 +7943,16 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor void T_Fade(fade_t *d) { if (d->rover && !P_FadeFakeFloor(d->rover, d->sourcevalue, d->destvalue, d->speed, d->ticbased, &d->timer, - d->doexists, d->dotranslucent, d->dolighting, d->docollision, d->doghostfade, d->exactalpha)) + d->doexists, d->dotranslucent, d->dolighting, d->docolormap, d->docollision, d->doghostfade, d->exactalpha)) { // Finalize lighting, copypasta from P_AddFakeFloorFader if (d->dolighting && !(d->rover->flags & FF_NOSHADE) && d->destlightlevel > -1) sectors[d->rover->secnum].lightlevel = d->destlightlevel; + // Finalize colormap + if (d->docolormap && !(d->rover->flags & FF_NOSHADE) && sectors[d->rover->secnum].spawn_extra_colormap) + sectors[d->rover->secnum].extra_colormap = d->dest_exc; + P_RemoveFakeFloorFader(d->rover); } } diff --git a/src/p_spec.h b/src/p_spec.h index 1970aeb6b..189823435 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -466,6 +466,7 @@ typedef struct { thinker_t thinker; ///< Thinker structure for effect. ffloor_t *rover; ///< Target ffloor + extracolormap_t *dest_exc; ///< Colormap to fade to UINT32 sectornum; ///< Number of ffloor target sector UINT32 ffloornum; ///< Number of ffloor of target sector INT32 alpha; ///< Internal alpha counter @@ -478,6 +479,7 @@ typedef struct boolean doexists; ///< Handle FF_EXISTS boolean dotranslucent; ///< Handle FF_TRANSLUCENT boolean dolighting; ///< Handle shadows and light blocks + boolean docolormap; ///< Handle colormaps boolean docollision; ///< Handle interactive flags boolean doghostfade; ///< No interactive flags during fading boolean exactalpha; ///< Use exact alpha values (opengl) From ad9ef5d59316246b647d456c170da6d98293914a Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 17:39:30 -0400 Subject: [PATCH 169/306] Merge errors --- src/p_saveg.c | 2 -- src/p_spec.c | 2 +- src/r_defs.h | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index f2e8dcdb7..c9b474b1d 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -730,8 +730,6 @@ static void P_NetArchiveWorld(void) WRITEINT32(put, ss->firsttag); WRITEINT32(put, ss->nexttag); } - if (diff3 & SD_MIDMAP) - WRITEINT32(put, ss->midmap); if (diff3 & SD_COLORMAP) SaveExtraColormap(put, ss->extra_colormap); diff --git a/src/p_spec.c b/src/p_spec.c index b5e862749..21380584b 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3256,7 +3256,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // This could even override existing colormaps I believe // -- Monster Iestyn 14/06/18 for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;) - sectors[secnum].midmap = line->frontsector->midmap; + sectors[secnum].extra_colormap = line->frontsector->extra_colormap; break; case 448: // Change skybox viewpoint/centerpoint diff --git a/src/r_defs.h b/src/r_defs.h index 1d1d471e5..63ca29aa1 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -390,7 +390,6 @@ typedef struct sector_s // these are saved for netgames, so do not let Lua touch these! INT32 spawn_nexttag, spawn_firsttag; // the actual nexttag/firsttag values may differ if the sector's tag was changed - INT32 spawn_bottommap, spawn_midmap, spawn_topmap; // offsets sector spawned with (via linedef type 7) fixed_t spawn_flr_xoffs, spawn_flr_yoffs; From f7ff440250ddaf9ee1a03a254cfad0834d6514e3 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 20:43:48 -0400 Subject: [PATCH 170/306] Add colormap_data to side_t and store colormaps there on setup --- src/p_setup.c | 2 +- src/p_spec.c | 4 ++-- src/r_defs.h | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 5d7fd3179..cc5ee3cc8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1469,7 +1469,7 @@ static void P_LoadRawSideDefs2(void *data) case 447: // Change colormap of tagged sectors! -- Monster Iestyn 14/06/18 // SoM: R_CreateColormap will only create a colormap in software mode... // Perhaps we should just call it instead of doing the calculations here. - sec->extra_colormap = sec->spawn_extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture, + sd->colormap_data = R_CreateColormap(msd->toptexture, msd->midtexture, msd->bottomtexture); sd->toptexture = sd->midtexture = sd->bottomtexture = 0; break; diff --git a/src/p_spec.c b/src/p_spec.c index 21380584b..8e5a612c3 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3256,7 +3256,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // This could even override existing colormaps I believe // -- Monster Iestyn 14/06/18 for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;) - sectors[secnum].extra_colormap = line->frontsector->extra_colormap; + sectors[secnum].extra_colormap = sides[line->sidenum[0]].colormap_data; break; case 448: // Change skybox viewpoint/centerpoint @@ -6769,7 +6769,7 @@ void P_SpawnSpecials(INT32 fromnetsave) case 606: // HACK! Copy colormaps. Just plain colormaps. for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - sectors[s].extra_colormap = sectors[s].spawn_extra_colormap = lines[i].frontsector->extra_colormap; + sectors[s].extra_colormap = sectors[s].spawn_extra_colormap = sides[lines[i].sidenum[0]].colormap_data; break; #ifdef ESLOPE // Slope copy specials. Handled here for sanity. diff --git a/src/r_defs.h b/src/r_defs.h index 63ca29aa1..1f2afdb99 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -476,6 +476,8 @@ typedef struct INT16 repeatcnt; // # of times to repeat midtexture char *text; // a concatination of all top, bottom, and mid texture names, for linedef specials that require a string. + + extracolormap_t *colormap_data; // storage for colormaps; not applied to sectors. } side_t; // From 05c91f1f81aea11738269d84e5cf5816b56bfe46 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 20:52:05 -0400 Subject: [PATCH 171/306] 455: Change to side->colormap_data --- src/p_spec.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 8797200c2..491671c40 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3379,17 +3379,18 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) extracolormap_t *source_exc, *dest_exc, *exc; if (line->flags & ML_TFERLINE) // use back colormap instead of target sector - sectors[secnum].extra_colormap = line->backsector->extra_colormap; + sectors[secnum].extra_colormap = (line->sidenum[1] != 0xFFFF) ? + sides[line->sidenum[1]].colormap_data : NULL; exc = sectors[secnum].extra_colormap; if (!(line->flags & ML_BOUNCY) // BOUNCY: Do not override fade from default rgba - && !R_CheckDefaultColormap(line->frontsector->extra_colormap, true, false, false) + && !R_CheckDefaultColormap(sides[line->sidenum[0]].colormap_data, true, false, false) && R_CheckDefaultColormap(exc, true, false, false)) { exc = R_CopyColormap(exc, false); - exc->rgba = R_GetRgbaRGB(line->frontsector->extra_colormap->rgba) + R_PutRgbaA(R_GetRgbaA(exc->rgba)); - exc->fadergba = R_GetRgbaRGB(line->frontsector->extra_colormap->rgba) + R_PutRgbaA(R_GetRgbaA(exc->fadergba)); + exc->rgba = R_GetRgbaRGB(sides[line->sidenum[0]].colormap_data->rgba) + R_PutRgbaA(R_GetRgbaA(exc->rgba)); + exc->fadergba = R_GetRgbaRGB(sides[line->sidenum[0]].colormap_data->rgba) + R_PutRgbaA(R_GetRgbaA(exc->fadergba)); if (!(source_exc = R_GetColormapFromList(exc))) { @@ -3409,7 +3410,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { exc = R_AddColormaps( source_exc, - line->frontsector->extra_colormap, + sides[line->sidenum[0]].colormap_data, line->flags & ML_EFFECT1, // subtract R line->flags & ML_NOCLIMB, // subtract G line->flags & ML_EFFECT2, // subtract B @@ -3428,12 +3429,12 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } else if (line->flags & ML_DONTPEGBOTTOM) // alternate alpha (by texture offsets) { - exc = R_CopyColormap(line->frontsector->extra_colormap, false); + exc = R_CopyColormap(sides[line->sidenum[0]].colormap_data, false); exc->rgba = R_GetRgbaRGB(exc->rgba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].textureoffset >> FRACBITS, 25), 0)); exc->fadergba = R_GetRgbaRGB(exc->fadergba) + R_PutRgbaA(max(min(sides[line->sidenum[0]].rowoffset >> FRACBITS, 25), 0)); } else - exc = R_CopyColormap(line->frontsector->extra_colormap, false); + exc = R_CopyColormap(sides[line->sidenum[0]].colormap_data, false); if (!(dest_exc = R_GetColormapFromList(exc))) { From 0b2caa948fb89ab5a7d25d2164c01b01091237fa Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 21:05:50 -0400 Subject: [PATCH 172/306] Init side->colormap_data pointer to NULL (for paranoia) --- src/p_setup.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_setup.c b/src/p_setup.c index cc5ee3cc8..f0ce69598 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1461,6 +1461,8 @@ static void P_LoadRawSideDefs2(void *data) sd->sector = sec = §ors[SHORT(msd->sector)]; + sd->colormap_data = NULL; + // Colormaps! switch (sd->special) { From 41fe080a68b36df41d0a6161e570e59ad0bb037a Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 21:32:12 -0400 Subject: [PATCH 173/306] 420: Allow Back Y Offset for timing parameter --- src/p_spec.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index aa3a81f23..eed083cd9 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2779,8 +2779,14 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 420: // Fade light levels in tagged sectors to new value P_FadeLight(line->tag, - (line->flags & ML_DONTPEGBOTTOM) ? max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 255), 0) : line->frontsector->lightlevel, - (line->flags & ML_DONTPEGBOTTOM) ? max(sides[line->sidenum[0]].rowoffset>>FRACBITS, 0) : P_AproxDistance(line->dx, line->dy)>>FRACBITS, + (line->flags & ML_DONTPEGBOTTOM) ? max(sides[line->sidenum[0]].textureoffset>>FRACBITS, 0) : line->frontsector->lightlevel, + // failsafe: if user specifies Back Y Offset and NOT Front Y Offset, use the Back Offset + // to be consistent with other light and fade specials + (line->flags & ML_DONTPEGBOTTOM) ? + ((line->sidenum[1] != 0xFFFF && !(sides[line->sidenum[0]].rowoffset>>FRACBITS)) ? + max(min(sides[line->sidenum[1]].rowoffset>>FRACBITS, 255), 0) + : max(min(sides[line->sidenum[0]].rowoffset>>FRACBITS, 255), 0)) + : abs(P_AproxDistance(line->dx, line->dy))>>FRACBITS), (line->flags & ML_EFFECT4)); break; From 63a3125df2a5f12fcecc28d7d4ccbcd4b6252b2b Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 21:47:53 -0400 Subject: [PATCH 174/306] 420: A parenthesis --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 85790041f..5ccdca671 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2786,7 +2786,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) ((line->sidenum[1] != 0xFFFF && !(sides[line->sidenum[0]].rowoffset>>FRACBITS)) ? max(min(sides[line->sidenum[1]].rowoffset>>FRACBITS, 255), 0) : max(min(sides[line->sidenum[0]].rowoffset>>FRACBITS, 255), 0)) - : abs(P_AproxDistance(line->dx, line->dy))>>FRACBITS), + : abs(P_AproxDistance(line->dx, line->dy))>>FRACBITS, (line->flags & ML_EFFECT4)); break; From 2f9e014aab5b41f078914114bd32524ce60f1a8b Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 21:58:20 -0400 Subject: [PATCH 175/306] 490 PolyVisible: Set proper spawn render flags instead of RENDERALL --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index a20a339ed..65f7fcd67 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1218,7 +1218,7 @@ static void PolyVisible(line_t *line) po->flags |= POF_SOLID; po->flags &= ~POF_NOSPECIALS; - po->flags |= POF_RENDERALL; + po->flags |= (po->spawnflags & POF_RENDERALL); } // From 0697a1b90a6fa7763a9472d21e7e1e5e872f0f0e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 12 Sep 2018 22:08:07 -0400 Subject: [PATCH 176/306] PolyObjFade: Apply RENDER, SOLID, and NOSPECIALS flags according to spawnflags --- src/p_polyobj.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index a8616dba1..b47afed27 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -2898,7 +2898,7 @@ void T_PolyObjFade(polyfade_t *th) if (po->translucency >= NUMTRANSMAPS) // invisible po->flags &= ~POF_RENDERALL; else - po->flags |= POF_RENDERALL; + po->flags |= (po->spawnflags & POF_RENDERALL); // set collision if (th->docollision && th->speed) @@ -2910,14 +2910,15 @@ void T_PolyObjFade(polyfade_t *th) } else { - po->flags |= POF_SOLID; - po->flags &= ~POF_NOSPECIALS; + po->flags |= (po->spawnflags & POF_SOLID); + if (!(po->spawnflags & POF_NOSPECIALS)) + po->flags &= ~POF_NOSPECIALS; } } } else { - po->flags |= POF_RENDERALL; + po->flags |= (po->spawnflags & POF_RENDERALL); // set collision if (th->docollision && th->speed) @@ -2929,8 +2930,9 @@ void T_PolyObjFade(polyfade_t *th) } else { - po->flags |= POF_SOLID; - po->flags &= ~POF_NOSPECIALS; + po->flags |= (po->spawnflags & POF_SOLID); + if (!(po->spawnflags & POF_NOSPECIALS)) + po->flags &= ~POF_NOSPECIALS; } } } From 4ab3a986f319ec7632e4d0d0fde3f2e325f1704c Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 13 Sep 2018 00:04:50 -0400 Subject: [PATCH 177/306] 492 PolyObj Fade, 491 PolyObj Translucency, 490 PolyObj changes * 490: Set proper render flags according to spawnflags * 491: Add relative calc (EFFECT3) and Front X alpha param (DONTPEGTOP) * 492: * Tic-based (EFFECT4) and speed timing * Add relative calc (EFFECT3) and Front X alpha param (DONTPEGTOP) * Set proper render flags according to spawnflags * Fix OpenGL >= NUMTRANSMAPS render bug --- src/p_polyobj.c | 85 +++++++++++++++++++++++++++++++++++++------------ src/p_polyobj.h | 6 ++-- src/p_saveg.c | 6 ++-- src/p_spec.c | 57 +++++++++++++++++++++++++-------- 4 files changed, 116 insertions(+), 38 deletions(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index b47afed27..f7545e5bd 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -2873,23 +2873,54 @@ void T_PolyObjFade(polyfade_t *th) if (po->thinker == NULL) po->thinker = &th->thinker; - stillfading = !(--(th->timer) <= 0); - - if (th->timer <= 0) + if (th->ticbased) { - po->translucency = th->destvalue; // set to dest translucency + stillfading = !(--(th->timer) <= 0); - // remove thinker - if (po->thinker == &th->thinker) - po->thinker = NULL; - P_RemoveThinker(&th->thinker); - } - else if (!(th->timer % th->interval)) - { - if (th->speed <= 0) - po->translucency = max(po->translucency + th->speed, th->destvalue); + if (th->timer <= 0) + { + po->translucency = max(min(th->destvalue, NUMTRANSMAPS), 0); + + // remove thinker + if (po->thinker == &th->thinker) + po->thinker = NULL; + P_RemoveThinker(&th->thinker); + } else - po->translucency = min(po->translucency + th->speed, th->destvalue); + { + INT16 delta = abs(th->destvalue - th->sourcevalue); + fixed_t factor = min(FixedDiv(th->speed - th->timer, th->speed), 1*FRACUNIT); + if (th->destvalue < th->sourcevalue) + po->translucency = max(min(po->translucency, th->sourcevalue - (INT16)FixedMul(delta, factor)), th->destvalue); + else if (th->destvalue > th->sourcevalue) + po->translucency = min(max(po->translucency, th->sourcevalue + (INT16)FixedMul(delta, factor)), th->destvalue); + } + } + else + { + fixed_t timerdest = FixedMul(FixedDiv(256, NUMTRANSMAPS), NUMTRANSMAPS-th->destvalue); + + if (th->destvalue > th->sourcevalue) // fading out, destvalue is higher + { + // for timer, lower is transparent, higher is opaque + stillfading = (th->timer > timerdest); + th->timer = max(timerdest, th->timer - th->speed); + } + else if (th->destvalue < th->sourcevalue) // fading in, destvalue is lower + { stillfading = (th->timer < timerdest); + th->timer = min(timerdest, th->timer + th->speed); + } + + if (!stillfading) + { + po->translucency = max(min(th->destvalue, NUMTRANSMAPS), 0); + // remove thinker + if (po->thinker == &th->thinker) + po->thinker = NULL; + P_RemoveThinker(&th->thinker); + } + else + po->translucency = FixedDiv(256-th->timer, FixedDiv(256, NUMTRANSMAPS)); } if (!stillfading) @@ -2901,9 +2932,9 @@ void T_PolyObjFade(polyfade_t *th) po->flags |= (po->spawnflags & POF_RENDERALL); // set collision - if (th->docollision && th->speed) + if (th->docollision) { - if (th->speed > 0) // faded out + if (th->destvalue > th->sourcevalue) // faded out { po->flags &= ~POF_SOLID; po->flags |= POF_NOSPECIALS; @@ -2918,10 +2949,14 @@ void T_PolyObjFade(polyfade_t *th) } else { + if (po->translucency >= NUMTRANSMAPS) + // HACK: OpenGL renders fully opaque when >= NUMTRANSMAPS + po->translucency = NUMTRANSMAPS-1; + po->flags |= (po->spawnflags & POF_RENDERALL); // set collision - if (th->docollision && th->speed) + if (th->docollision) { if (th->doghostfade) { @@ -2967,12 +3002,22 @@ INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata) // set fields th->polyObjNum = pfdata->polyObjNum; + th->sourcevalue = po->translucency; th->destvalue = pfdata->destvalue; th->docollision = pfdata->docollision; th->doghostfade = pfdata->doghostfade; - th->timer = pfdata->timer; - th->speed = pfdata->speed; - th->interval = pfdata->interval; + + if (pfdata->ticbased) + { + th->ticbased = true; + th->timer = th->speed = abs(pfdata->speed); // use th->speed for total duration + } + else + { + th->ticbased = false; + th->timer = FixedMul(FixedDiv(256, NUMTRANSMAPS), NUMTRANSMAPS - po->translucency); // use as internal counter + th->speed = pfdata->speed; + } oldpo = po; diff --git a/src/p_polyobj.h b/src/p_polyobj.h index d5c07cb5b..61404112c 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -212,12 +212,13 @@ typedef struct polyfade_s thinker_t thinker; // must be first INT32 polyObjNum; + INT32 sourcevalue; INT32 destvalue; boolean docollision; boolean doghostfade; + boolean ticbased; INT32 timer; INT32 speed; - UINT32 interval; } polyfade_t; // @@ -285,9 +286,8 @@ typedef struct polyfadedata_s INT32 destvalue; boolean docollision; boolean doghostfade; - INT32 timer; + boolean ticbased; INT32 speed; - UINT32 interval; } polyfadedata_t; // diff --git a/src/p_saveg.c b/src/p_saveg.c index 403f05b00..2bfc5859a 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1705,12 +1705,13 @@ static void SavePolyfadeThinker(const thinker_t *th, const UINT8 type) const polyfade_t *ht = (const void *)th; WRITEUINT8(save_p, type); WRITEINT32(save_p, ht->polyObjNum); + WRITEINT32(save_p, ht->sourcevalue); WRITEINT32(save_p, ht->destvalue); WRITEUINT8(save_p, (UINT8)ht->docollision); WRITEUINT8(save_p, (UINT8)ht->doghostfade); + WRITEUINT8(save_p, (UINT8)ht->ticbased); WRITEINT32(save_p, ht->timer); WRITEINT32(save_p, ht->speed); - WRITEUINT32(save_p, ht->interval); } #endif @@ -2719,12 +2720,13 @@ static void LoadPolyfadeThinker(actionf_p1 thinker) polyfade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; ht->polyObjNum = READINT32(save_p); + ht->sourcevalue = READINT32(save_p); ht->destvalue = READINT32(save_p); ht->docollision = (boolean)READUINT8(save_p); ht->doghostfade = (boolean)READUINT8(save_p); + ht->ticbased = (boolean)READUINT8(save_p); ht->timer = READINT32(save_p); ht->speed = READINT32(save_p); - ht->interval = READUINT32(save_p); P_AddThinker(&ht->thinker); } #endif diff --git a/src/p_spec.c b/src/p_spec.c index 65f7fcd67..49d266f99 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1242,7 +1242,21 @@ static void PolyTranslucency(line_t *line) if (po->isBad) return; - po->translucency = (line->frontsector->floorheight >> FRACBITS) / 100; + // if DONTPEGBOTTOM, specify raw translucency value in Front X Offset + // else, take it out of 1000. If Front X Offset is specified, use that. Else, use floorheight. + if (line->flags & ML_EFFECT3) // relative calc + po->translucency = max(min(po->translucency + ((line->flags & ML_DONTPEGBOTTOM) ? + max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), -NUMTRANSMAPS) + : (sides[line->sidenum[0]].textureoffset ? + max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 1000), -1000) / 100 + : max(min(line->frontsector->floorheight>>FRACBITS, 1000), -1000) / 100)), + NUMTRANSMAPS), 0); + else + po->translucency = (line->flags & ML_DONTPEGBOTTOM) ? + max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), 0) + : (sides[line->sidenum[0]].textureoffset ? + max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 1000), 0) / 100 + : max(min(line->frontsector->floorheight>>FRACBITS, 1000), 0) / 100); } // @@ -1265,22 +1279,39 @@ static boolean PolyFade(line_t *line) if (po->isBad) return 0; - // already equal, nothing to do - if (po->translucency == max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), 0)) - return 1; - polyfadedata_t pfd; pfd.polyObjNum = polyObjNum; - pfd.destvalue = max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), 0); - pfd.docollision = !(line->flags & ML_BOUNCY), // do not handle collision flags - pfd.doghostfade = (line->flags & ML_EFFECT1), // do ghost fade (no collision flags during fade) - pfd.timer = abs(sides[line->sidenum[0]].rowoffset>>FRACBITS); - pfd.speed = FixedFloor(FixedDiv(pfd.destvalue - po->translucency, pfd.timer))/FRACUNIT; - if (!pfd.speed) - pfd.speed = (pfd.destvalue < po->translucency) ? -1 : 1; - pfd.interval = max(FixedFloor(FixedDiv(pfd.timer, abs(pfd.destvalue - po->translucency)))/FRACUNIT, 1); + // if DONTPEGBOTTOM, specify raw translucency value in Front X Offset + // else, take it out of 1000 like type 491. If Front X Offset is specified, use that. Else, use floorheight. + if (line->flags & ML_EFFECT3) + pfd.destvalue = max(min(po->translucency + ((line->flags & ML_DONTPEGBOTTOM) ? + max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), -NUMTRANSMAPS) + : (sides[line->sidenum[0]].textureoffset ? + max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 1000), -1000) / 100 + : max(min(line->frontsector->floorheight>>FRACBITS, 1000), -1000) / 100)), + NUMTRANSMAPS), 0); + else + pfd.destvalue = (line->flags & ML_DONTPEGBOTTOM) ? + max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), 0) + : (sides[line->sidenum[0]].textureoffset ? + max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 1000), 0) / 100 + : max(min(line->frontsector->floorheight>>FRACBITS, 1000), 0) / 100); + + // already equal, nothing to do + if (po->translucency == pfd.destvalue) + return 1; + + pfd.docollision = !(line->flags & ML_BOUNCY); // do not handle collision flags + pfd.doghostfade = (line->flags & ML_EFFECT1); // do ghost fade (no collision flags during fade) + pfd.ticbased = (line->flags & ML_EFFECT4); // Speed = Tic Duration + + // allow Back Y Offset to be consistent with other fade specials + pfd.speed = (line->sidenum[1] != 0xFFFF && !sides[line->sidenum[0]].rowoffset) ? + abs(sides[line->sidenum[1]].rowoffset>>FRACBITS) + : abs(sides[line->sidenum[0]].rowoffset>>FRACBITS); + return EV_DoPolyObjFade(&pfd); } From 539092bec5a173c4a78b24e90df66a6498843966 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 13 Sep 2018 00:26:24 -0400 Subject: [PATCH 178/306] 491, 492: Allow BLOCKMONSTERS raw translucency value in floorheight --- src/p_spec.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 49d266f99..0502b5638 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1246,14 +1246,18 @@ static void PolyTranslucency(line_t *line) // else, take it out of 1000. If Front X Offset is specified, use that. Else, use floorheight. if (line->flags & ML_EFFECT3) // relative calc po->translucency = max(min(po->translucency + ((line->flags & ML_DONTPEGBOTTOM) ? - max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), -NUMTRANSMAPS) + (sides[line->sidenum[0]].textureoffset ? + max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), -NUMTRANSMAPS) + : max(min(line->frontsector->floorheight>>FRACBITS, NUMTRANSMAPS), -NUMTRANSMAPS)) : (sides[line->sidenum[0]].textureoffset ? max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 1000), -1000) / 100 : max(min(line->frontsector->floorheight>>FRACBITS, 1000), -1000) / 100)), NUMTRANSMAPS), 0); else po->translucency = (line->flags & ML_DONTPEGBOTTOM) ? - max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), 0) + (sides[line->sidenum[0]].textureoffset ? + max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), 0) + : max(min(line->frontsector->floorheight>>FRACBITS, NUMTRANSMAPS), 0)) : (sides[line->sidenum[0]].textureoffset ? max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 1000), 0) / 100 : max(min(line->frontsector->floorheight>>FRACBITS, 1000), 0) / 100); @@ -1284,17 +1288,21 @@ static boolean PolyFade(line_t *line) pfd.polyObjNum = polyObjNum; // if DONTPEGBOTTOM, specify raw translucency value in Front X Offset - // else, take it out of 1000 like type 491. If Front X Offset is specified, use that. Else, use floorheight. - if (line->flags & ML_EFFECT3) + // else, take it out of 1000. If Front X Offset is specified, use that. Else, use floorheight. + if (line->flags & ML_EFFECT3) // relative calc pfd.destvalue = max(min(po->translucency + ((line->flags & ML_DONTPEGBOTTOM) ? - max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), -NUMTRANSMAPS) + (sides[line->sidenum[0]].textureoffset ? + max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), -NUMTRANSMAPS) + : max(min(line->frontsector->floorheight>>FRACBITS, NUMTRANSMAPS), -NUMTRANSMAPS)) : (sides[line->sidenum[0]].textureoffset ? max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 1000), -1000) / 100 : max(min(line->frontsector->floorheight>>FRACBITS, 1000), -1000) / 100)), NUMTRANSMAPS), 0); else pfd.destvalue = (line->flags & ML_DONTPEGBOTTOM) ? - max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), 0) + (sides[line->sidenum[0]].textureoffset ? + max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), 0) + : max(min(line->frontsector->floorheight>>FRACBITS, NUMTRANSMAPS), 0)) : (sides[line->sidenum[0]].textureoffset ? max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 1000), 0) / 100 : max(min(line->frontsector->floorheight>>FRACBITS, 1000), 0) / 100); From 5aa66f887270733ebfe4bb3452fc58c8f4453995 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 13 Sep 2018 10:38:15 -0400 Subject: [PATCH 179/306] 455: Add speed increment timing (~EFFECT4) to FadeColormap --- src/p_saveg.c | 2 ++ src/p_spec.c | 25 +++++++++++++++++++------ src/p_spec.h | 5 +++-- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 1c8d46aa1..e0d3f1e94 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1687,6 +1687,7 @@ static void SaveFadeColormapThinker(const thinker_t *th, const UINT8 type) WRITEUINT32(save_p, SaveSector(ht->sector)); SaveExtraColormap(save_p, ht->source_exc); SaveExtraColormap(save_p, ht->dest_exc); + WRITEUINT8(save_p, (UINT8)ht->ticbased); WRITEINT32(save_p, ht->duration); WRITEINT32(save_p, ht->timer); } @@ -2686,6 +2687,7 @@ static inline void LoadFadeColormapThinker(actionf_p1 thinker) ht->sector = LoadSector(READUINT32(save_p)); ht->source_exc = LoadExtraColormap(save_p); ht->dest_exc = LoadExtraColormap(save_p); + ht->ticbased = (boolean)READUINT8(save_p); ht->duration = READINT32(save_p); ht->timer = READINT32(save_p); if (ht->sector) diff --git a/src/p_spec.c b/src/p_spec.c index 491671c40..bed5a89b4 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -105,7 +105,7 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t * static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); static void P_ResetColormapFader(sector_t *sector); static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, extracolormap_t *dest_exc, - INT32 duration); + boolean ticbased, INT32 duration); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); @@ -3445,7 +3445,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) else Z_Free(exc); - Add_ColormapFader(§ors[secnum], source_exc, dest_exc, + Add_ColormapFader(§ors[secnum], source_exc, dest_exc, (line->flags & ML_EFFECT4), // tic-based timing (line->sidenum[1] != 0xFFFF ? abs(sides[line->sidenum[1]].rowoffset >> FRACBITS) : abs(P_AproxDistance(line->dx, line->dy) >> FRACBITS))); } break; @@ -7480,7 +7480,7 @@ static void P_ResetColormapFader(sector_t *sector) } static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, extracolormap_t *dest_exc, - INT32 duration) + boolean ticbased, INT32 duration) { P_ResetColormapFader(sector); @@ -7496,7 +7496,18 @@ static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, ext d->sector = sector; d->source_exc = source_exc; d->dest_exc = dest_exc; - d->duration = d->timer = duration; + + if (ticbased) + { + d->ticbased = true; + d->duration = d->timer = duration; + } + else + { + d->ticbased = false; + d->timer = 256; + d->duration = duration; // use as speed + } sector->fadecolormapdata = d; P_AddThinker(&d->thinker); // add thinker @@ -7504,7 +7515,8 @@ static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, ext void T_FadeColormap(fadecolormap_t *d) { - if (--d->timer <= 0) + if ((d->ticbased && --d->timer <= 0) + || (!d->ticbased && (d->timer -= d->duration) <= 0)) // d->duration used as speed decrement { d->sector->extra_colormap = d->dest_exc; P_ResetColormapFader(d->sector); @@ -7512,7 +7524,8 @@ void T_FadeColormap(fadecolormap_t *d) else { extracolormap_t *exc; - fixed_t factor = min(FixedDiv(d->duration - d->timer, d->duration), 1*FRACUNIT); + INT32 duration = d->ticbased ? d->duration : 256; + fixed_t factor = min(FixedDiv(duration - d->timer, duration), 1*FRACUNIT); INT16 cr, cg, cb, ca, fadestart, fadeend, fog; INT32 rgba, fadergba; diff --git a/src/p_spec.h b/src/p_spec.h index 9e0b7d5c4..0a798ffcc 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -461,8 +461,9 @@ typedef struct sector_t *sector; ///< Sector where action is taking place. extracolormap_t *source_exc; extracolormap_t *dest_exc; - INT32 duration; ///< Total duration for tic-based logic - INT32 timer; ///< Timer for tic-based logic + boolean ticbased; ///< Tic-based timing + INT32 duration; ///< Total duration for tic-based logic (OR: speed increment) + INT32 timer; ///< Timer for tic-based logic (OR: internal speed counter) } fadecolormap_t; void T_FadeColormap(fadecolormap_t *d); From 94939f661357bdf1c6c20b9894cf9d4aee33637b Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 13 Sep 2018 10:41:22 -0400 Subject: [PATCH 180/306] 455: Don't override fadergba on default/no colormap init (~BOUNCY) --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index bed5a89b4..72b215163 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3390,7 +3390,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { exc = R_CopyColormap(exc, false); exc->rgba = R_GetRgbaRGB(sides[line->sidenum[0]].colormap_data->rgba) + R_PutRgbaA(R_GetRgbaA(exc->rgba)); - exc->fadergba = R_GetRgbaRGB(sides[line->sidenum[0]].colormap_data->rgba) + R_PutRgbaA(R_GetRgbaA(exc->fadergba)); + //exc->fadergba = R_GetRgbaRGB(sides[line->sidenum[0]].colormap_data->rgba) + R_PutRgbaA(R_GetRgbaA(exc->fadergba)); if (!(source_exc = R_GetColormapFromList(exc))) { From 3fc8ed5a9f05d8a387517ae657f7e224cdddb196 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 13 Sep 2018 10:53:03 -0400 Subject: [PATCH 181/306] 455: Set timing by either Back Y or Front Y, but not line length --- src/p_spec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 72b215163..1d213b63e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3446,7 +3446,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) Z_Free(exc); Add_ColormapFader(§ors[secnum], source_exc, dest_exc, (line->flags & ML_EFFECT4), // tic-based timing - (line->sidenum[1] != 0xFFFF ? abs(sides[line->sidenum[1]].rowoffset >> FRACBITS) : abs(P_AproxDistance(line->dx, line->dy) >> FRACBITS))); + ((line->flags & ML_DONTPEGBOTTOM) || !sides[line->sidenum[0]].rowoffset) && line->sidenum[1] != 0xFFFF ? + abs(sides[line->sidenum[1]].rowoffset >> FRACBITS) + : abs(sides[line->sidenum[0]].rowoffset >> FRACBITS)); } break; From c32c72c401b16d15184b1821cb52ff9e80717910 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 7 Sep 2018 18:14:52 -0400 Subject: [PATCH 182/306] Thwomp fix: Don't trigger (look for players) when ~FF_EXISTS --- src/p_floor.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/src/p_floor.c b/src/p_floor.c index f30637659..f3dda23bf 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1818,6 +1818,7 @@ void T_ThwompSector(levelspecthink_t *thwomp) #define ceilingwasheight vars[5] fixed_t thwompx, thwompy; sector_t *actionsector; + ffloor_t *rover = NULL; INT32 secnum; // If you just crashed down, wait a second before coming back up. @@ -1832,7 +1833,16 @@ void T_ThwompSector(levelspecthink_t *thwomp) secnum = P_FindSectorFromTag((INT16)thwomp->vars[0], -1); if (secnum > 0) + { actionsector = §ors[secnum]; + + // Look for thwomp FFloor + for (rover = actionsector->ffloors; rover; rover = rover->next) + { + if (rover->master == thwomp->sourceline) + break; + } + } else return; // Bad bad bad! @@ -1921,10 +1931,13 @@ void T_ThwompSector(levelspecthink_t *thwomp) { mobj_t *mp = (void *)&actionsector->soundorg; - if (thwomp->sourceline->flags & ML_EFFECT4) - S_StartSound(mp, sides[thwomp->sourceline->sidenum[0]].textureoffset>>FRACBITS); - else - S_StartSound(mp, sfx_thwomp); + if (!rover || (rover->flags & FF_EXISTS)) + { + if (thwomp->sourceline->flags & ML_EFFECT4) + S_StartSound(mp, sides[thwomp->sourceline->sidenum[0]].textureoffset>>FRACBITS); + else + S_StartSound(mp, sfx_thwomp); + } thwomp->direction = 1; // start heading back up thwomp->distance = TICRATE; // but only after a small delay @@ -1938,18 +1951,21 @@ void T_ThwompSector(levelspecthink_t *thwomp) thinker_t *th; mobj_t *mo; - // scan the thinkers to find players! - for (th = thinkercap.next; th != &thinkercap; th = th->next) + if (!rover || (rover->flags & FF_EXISTS)) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo = (mobj_t *)th; - if (mo->type == MT_PLAYER && mo->health && mo->z <= thwomp->sector->ceilingheight - && P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT) + // scan the thinkers to find players! + for (th = thinkercap.next; th != &thinkercap; th = th->next) { - thwomp->direction = -1; - break; + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo = (mobj_t *)th; + if (mo->type == MT_PLAYER && mo->health && mo->z <= thwomp->sector->ceilingheight + && P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT) + { + thwomp->direction = -1; + break; + } } } From 89a6694d6743375e3dbaaabfec48f7e12d1f9cfb Mon Sep 17 00:00:00 2001 From: Digiku Date: Thu, 13 Sep 2018 11:30:00 -0400 Subject: [PATCH 183/306] Don't trigger thwomp on spectators --- src/p_floor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_floor.c b/src/p_floor.c index f3dda23bf..e613b5ed4 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1960,7 +1960,8 @@ void T_ThwompSector(levelspecthink_t *thwomp) continue; mo = (mobj_t *)th; - if (mo->type == MT_PLAYER && mo->health && mo->z <= thwomp->sector->ceilingheight + if (mo->type == MT_PLAYER && mo->health && mo->player && !mo->player->spectator + && mo->z <= thwomp->sector->ceilingheight && P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT) { thwomp->direction = -1; From 6824e6a3596031a11e78b9c1d4706deee592c83c Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 13 Sep 2018 12:08:46 -0400 Subject: [PATCH 184/306] Make extracolormap_t->fog UINT8; it's not boolean, but categorical --- src/p_saveg.c | 7 +++---- src/r_data.c | 10 +++++----- src/r_data.h | 8 ++++---- src/r_defs.h | 2 +- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index c9b474b1d..2d39ccfa2 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -481,7 +481,7 @@ static void SaveExtraColormap(UINT8 *put, extracolormap_t *exc) WRITEUINT8(put, exc->fadestart); WRITEUINT8(put, exc->fadeend); - WRITEUINT8(put, (UINT8)exc->fog); + WRITEUINT8(put, exc->fog); WRITEINT32(put, exc->rgba); WRITEINT32(put, exc->fadergba); @@ -497,9 +497,8 @@ static extracolormap_t *LoadExtraColormap(UINT8 *get) //size_t dbg_i = 0; UINT8 fadestart = READUINT8(get), - fadeend = READUINT8(get); - - boolean fog = (boolean)READUINT8(get); + fadeend = READUINT8(get), + fog = READUINT8(get); INT32 rgba = READINT32(get), fadergba = READINT32(get); diff --git a/src/r_data.c b/src/r_data.c index c2e28fe9f..e987da066 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1439,10 +1439,10 @@ void R_AddColormapToList(extracolormap_t *extra_colormap) // #ifdef EXTRACOLORMAPLUMPS boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams, - INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump) + INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog, lumpnum_t lump) #else boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams, - INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog) + INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog) #endif { return ( @@ -1504,9 +1504,9 @@ boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, bo // NOTE: Returns NULL if no match is found // #ifdef EXTRACOLORMAPLUMPS -extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump) +extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog, lumpnum_t lump) #else -extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog) +extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog) #endif { extracolormap_t *exc; @@ -1730,7 +1730,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) // default values UINT8 cr = 0, cg = 0, cb = 0, ca = 0, cfr = 0, cfg = 0, cfb = 0, cfa = 25; UINT32 fadestart = 0, fadeend = 31; - boolean fog = false; + UINT8 fog = 0; INT32 rgba = 0, fadergba = 0x19000000; #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) diff --git a/src/r_data.h b/src/r_data.h index 3a7740c96..54857661a 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -112,12 +112,12 @@ void R_AddColormapToList(extracolormap_t *extra_colormap); #ifdef EXTRACOLORMAPLUMPS boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams, - INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump); -extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog, lumpnum_t lump); + INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog, lumpnum_t lump); +extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog, lumpnum_t lump); #else boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams, - INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog); -extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, boolean fog); + INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog); +extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog); #endif boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams); boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, boolean checkrgba, boolean checkfadergba, boolean checkparams); diff --git a/src/r_defs.h b/src/r_defs.h index 1f2afdb99..b9c6fd7dc 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -53,7 +53,7 @@ typedef UINT8 lighttable_t; typedef struct extracolormap_s { UINT8 fadestart, fadeend; - boolean fog; + UINT8 fog; // 1 = disable sprite fullbright, 2 = force planes fullbright, see public gitlab !268 // store rgba values in combined bitwise // also used in OpenGL instead lighttables From 761150b12d3b0fcf1a7f392d609b4a43e75ae982 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 13 Sep 2018 12:18:10 -0400 Subject: [PATCH 185/306] 455: Fog flag fix for fading --- src/p_spec.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 1d213b63e..88a046b37 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7577,9 +7577,7 @@ void T_FadeColormap(fadecolormap_t *d) fadestart = APPLYFADE(d->dest_exc->fadestart, d->source_exc->fadestart, d->sector->extra_colormap->fadestart); fadeend = APPLYFADE(d->dest_exc->fadeend, d->source_exc->fadeend, d->sector->extra_colormap->fadeend); - // fog: essentially we're switching from source_exc->fog to dest_exc->fog with a delta - // of 1 or -1, and hoping the factor rounds appropriately in the timing. - fog = APPLYFADE(d->dest_exc->fog, d->source_exc->fog, d->sector->extra_colormap->fog); + fog = abs(factor) > FRACUNIT/2 ? d->dest_exc->fog : d->source_exc->fog; // set new fog flag halfway through fade #undef APPLYFADE From 07af82aa8495101c8170a44b7f92cb5c3dc7eb69 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 13 Sep 2018 12:18:53 -0400 Subject: [PATCH 186/306] Missed fog boolean -> integer --- src/r_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_data.c b/src/r_data.c index e987da066..f1cd519e0 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1784,7 +1784,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3) { if (p2[1]) { - fog = (boolean)NUMFROMCHAR(p2[1]); + fog = NUMFROMCHAR(p2[1]); if (p2[2] && p2[3]) { fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10); From 714464993ef49e8f6beb3133dce03380e0289c36 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Sep 2018 08:26:52 -0400 Subject: [PATCH 187/306] 420: Removed unnecessary include (gametic no longer needed) --- src/p_lights.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/p_lights.c b/src/p_lights.c index 95171155e..8bcdd8ce0 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -13,7 +13,6 @@ /// Fire flicker, light flash, strobe flash, lightning flash, glow, and fade. #include "doomdef.h" -#include "doomstat.h" // gametic #include "p_local.h" #include "r_state.h" #include "z_zone.h" From b59aa2710433ca89744f4f9a91eb1e0dba727c6f Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 23 Aug 2018 09:37:02 -0400 Subject: [PATCH 188/306] Loose ends other targets (cherry picked from commit 9a5fc5f66a31baf713c6f32f7a696b933da6907b) --- src/android/i_sound.c | 22 ++++----- src/djgppdos/i_sound.c | 28 +---------- src/dummy/i_sound.c | 15 ++---- src/sdl/sdl_sound.c | 6 +-- src/win32/win_main.c | 4 +- src/win32/win_snd.c | 106 +++++++++++++++++++++-------------------- 6 files changed, 74 insertions(+), 107 deletions(-) diff --git a/src/android/i_sound.c b/src/android/i_sound.c index ecf96f2f0..1011dbb6a 100644 --- a/src/android/i_sound.c +++ b/src/android/i_sound.c @@ -64,12 +64,12 @@ void I_InitMusic(void){} void I_ShutdownMusic(void){} -void I_PauseSong(INT32 handle) +void I_PauseSong(void) { (void)handle; } -void I_ResumeSong(INT32 handle) +void I_ResumeSong(void) { (void)handle; } @@ -80,23 +80,19 @@ void I_ResumeSong(INT32 handle) UINT8 midimusic_started = 0; -void I_InitMIDIMusic(void){} - -void I_ShutdownMIDIMusic(void){} - -void I_SetMIDIMusicVolume(INT32 volume) -{ - (void)volume; -} - -INT32 I_RegisterSong(void *data, size_t len) +boolean I_LoadSong(char *data, size_t len) { (void)data; (void)len; return -1; } -boolean I_PlaySong(INT32 handle, INT32 looping) +void I_SetMIDIMusicVolume(INT32 volume) +{ + (void)volume; +} + +boolean I_PlaySong(boolean looping) { (void)handle; (void)looping; diff --git a/src/djgppdos/i_sound.c b/src/djgppdos/i_sound.c index 88fc807f4..105e8d67a 100644 --- a/src/djgppdos/i_sound.c +++ b/src/djgppdos/i_sound.c @@ -408,31 +408,7 @@ void I_ShutdownMIDIMusic(void) music_started=false; } -void I_InitDigMusic(void) -{ -// CONS_Printf("Digital music not yet supported under DOS.\n"); -} - -void I_ShutdownDigMusic(void) -{ -// CONS_Printf("Digital music not yet supported under DOS.\n"); -} - -void I_InitMusic(void) -{ - if (!nodigimusic) - I_InitDigMusic(); - if (!nomidimusic) - I_InitMIDIMusic(); -} - -void I_ShutdownMusic(void) -{ - I_ShutdownMIDIMusic(); - I_ShutdownDigMusic(); -} - -boolean I_PlaySong(INT32 handle, INT32 looping) +boolean I_PlaySong(boolean looping) { handle = 0; if (nomidimusic) @@ -495,7 +471,7 @@ void I_UnRegisterSong(INT32 handle) //destroy_midi(currsong); } -INT32 I_RegisterSong(void *data, size_t len) +boolean I_LoadSong(char *data, size_t len) { int e = len; //Alam: For error if (nomidimusic) diff --git a/src/dummy/i_sound.c b/src/dummy/i_sound.c index 51dbb610d..2f6f0001c 100644 --- a/src/dummy/i_sound.c +++ b/src/dummy/i_sound.c @@ -70,7 +70,7 @@ void I_PauseSong(INT32 handle) (void)handle; } -void I_ResumeSong(INT32 handle) +void I_ResumeSong(void) { (void)handle; } @@ -79,23 +79,14 @@ void I_ResumeSong(INT32 handle) // MIDI I/O // -void I_InitMIDIMusic(void){} - -void I_ShutdownMIDIMusic(void){} - -void I_SetMIDIMusicVolume(UINT8 volume) -{ - (void)volume; -} - -INT32 I_RegisterSong(void *data, size_t len) +boolean I_LoadSong(char *data, size_t len) { (void)data; (void)len; return -1; } -boolean I_PlaySong(INT32 handle, boolean looping) +boolean I_PlaySong(boolean looping) { (void)handle; (void)looping; diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index 6c70c163b..c714f675b 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -1605,7 +1605,7 @@ static void I_PauseGME(void) #endif } -void I_PauseSong(INT32 handle) +void I_PauseSong(void) { (void)handle; I_PauseGME(); @@ -1625,7 +1625,7 @@ static void I_ResumeGME(void) #endif } -void I_ResumeSong(INT32 handle) +void I_ResumeSong(void) { (void)handle; I_ResumeGME(); @@ -1669,7 +1669,7 @@ void I_UnRegisterSong(INT32 handle) #endif } -INT32 I_RegisterSong(void *data, size_t len) +boolean I_LoadSong(char *data, size_t len) { #ifdef HAVE_MIXER if (nomidimusic || !musicStarted) diff --git a/src/win32/win_main.c b/src/win32/win_main.c index 6c774f557..bfe620a43 100644 --- a/src/win32/win_main.c +++ b/src/win32/win_main.c @@ -110,9 +110,9 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR // pause music when alt-tab if (appActive && !paused) - I_ResumeSong(0); + I_ResumeSong(); else if (!paused) - I_PauseSong(0); + I_PauseSong(); { HANDLE ci = GetStdHandle(STD_INPUT_HANDLE); DWORD mode; diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index f168f1fe3..18c88d267 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -456,14 +456,14 @@ void I_ShutdownMusic(void) I_ShutdownMIDIMusic(); } -void I_PauseSong(INT32 handle) +void I_PauseSong(void) { UNREFERENCED_PARAMETER(handle); if (music_stream) FMR_MUSIC(FMOD_Channel_SetPaused(music_channel, true)); } -void I_ResumeSong(INT32 handle) +void I_ResumeSong(void) { UNREFERENCED_PARAMETER(handle); if (music_stream) @@ -644,60 +644,64 @@ boolean I_StartDigSong(const char *musicname, boolean looping) current_track = 0; // Try to find a loop point in streaming music formats (ogg, mp3) - if (looping) - { - FMOD_RESULT e; - FMOD_TAG tag; - unsigned int loopstart, loopend; + FMOD_RESULT e; + FMOD_TAG tag; + unsigned int loopstart, loopend; - // A proper LOOPPOINT is its own tag, stupid. - e = FMOD_Sound_GetTag(music_stream, "LOOPPOINT", 0, &tag); - if (e != FMOD_ERR_TAGNOTFOUND) + // A proper LOOPPOINT is its own tag, stupid. + e = FMOD_Sound_GetTag(music_stream, "LOOPPOINT", 0, &tag); + if (e != FMOD_ERR_TAGNOTFOUND) + { + FMR(e); + loopstart = atoi((char *)tag.data); // assumed to be a string data tag. + FMR(FMOD_Sound_GetLoopPoints(music_stream, NULL, FMOD_TIMEUNIT_PCM, &loopend, FMOD_TIMEUNIT_PCM)); + if (loopstart > 0) + FMR(FMOD_Sound_SetLoopPoints(music_stream, loopstart, FMOD_TIMEUNIT_PCM, loopend, FMOD_TIMEUNIT_PCM)); + return true; + } + + // todo + // if(music type == MIDI) + // { + // FMR(FMOD_Sound_SetMode(music_stream, FMOD_LOOP_NORMAL)); + // return true; + // } + + // Use LOOPMS for time in miliseconds. + e = FMOD_Sound_GetTag(music_stream, "LOOPMS", 0, &tag); + if (e != FMOD_ERR_TAGNOTFOUND) + { + FMR(e); + loopstart = atoi((char *)tag.data); // assumed to be a string data tag. + FMR(FMOD_Sound_GetLoopPoints(music_stream, NULL, FMOD_TIMEUNIT_MS, &loopend, FMOD_TIMEUNIT_PCM)); + if (loopstart > 0) + FMR(FMOD_Sound_SetLoopPoints(music_stream, loopstart, FMOD_TIMEUNIT_MS, loopend, FMOD_TIMEUNIT_PCM)); + return true; + } + + // Try to fetch it from the COMMENT tag, like A.J. Freda + e = FMOD_Sound_GetTag(music_stream, "COMMENT", 0, &tag); + if (e != FMOD_ERR_TAGNOTFOUND) + { + char *loopText; + // Handle any errors that arose, first + FMR(e); + // Figure out where the number starts + loopText = strstr((char *)tag.data,"LOOPPOINT="); + if (loopText != NULL) { - FMR(e); - loopstart = atoi((char *)tag.data); // assumed to be a string data tag. + // Skip the "LOOPPOINT=" part. + loopText += 10; + // Convert it to our looppoint + // FMOD seems to ensure the tag is properly NULL-terminated. + // atoi will stop when it reaches anything that's not a number. + loopstart = atoi(loopText); + // Now do the rest like above FMR(FMOD_Sound_GetLoopPoints(music_stream, NULL, FMOD_TIMEUNIT_PCM, &loopend, FMOD_TIMEUNIT_PCM)); if (loopstart > 0) FMR(FMOD_Sound_SetLoopPoints(music_stream, loopstart, FMOD_TIMEUNIT_PCM, loopend, FMOD_TIMEUNIT_PCM)); - return true; - } - - // Use LOOPMS for time in miliseconds. - e = FMOD_Sound_GetTag(music_stream, "LOOPMS", 0, &tag); - if (e != FMOD_ERR_TAGNOTFOUND) - { - FMR(e); - loopstart = atoi((char *)tag.data); // assumed to be a string data tag. - FMR(FMOD_Sound_GetLoopPoints(music_stream, NULL, FMOD_TIMEUNIT_MS, &loopend, FMOD_TIMEUNIT_PCM)); - if (loopstart > 0) - FMR(FMOD_Sound_SetLoopPoints(music_stream, loopstart, FMOD_TIMEUNIT_MS, loopend, FMOD_TIMEUNIT_PCM)); - return true; - } - - // Try to fetch it from the COMMENT tag, like A.J. Freda - e = FMOD_Sound_GetTag(music_stream, "COMMENT", 0, &tag); - if (e != FMOD_ERR_TAGNOTFOUND) - { - char *loopText; - // Handle any errors that arose, first - FMR(e); - // Figure out where the number starts - loopText = strstr((char *)tag.data,"LOOPPOINT="); - if (loopText != NULL) - { - // Skip the "LOOPPOINT=" part. - loopText += 10; - // Convert it to our looppoint - // FMOD seems to ensure the tag is properly NULL-terminated. - // atoi will stop when it reaches anything that's not a number. - loopstart = atoi(loopText); - // Now do the rest like above - FMR(FMOD_Sound_GetLoopPoints(music_stream, NULL, FMOD_TIMEUNIT_PCM, &loopend, FMOD_TIMEUNIT_PCM)); - if (loopstart > 0) - FMR(FMOD_Sound_SetLoopPoints(music_stream, loopstart, FMOD_TIMEUNIT_PCM, loopend, FMOD_TIMEUNIT_PCM)); - } - return true; } + return true; } // No special loop point, but we're playing so it's all good. @@ -825,7 +829,7 @@ void I_SetMIDIMusicVolume(UINT8 volume) FMR_MUSIC(FMOD_Channel_SetVolume(music_channel, volume / 31.0)); } -INT32 I_RegisterSong(void *data, size_t len) +boolean I_PlaySong(boolean looping) { FMOD_CREATESOUNDEXINFO fmt; memset(&fmt, 0, sizeof(FMOD_CREATESOUNDEXINFO)); From 06b73679414f3c52755ee407833b0d965f0ab761 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 23 Aug 2018 10:18:38 -0400 Subject: [PATCH 189/306] Added I_GetMusicType and removed midimode variable * Revised S_PlayMusic arguments * Now music plays again! (cherry picked from commit 55f3803e4b9f8104c90cc6c769d54121e5bac0b8) --- src/i_sound.h | 18 +++++++++++++++ src/s_sound.c | 16 +++++++------ src/sdl/mixer_sound.c | 54 +++++++++++++++++++++++++++++++++---------- 3 files changed, 69 insertions(+), 19 deletions(-) diff --git a/src/i_sound.h b/src/i_sound.h index 084479ee1..0fe62d5eb 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -18,6 +18,21 @@ #include "sounds.h" #include "command.h" +// copied from SDL mixer, plus GME +typedef enum { + MU_NONE, + MU_CMD, + MU_WAV, + MU_MOD, + MU_MID, + MU_OGG, + MU_MP3, + MU_MP3_MAD_UNUSED, // use MU_MP3 instead + MU_FLAC, + MU_MODPLUG_UNUSED, // use MU_MOD instead + MU_GME +} musictype_t; + /** \brief Sound subsystem runing and waiting */ extern UINT8 sound_started; @@ -108,6 +123,9 @@ void I_SetSfxVolume(UINT8 volume); // // MUSIC I/O // + +musictype_t I_GetMusicType(void); + /** \brief Init the music systems */ void I_InitMusic(void); diff --git a/src/s_sound.c b/src/s_sound.c index 76ee4c649..279f0dc6d 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1227,7 +1227,7 @@ static boolean S_MIDIMusic(const char *mname, boolean looping) return true; } -static boolean S_DigMusic(const char *mname, boolean looping) +static boolean S_PlayMusic(boolean looping) { if (nodigimusic || digital_disabled) return false; // try midi @@ -1235,11 +1235,6 @@ static boolean S_DigMusic(const char *mname, boolean looping) if (!I_StartDigSong(mname, looping)) return false; - strncpy(music_name, mname, 7); - music_name[6] = 0; - music_lumpnum = LUMPERROR; - music_data = NULL; - music_handle = 0; return true; } @@ -1262,11 +1257,18 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) if (strncmp(music_name, mmusic, 6)) { S_StopMusic(); // shutdown old music - if (!S_DigMusic(mmusic, looping) && !S_MIDIMusic(mmusic, looping)) + + if (!S_LoadMusic(mmusic)) { CONS_Alert(CONS_ERROR, M_GetText("Music lump %.6s not found!\n"), mmusic); return; } + + if (!S_PlayMusic(looping)) + { + CONS_Alert(CONS_ERROR, "Music cannot be played!\n"); + return; + } } I_SetSongTrack(mflags & MUSIC_TRACKMASK); } diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 5211efe0a..0888d5d31 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -62,7 +62,6 @@ UINT8 sound_started = false; -static boolean midimode; static Mix_Music *music; static UINT8 music_volume, midi_volume, sfx_volume; static float loop_point; @@ -87,7 +86,6 @@ void I_StartupSound(void) return; } - midimode = false; music = NULL; music_volume = midi_volume = sfx_volume = 0; @@ -436,6 +434,25 @@ void I_SetSfxVolume(UINT8 volume) // Music // +musictype_t I_GetMusicType(void) +{ +#ifdef HAVE_LIBGME + if (gme) + return MU_GME; + else +#endif + if (!music) + return MU_NONE; + else if (Mix_GetMusicType(music) == MUS_MID) + return MU_MID; + else if (Mix_GetMusicType(music) == MUS_MOD || Mix_GetMusicType(music) == MUS_MODPLUG_UNUSED) + return MU_MOD; + else if (Mix_GetMusicType(music) == MUS_MP3 || Mix_GetMusicType(music) == MUS_MP3_MAD_UNUSED) + return MU_MP3; + else + return (musictype_t)Mix_GetMusicType(music); +} + // Music hooks static void music_loop(void) { @@ -470,8 +487,19 @@ FUNCMATH void I_InitMusic(void) void I_ShutdownMusic(void) { - I_ShutdownDigMusic(); - I_ShutdownMIDIMusic(); +#ifdef HAVE_LIBGME + if (gme) + { + Mix_HookMusic(NULL, NULL); + gme_delete(gme); + gme = NULL; + } +#endif + if (!music) + return; + Mix_HookMusicFinished(NULL); + Mix_FreeMusic(music); + music = NULL; } void I_PauseSong(INT32 handle) @@ -492,7 +520,15 @@ void I_ResumeSong(INT32 handle) // Digital Music // -void I_InitDigMusic(void) +void I_SetDigMusicVolume(UINT8 volume) +{ + music_volume = volume; + if (I_GetMusicType() == MU_MID || !music) + return; + Mix_VolumeMusic((UINT32)volume*128/31); +} + +boolean I_SetSongSpeed(float speed) { #ifdef HAVE_LIBGME gme = NULL; @@ -691,8 +727,6 @@ boolean I_StartDigSong(const char *musicname, boolean looping) void I_StopDigSong(void) { - if (midimode) - return; #ifdef HAVE_LIBGME if (gme) { @@ -791,7 +825,7 @@ void I_SetMIDIMusicVolume(UINT8 volume) midi_volume = 31; //midi_volume = volume; - if (!midimode || !music) + if (I_GetMusicType() != MU_MID || !music) return; Mix_VolumeMusic((UINT32)midi_volume*128/31); } @@ -834,10 +868,6 @@ void I_StopSong(INT32 handle) void I_UnRegisterSong(INT32 handle) { - if (!midimode || !music) - return; - - (void)handle; Mix_FreeMusic(music); music = NULL; } From 46b53e8baeede0df6c75d93697301a027aeb8a70 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 23 Aug 2018 10:19:04 -0400 Subject: [PATCH 190/306] Added I_GetMusicType and removed midimode variable: other targets (cherry picked from commit 14b393ab16736bb44dab6fd4a90b7bdd8ff782e0) --- src/android/i_sound.c | 24 ++---- src/djgppdos/i_sound.c | 33 ++++----- src/dummy/i_sound.c | 31 ++++---- src/sdl/sdl_sound.c | 98 +++++++++++-------------- src/win32/win_snd.c | 162 +++++++++++++++++++---------------------- 5 files changed, 155 insertions(+), 193 deletions(-) diff --git a/src/android/i_sound.c b/src/android/i_sound.c index 1011dbb6a..c3fc038e5 100644 --- a/src/android/i_sound.c +++ b/src/android/i_sound.c @@ -60,6 +60,11 @@ void I_SetSfxVolume(INT32 volume) // UINT8 music_started = 0; +musictype_t I_GetMusicType(void) +{ + return MU_NONE; +} + void I_InitMusic(void){} void I_ShutdownMusic(void){} @@ -99,12 +104,12 @@ boolean I_PlaySong(boolean looping) return false; } -void I_StopSong(INT32 handle) +void I_StopSong(void) { (void)handle; } -void I_UnRegisterSong(INT32 handle) +void I_UnloadSong(void) { (void)handle; } @@ -115,19 +120,6 @@ void I_UnRegisterSong(INT32 handle) UINT8 digmusic_started = 0; -void I_InitDigMusic(void){} - -void I_ShutdownDigMusic(void){} - -boolean I_StartDigSong(const char *musicname, INT32 looping) -{ - (void)musicname; - (void)looping; - return false; -} - -void I_StopDigSong(void){} - void I_SetDigMusicVolume(INT32 volume) { (void)volume; @@ -137,4 +129,4 @@ boolean I_SetSongSpeed(float speed) { (void)speed; return false; -} +} \ No newline at end of file diff --git a/src/djgppdos/i_sound.c b/src/djgppdos/i_sound.c index 105e8d67a..4c8ceb20c 100644 --- a/src/djgppdos/i_sound.c +++ b/src/djgppdos/i_sound.c @@ -322,6 +322,13 @@ static int islooping=0; static int musicdies=-1; UINT8 music_started=0; +musictype_t I_GetMusicType(void) +{ + if (currsong) + return MU_MID; + else + return MU_NONE; +} /* load_midi_mem: * Loads a standard MIDI file from memory, returning a pointer to @@ -389,7 +396,7 @@ static MIDI *load_midi_mem(char *mempointer,int *e) return midi; } -void I_InitMIDIMusic(void) +void I_InitMusic(void) { if (nomidimusic) return; @@ -398,12 +405,12 @@ void I_InitMIDIMusic(void) music_started = true; } -void I_ShutdownMIDIMusic(void) +void I_ShutdownMusic(void) { if ( !music_started ) return; - I_StopSong(1); + I_StopSong(); music_started=false; } @@ -439,7 +446,7 @@ void I_ResumeSong (INT32 handle) midi_resume(); } -void I_StopSong(INT32 handle) +void I_StopSong(void) { handle = 0; if (nomidimusic) @@ -462,7 +469,7 @@ int I_QrySongPlaying(int handle) } #endif -void I_UnRegisterSong(INT32 handle) +void I_UnloadSong(void) { handle = 0; if (nomidimusic) @@ -496,20 +503,6 @@ boolean I_LoadSong(char *data, size_t len) return 1; } -/// \todo Add OGG/MP3 support for dos -boolean I_StartDigSong(const char *musicname, INT32 looping) -{ - musicname = NULL; - looping = 0; - //CONS_Printf("I_StartDigSong: Not yet supported under DOS.\n"); - return false; -} - -void I_StopDigSong(void) -{ -// CONS_Printf("I_StopDigSong: Not yet supported under DOS.\n"); -} - void I_SetDigMusicVolume(INT32 volume) { volume = 0; @@ -524,4 +517,4 @@ boolean I_SetSongSpeed(float speed) { (void)speed; return false; -} +} \ No newline at end of file diff --git a/src/dummy/i_sound.c b/src/dummy/i_sound.c index 2f6f0001c..60cf51f73 100644 --- a/src/dummy/i_sound.c +++ b/src/dummy/i_sound.c @@ -61,11 +61,21 @@ void I_SetSfxVolume(UINT8 volume) // MUSIC I/O // +musictype_t I_GetMusicType(void) +{ + return MU_NONE; +} + void I_InitMusic(void){} void I_ShutdownMusic(void){} -void I_PauseSong(INT32 handle) +void I_SetMIDIMusicVolume(UINT8 volume) +{ + (void)volume; +} + +void I_PauseSong(void) { (void)handle; } @@ -93,12 +103,12 @@ boolean I_PlaySong(boolean looping) return false; } -void I_StopSong(INT32 handle) +void I_StopSong(void) { (void)handle; } -void I_UnRegisterSong(INT32 handle) +void I_UnloadSong(void) { (void)handle; } @@ -107,19 +117,6 @@ void I_UnRegisterSong(INT32 handle) // DIGMUSIC I/O // -void I_InitDigMusic(void){} - -void I_ShutdownDigMusic(void){} - -boolean I_StartDigSong(const char *musicname, boolean looping) -{ - (void)musicname; - (void)looping; - return false; -} - -void I_StopDigSong(void){} - void I_SetDigMusicVolume(UINT8 volume) { (void)volume; @@ -135,4 +132,4 @@ boolean I_SetSongTrack(int track) { (void)track; return false; -} +} \ No newline at end of file diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index c714f675b..b729d4d89 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -1313,10 +1313,27 @@ void I_StartupSound(void) // MUSIC API. // -void I_ShutdownMIDIMusic(void) +musictype_t I_GetMusicType(void) { - nomidimusic = false; - if (nodigimusic) I_ShutdownMusic(); +#ifdef HAVE_MIXER +#ifdef HAVE_LIBGME + if (gme) + return MU_GME; + else +#endif + if (!music) + return MU_NONE; + else if (Mix_GetMusicType(music) == MUS_MID) + return MU_MID; + else if (Mix_GetMusicType(music) == MUS_MOD || Mix_GetMusicType(music) == MUS_MODPLUG_UNUSED) + return MU_MOD; + else if (Mix_GetMusicType(music) == MUS_MP3 || Mix_GetMusicType(music) == MUS_MP3_MAD_UNUSED) + return MU_MP3; + else + return (musictype_t)Mix_GetMusicType(music); +#else + return MU_NONE +#endif } #ifdef HAVE_LIBGME @@ -1330,12 +1347,6 @@ static void I_ShutdownGMEMusic(void) } #endif -void I_ShutdownDigMusic(void) -{ - nodigimusic = false; - if (nomidimusic) I_ShutdownMusic(); -} - #ifdef HAVE_MIXER static boolean LoadSong(void *data, size_t lumplength, size_t selectpos) { @@ -1436,8 +1447,8 @@ void I_ShutdownMusic(void) CONS_Printf("%s", M_GetText("I_ShutdownMusic: ")); - I_UnRegisterSong(0); - I_StopDigSong(); + I_UnloadSong(); + I_StopSong(); Mix_CloseAudio(); #ifdef MIX_INIT Mix_Quit(); @@ -1450,16 +1461,6 @@ void I_ShutdownMusic(void) #endif } -void I_InitMIDIMusic(void) -{ - if (nodigimusic) I_InitMusic(); -} - -void I_InitDigMusic(void) -{ - if (nomidimusic) I_InitMusic(); -} - void I_InitMusic(void) { #ifdef HAVE_MIXER @@ -1639,17 +1640,29 @@ void I_ResumeSong(void) #endif } -void I_StopSong(INT32 handle) +void I_StopSong(void) { - (void)handle; + I_StopGME(); #ifdef HAVE_MIXER - if (nomidimusic || !musicStarted) + if (nodigimusic) return; - Mix_FadeOutMusic(MIDIfade); + +#ifdef MIXER_POS + if (canlooping) + Mix_HookMusicFinished(NULL); #endif + + Mix_HaltMusic(); + while (Mix_PlayingMusic()) + ; + + if (music[1]) + Mix_FreeMusic(music[1]); + music[1] = NULL; + LoadSong(NULL, 0, 1); } -void I_UnRegisterSong(INT32 handle) +void I_UnloadSong(void) { #ifdef HAVE_MIXER @@ -1714,7 +1727,7 @@ static void I_CleanupGME(void *userdata) static boolean I_StartGMESong(const char *musicname, boolean looping) { #ifdef HAVE_LIBGME - XBOXSTATIC char filename[9]; + char filename[9]; void *data; lumpnum_t lumpnum; size_t lumplength; @@ -1769,7 +1782,7 @@ static boolean I_StartGMESong(const char *musicname, boolean looping) boolean I_StartDigSong(const char *musicname, boolean looping) { #ifdef HAVE_MIXER - XBOXSTATIC char filename[9]; + char filename[9]; void *data; lumpnum_t lumpnum; size_t lumplength; @@ -1786,7 +1799,7 @@ boolean I_StartDigSong(const char *musicname, boolean looping) lumpnum = W_CheckNumForName(filename); - I_StopDigSong(); + I_StopSong(); if (lumpnum == LUMPERROR) { @@ -1811,7 +1824,7 @@ boolean I_StartDigSong(const char *musicname, boolean looping) { size_t scan; const char *dataum = data; - XBOXSTATIC char looplength[64]; + char looplength[64]; UINT32 loopstart = 0; UINT8 newcount = 0; @@ -1938,29 +1951,6 @@ static void I_StopGME(void) #endif } -void I_StopDigSong(void) -{ - I_StopGME(); -#ifdef HAVE_MIXER - if (nodigimusic) - return; - -#ifdef MIXER_POS - if (canlooping) - Mix_HookMusicFinished(NULL); -#endif - - Mix_HaltMusic(); - while (Mix_PlayingMusic()) - ; - - if (music[1]) - Mix_FreeMusic(music[1]); - music[1] = NULL; - LoadSong(NULL, 0, 1); -#endif -} - void I_SetDigMusicVolume(UINT8 volume) { I_SetMIDIMusicVolume(volume); @@ -1995,4 +1985,4 @@ static void SDLCALL I_FinishMusic(void) if (Msc_Mutex) SDL_UnlockMutex(Msc_Mutex); } #endif -#endif //HAVE_SDL +#endif //HAVE_SDL \ No newline at end of file diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index 18c88d267..295d68680 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -22,12 +22,10 @@ #define HAVE_ZLIB #ifndef _MSC_VER -#ifndef _WII #ifndef _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE #endif #endif -#endif #ifndef _LFS64_LARGEFILE #define _LFS64_LARGEFILE @@ -44,7 +42,6 @@ static FMOD_SYSTEM *fsys; static FMOD_SOUND *music_stream; static FMOD_CHANNEL *music_channel; -static boolean midimode; static UINT8 music_volume, midi_volume, sfx_volume; static INT32 current_track; @@ -446,14 +443,48 @@ void I_SetSfxVolume(UINT8 volume) // MUSIC // +musictype_t I_GetMusicType(void) +{ +#ifdef HAVE_LIBGME + if (gme) + return MU_GME; +#endif + + if (!music_stream) + return MU_NONE; + + FMOD_SOUND_TYPE type; + if (FMOD_Sound_GetFormat(music_stream, &type, NULL, NULL, NULL) == FMOD_OK) + { + switch(type) + { + case FMOD_SOUND_TYPE_WAV: + return MU_WAV; + case FMOD_SOUND_TYPE_MOD: + return MU_MOD; + case FMOD_SOUND_TYPE_MID: + return MU_MID; + case FMOD_SOUND_TYPE_OGGVORBIS: + return MU_OGG; + case FMOD_SOUND_TYPE_MP3: + return MU_MP3; + case FMOD_SOUND_TYPE_FLAC: + return MU_FLAC; + default: + return MU_NONE; + } + } + else + return MU_NONE; +} + void I_InitMusic(void) { } void I_ShutdownMusic(void) { - I_ShutdownDigMusic(); - I_ShutdownMIDIMusic(); + I_StopSong(); } void I_PauseSong(void) @@ -470,17 +501,7 @@ void I_ResumeSong(void) FMR_MUSIC(FMOD_Channel_SetPaused(music_channel, false)); } -void I_InitDigMusic(void) -{ -} - -void I_ShutdownDigMusic(void) -{ - if (!midimode) - I_StopDigSong(); -} - -boolean I_StartDigSong(const char *musicname, boolean looping) +boolean I_LoadSong(char *data, size_t len) { char *data; size_t len; @@ -492,10 +513,7 @@ boolean I_StartDigSong(const char *musicname, boolean looping) lumpnum = W_CheckNumForName(va("D_%s",musicname)); if (lumpnum == LUMPERROR) return false; - midimode = true; } - else - midimode = false; data = (char *)W_CacheLumpNum(lumpnum, PU_MUSIC); len = W_LumpLength(lumpnum); @@ -605,8 +623,6 @@ boolean I_StartDigSong(const char *musicname, boolean looping) { gme_equalizer_t gmeq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; Z_Free(data); // We don't need this anymore. - gme_start_track(gme, 0); - current_track = 0; gme_set_equalizer(gme,&gmeq); fmt.format = FMOD_SOUND_FORMAT_PCM16; fmt.defaultfrequency = 44100; @@ -616,32 +632,21 @@ boolean I_StartDigSong(const char *musicname, boolean looping) fmt.pcmreadcallback = GMEReadCallback; fmt.userdata = gme; FMR(FMOD_System_CreateStream(fsys, NULL, FMOD_OPENUSER | (looping ? FMOD_LOOP_NORMAL : 0), &fmt, &music_stream)); - FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel)); - FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); - FMR(FMOD_Channel_SetPriority(music_channel, 0)); return true; } #endif fmt.length = len; + + FMOD_RESULT e = FMOD_System_CreateStream(fsys, data, FMOD_OPENMEMORY_POINT|(looping ? FMOD_LOOP_NORMAL : 0), &fmt, &music_stream); + if (e != FMOD_OK) { - FMOD_RESULT e = FMOD_System_CreateStream(fsys, data, FMOD_OPENMEMORY_POINT|(looping ? FMOD_LOOP_NORMAL : 0), &fmt, &music_stream); - if (e != FMOD_OK) - { - if (e == FMOD_ERR_FORMAT) - CONS_Alert(CONS_WARNING, "Failed to play music lump %s due to invalid format.\n", W_CheckNameForNum(lumpnum)); - else - FMR(e); - return false; - } + if (e == FMOD_ERR_FORMAT) + CONS_Alert(CONS_WARNING, "Failed to play music lump %s due to invalid format.\n", W_CheckNameForNum(lumpnum)); + else + FMR(e); + return false; } - FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel)); - if (midimode) - FMR(FMOD_Channel_SetVolume(music_channel, midi_volume / 31.0)); - else - FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); - FMR(FMOD_Channel_SetPriority(music_channel, 0)); - current_track = 0; // Try to find a loop point in streaming music formats (ogg, mp3) FMOD_RESULT e; @@ -704,28 +709,15 @@ boolean I_StartDigSong(const char *musicname, boolean looping) return true; } - // No special loop point, but we're playing so it's all good. + // No special loop point return true; } -void I_StopDigSong(void) -{ - if (music_stream) - FMR(FMOD_Sound_Release(music_stream)); - music_stream = NULL; -#ifdef HAVE_LIBGME - if (gme) - gme_delete(gme); - gme = NULL; -#endif - current_track = -1; -} - void I_SetDigMusicVolume(UINT8 volume) { // volume is 0 to 31. music_volume = volume; - if (!midimode && music_stream) + if (I_GetMusicType() != MU_MID && music_stream) FMR_MUSIC(FMOD_Channel_SetVolume(music_channel, volume / 31.0)); } @@ -811,57 +803,55 @@ boolean I_SetSongTrack(INT32 track) // Fuck MIDI. ... Okay fine, you can have your silly D_-only mode. // -void I_InitMIDIMusic(void) -{ -} - -void I_ShutdownMIDIMusic(void) -{ - if (midimode) - I_StopSong(0); -} - void I_SetMIDIMusicVolume(UINT8 volume) { // volume is 0 to 31. midi_volume = volume; - if (midimode && music_stream) + if (I_GetMusicType() != MU_MID && music_stream) FMR_MUSIC(FMOD_Channel_SetVolume(music_channel, volume / 31.0)); } boolean I_PlaySong(boolean looping) { - FMOD_CREATESOUNDEXINFO fmt; - memset(&fmt, 0, sizeof(FMOD_CREATESOUNDEXINFO)); - fmt.cbsize = sizeof(FMOD_CREATESOUNDEXINFO); - fmt.length = len; - FMR(FMOD_System_CreateStream(fsys, (char *)data, FMOD_OPENMEMORY_POINT, &fmt, &music_stream)); - return 1337; -} - -boolean I_PlaySong(INT32 handle, boolean looping) -{ - if (1337 == handle) +#ifdef HAVE_LIBGME + if (gme) { - midimode = true; - if (looping) - FMR(FMOD_Sound_SetMode(music_stream, FMOD_LOOP_NORMAL)); + gme_start_track(gme, 0); + current_track = 0; FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel)); - FMR_MUSIC(FMOD_Channel_SetVolume(music_channel, midi_volume / 31.0)); - FMR_MUSIC(FMOD_Channel_SetPriority(music_channel, 0)); + FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); + FMR(FMOD_Channel_SetPriority(music_channel, 0)); + return true; } +#endif + + FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel)); + if (I_GetMusicType() != MU_MID) + FMR(FMOD_Channel_SetVolume(music_channel, midi_volume / 31.0)); + else + FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); + FMR(FMOD_Channel_SetPriority(music_channel, 0)); + current_track = 0; + return true; } -void I_StopSong(INT32 handle) +void I_StopSong(void) { - I_UnRegisterSong(handle); +#ifdef HAVE_LIBGME + if (gme) + gme_delete(gme); + gme = NULL; +#endif + current_track = -1; + + I_UnloadSong(); } -void I_UnRegisterSong(INT32 handle) +void I_UnloadSong(void) { UNREFERENCED_PARAMETER(handle); if (music_stream) FMR(FMOD_Sound_Release(music_stream)); music_stream = NULL; -} +} \ No newline at end of file From a7ed7b2c90e5dcc2b342adca4227a33a1432d38d Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 23 Aug 2018 11:51:23 -0400 Subject: [PATCH 191/306] Consolidate I_SetDigMusicVolume and I_SetMIDIMusicVolume into one method * In s_sound, they are merged to one method as well, but there are still two separate digvolume and seqvolume variables * Simplified Dig/MidiMusicDisabled in s_sound * Method reordering (cherry picked from commit 701cc5a7dd1dfead87a42ec7558c9fa6a1deb193) --- src/d_netcmd.c | 4 +- src/i_sound.h | 47 ++----- src/s_sound.c | 161 +++++++++++++++-------- src/s_sound.h | 28 +++- src/sdl/mixer_sound.c | 298 +++++++++++++++--------------------------- 5 files changed, 242 insertions(+), 296 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index bf26ca61a..ab3201c5c 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3963,11 +3963,9 @@ static void Command_RestartAudio_f(void) // These must be called or no sound and music until manually set. I_SetSfxVolume(cv_soundvolume.value); - I_SetDigMusicVolume(cv_digmusicvolume.value); - I_SetMIDIMusicVolume(cv_midimusicvolume.value); + S_SetMusicVolume(cv_digmusicvolume.value, cv_midimusicvolume.value); if (Playing()) // Gotta make sure the player is in a level P_RestoreMusic(&players[consoleplayer]); - } /** Quits a game and returns to the title screen. diff --git a/src/i_sound.h b/src/i_sound.h index 0fe62d5eb..1d4d6ff72 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -140,7 +140,7 @@ void I_ShutdownMusic(void); \return void */ -void I_PauseSong(INT32 handle); +void I_PauseSong(void); /** \brief RESUME game handling @@ -148,20 +148,12 @@ void I_PauseSong(INT32 handle); \return void */ -void I_ResumeSong(INT32 handle); +void I_ResumeSong(void); // // MIDI I/O // -/** \brief Startup the MIDI music system -*/ -void I_InitMIDIMusic(void); - -/** \brief Shutdown the MIDI music system -*/ -void I_ShutdownMIDIMusic(void); - /** \brief The I_SetMIDIMusicVolume function \param volume volume to set at @@ -179,7 +171,7 @@ void I_SetMIDIMusicVolume(UINT8 volume); \todo Remove this */ -INT32 I_RegisterSong(void *data, size_t len); +boolean I_LoadSong(char *data, size_t len); /** \brief Called by anything that wishes to start music @@ -190,7 +182,7 @@ INT32 I_RegisterSong(void *data, size_t len); \todo pass music name, not handle */ -boolean I_PlaySong(INT32 handle, boolean looping); +boolean I_PlaySong(boolean looping); /** \brief Stops a song over 3 seconds @@ -199,46 +191,25 @@ boolean I_PlaySong(INT32 handle, boolean looping); /todo drop handle */ -void I_StopSong(INT32 handle); +void I_StopSong(void); -/** \brief See ::I_RegisterSong, then think backwards +/** \brief See ::I_LoadSong, then think backwards \param handle song handle - \sa I_RegisterSong + \sa I_LoadSong \todo remove midi handle */ -void I_UnRegisterSong(INT32 handle); +void I_UnloadSong(void); // // DIGMUSIC I/O // -/** \brief Startup the music system -*/ -void I_InitDigMusic(void); - -/** \brief Shutdown the music system -*/ -void I_ShutdownDigMusic(void); - boolean I_SetSongSpeed(float speed); boolean I_SetSongTrack(INT32 track); -/** \brief The I_StartDigSong function - - \param musicname music lump name - \param looping if true, loop the song - - \return if true, song playing -*/ -boolean I_StartDigSong(const char *musicname, boolean looping); - -/** \brief stop non-MIDI song -*/ -void I_StopDigSong(void); - /** \brief The I_SetDigMusicVolume function \param volume volume to set at @@ -297,4 +268,4 @@ void I_PlayCD(UINT8 track, UINT8 looping); */ boolean I_SetVolumeCD(INT32 volume); -#endif +#endif \ No newline at end of file diff --git a/src/s_sound.c b/src/s_sound.c index 279f0dc6d..a1c53acd2 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1180,28 +1180,71 @@ const char *compat_special_music_slots[16] = #define music_playing (music_name[0]) // String is empty if no music is playing static char music_name[7]; // up to 6-character name -static lumpnum_t music_lumpnum; // lump number of music (used??) -static void *music_data; // music raw data -static INT32 music_handle; // once registered, the handle for the music +static boolean mus_paused = 0; // whether songs are mus_paused -static boolean mus_paused = 0; // whether songs are mus_paused +/// ------------------------ +/// Music Status +/// ------------------------ -static boolean S_MIDIMusic(const char *mname, boolean looping) +boolean S_DigMusicDisabled() +{ + return (nodigimusic || digital_disabled); +} + +boolean S_MIDIMusicDisabled() +{ + return (nomidimusic || music_disabled); +} + +boolean S_MusicDisabled() +{ + return ( + (nodigimusic && nomidimusic) || + (music_disabled && digital_disabled) || + (nodigimusic && music_disabled) || + (nomidimusic && digital_disabled) + ); +} + +/// ------------------------ +/// Music Properties +/// ------------------------ + +boolean S_SpeedMusic(float speed) +{ + return I_SetSongSpeed(speed); +} + +/// ------------------------ +/// Music Routines +/// ------------------------ + +static boolean S_LoadMusic(const char *mname) { lumpnum_t mlumpnum; void *mdata; - INT32 mhandle; - if (nomidimusic || music_disabled) - return false; // didn't search. - - if (W_CheckNumForName(va("d_%s", mname)) == LUMPERROR) + if (S_MusicDisabled()) return false; - mlumpnum = W_GetNumForName(va("d_%s", mname)); + + if (S_DigMusicDisabled()) + { + if (W_CheckNumForName(va("d_%s", mname)) == LUMPERROR) + return false; + mlumpnum = W_GetNumForName(va("d_%s", mname)); + } + else + { + if (W_CheckNumForName(va("o_%s", mname)) != LUMPERROR) + mlumpnum = W_GetNumForName(va("o_%s", mname)); + else if (W_CheckNumForName(va("d_%s", mname)) != LUMPERROR) + mlumpnum = W_GetNumForName(va("d_%s", mname)); + else + return false; + } // load & register it mdata = W_CacheLumpNum(mlumpnum, PU_MUSIC); - mhandle = I_RegisterSong(mdata, W_LumpLength(mlumpnum)); #ifdef MUSSERV if (msg_id != -1) @@ -1215,16 +1258,20 @@ static boolean S_MIDIMusic(const char *mname, boolean looping) } #endif - // play it - if (!I_PlaySong(mhandle, looping)) + if (I_LoadSong(mdata, W_LumpLength(mlumpnum))) + { + strncpy(music_name, mname, 7); + music_name[6] = 0; + return true; + } + else return false; +} - strncpy(music_name, mname, 7); - music_name[6] = 0; - music_lumpnum = mlumpnum; - music_data = mdata; - music_handle = mhandle; - return true; +static void S_UnloadMusic(void) +{ + I_UnloadSong(); + music_name[0] = 0; } static boolean S_PlayMusic(boolean looping) @@ -1232,9 +1279,13 @@ static boolean S_PlayMusic(boolean looping) if (nodigimusic || digital_disabled) return false; // try midi - if (!I_StartDigSong(mname, looping)) + if (!I_PlaySong(looping)) + { + S_UnloadMusic(); return false; + } + S_InitMusicVolume(); // switch between digi and sequence volume return true; } @@ -1244,7 +1295,7 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) S_ClearSfx(); #endif - if ((nomidimusic || music_disabled) && (nodigimusic || digital_disabled)) + if (S_MusicDisabled()) return; // No Music (empty string) @@ -1273,60 +1324,55 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) I_SetSongTrack(mflags & MUSIC_TRACKMASK); } -boolean S_SpeedMusic(float speed) -{ - return I_SetSongSpeed(speed); -} - void S_StopMusic(void) { if (!music_playing) return; if (mus_paused) - I_ResumeSong(music_handle); - - if (!nodigimusic) - I_StopDigSong(); + I_ResumeSong(); S_SpeedMusic(1.0f); - I_StopSong(music_handle); - I_UnRegisterSong(music_handle); + I_StopSong(); + I_UnloadSong(); #ifndef HAVE_SDL //SDL uses RWOPS Z_ChangeTag(music_data, PU_CACHE); #endif - music_data = NULL; music_name[0] = 0; } -void S_SetDigMusicVolume(INT32 volume) +void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume) { - if (volume < 0 || volume > 31) - CONS_Alert(CONS_WARNING, "musicvolume should be between 0-31\n"); + if (digvolume < 0) + digvolume = cv_digmusicvolume.value; + if (seqvolume < 0) + seqvolume = cv_midimusicvolume.value; - CV_SetValue(&cv_digmusicvolume, volume&31); + if (digvolume < 0 || digvolume > 31) + CONS_Alert(CONS_WARNING, "digmusicvolume should be between 0-31\n"); + CV_SetValue(&cv_digmusicvolume, digvolume&31); actualdigmusicvolume = cv_digmusicvolume.value; //check for change of var -#ifdef DJGPPDOS - I_SetDigMusicVolume(31); // Trick for buggy dos drivers. Win32 doesn't need this. -#endif - I_SetDigMusicVolume(volume&31); -} - -void S_SetMIDIMusicVolume(INT32 volume) -{ - if (volume < 0 || volume > 31) - CONS_Alert(CONS_WARNING, "musicvolume should be between 0-31\n"); - - CV_SetValue(&cv_midimusicvolume, volume&0x1f); + if (digvolume < 0 || digvolume > 31) + CONS_Alert(CONS_WARNING, "midimusicvolume should be between 0-31\n"); + CV_SetValue(&cv_midimusicvolume, seqvolume&31); actualmidimusicvolume = cv_midimusicvolume.value; //check for change of var #ifdef DJGPPDOS - I_SetMIDIMusicVolume(31); // Trick for buggy dos drivers. Win32 doesn't need this. + digvolume = seqvolume = 31; #endif - I_SetMIDIMusicVolume(volume&0x1f); + + switch(I_GetMusicType()) + { + case MU_MID: + case MU_MOD: + case MU_GME: + I_SetMusicVolume(seqvolume&31); + default: + I_SetMusicVolume(digvolume&31); + } } /// ------------------------ @@ -1346,8 +1392,7 @@ void S_Init(INT32 sfxVolume, INT32 digMusicVolume, INT32 midiMusicVolume) return; S_SetSfxVolume(sfxVolume); - S_SetDigMusicVolume(digMusicVolume); - S_SetMIDIMusicVolume(midiMusicVolume); + S_SetMusicVolume(digMusicVolume, midiMusicVolume); SetChannelsNum(); @@ -1403,11 +1448,11 @@ void S_Start(void) void S_PauseAudio(void) { if (!nodigimusic) - I_PauseSong(0); + I_PauseSong(); if (music_playing && !mus_paused) { - I_PauseSong(music_handle); + I_PauseSong(); mus_paused = true; } @@ -1422,11 +1467,11 @@ void S_PauseAudio(void) void S_ResumeAudio(void) { if (!nodigimusic) - I_ResumeSong(0); + I_ResumeSong(); else if (music_playing && mus_paused) { - I_ResumeSong(music_handle); + I_ResumeSong(); mus_paused = false; } diff --git a/src/s_sound.h b/src/s_sound.h index 39ec769a6..bce3ab8bb 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -97,6 +97,25 @@ void S_StartSoundAtVolume(const void *origin, sfxenum_t sound_id, INT32 volume); // Stop sound for thing at void S_StopSound(void *origin); +// +// Music Status +// + +boolean S_DigMusicDisabled(); +boolean S_MIDIMusicDisabled(); +boolean S_MusicDisabled(); + +// +// Music Properties +// + +// Set Speed of Music +boolean S_SpeedMusic(float speed); + +// +// Music Routines +// + // Start music track, arbitrary, given its name, and set whether looping // note: music flags 12 bits for tracknum (gme, other formats with more than one track) // 13-15 aren't used yet @@ -104,9 +123,6 @@ void S_StopSound(void *origin); #define S_ChangeMusicInternal(a,b) S_ChangeMusic(a,0,b) void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping); -// Set Speed of Music -boolean S_SpeedMusic(float speed); - // Stops the music. void S_StopMusic(void); @@ -121,9 +137,11 @@ void S_UpdateSounds(void); FUNCMATH fixed_t S_CalculateSoundDistance(fixed_t px1, fixed_t py1, fixed_t pz1, fixed_t px2, fixed_t py2, fixed_t pz2); -void S_SetDigMusicVolume(INT32 volume); -void S_SetMIDIMusicVolume(INT32 volume); void S_SetSfxVolume(INT32 volume); +void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume); +#define S_SetDigMusicVolume(a) S_SetMusicVolume(a,-1) +#define S_SetMIDIMusicVolume(a) S_SetMusicVolume(-1,a) +#define S_InitMusicVolume() S_SetMusicVolume(-1,-1) INT32 S_OriginPlaying(void *origin); INT32 S_IdPlaying(sfxenum_t id); diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 0888d5d31..457f74f95 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -483,6 +483,10 @@ static void mix_gme(void *udata, Uint8 *stream, int len) FUNCMATH void I_InitMusic(void) { +#ifdef HAVE_LIBGME + gme = NULL; + current_track = -1; +#endif } void I_ShutdownMusic(void) @@ -502,16 +506,14 @@ void I_ShutdownMusic(void) music = NULL; } -void I_PauseSong(INT32 handle) +void I_PauseSong(void) { - (void)handle; Mix_PauseMusic(); songpaused = true; } -void I_ResumeSong(INT32 handle) +void I_ResumeSong(void) { - (void)handle; Mix_ResumeMusic(); songpaused = false; } @@ -520,59 +522,66 @@ void I_ResumeSong(INT32 handle) // Digital Music // -void I_SetDigMusicVolume(UINT8 volume) -{ - music_volume = volume; - if (I_GetMusicType() == MU_MID || !music) - return; - Mix_VolumeMusic((UINT32)volume*128/31); -} - boolean I_SetSongSpeed(float speed) { -#ifdef HAVE_LIBGME - gme = NULL; - current_track = -1; -#endif -} - -void I_ShutdownDigMusic(void) -{ - if (midimode) - return; + if (speed > 250.0f) + speed = 250.0f; //limit speed up to 250x #ifdef HAVE_LIBGME if (gme) { - Mix_HookMusic(NULL, NULL); - gme_delete(gme); - gme = NULL; + SDL_LockAudio(); + gme_set_tempo(gme, speed); + SDL_UnlockAudio(); + return true; } +#else + (void)speed; #endif - if (!music) - return; - Mix_HookMusicFinished(NULL); - Mix_FreeMusic(music); - music = NULL; + return false; } -boolean I_StartDigSong(const char *musicname, boolean looping) +boolean I_SetSongTrack(int track) { - char *data; - size_t len; - lumpnum_t lumpnum = W_CheckNumForName(va("O_%s",musicname)); +#ifdef HAVE_LIBGME + if (current_track == track) + return false; + // If the specified track is within the number of tracks playing, then change it + if (gme) + { + SDL_LockAudio(); + if (track >= 0 + && track < gme_track_count(gme)) + { + gme_err_t gme_e = gme_start_track(gme, track); + if (gme_e != NULL) + { + CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); + return false; + } + current_track = track; + SDL_UnlockAudio(); + return true; + } + SDL_UnlockAudio(); + return false; + } +#endif + (void)track; + return false; +} + +// +// MIDI Music +// + +boolean I_LoadSong(char *data, size_t len) +{ I_Assert(!music); #ifdef HAVE_LIBGME I_Assert(!gme); #endif - if (lumpnum == LUMPERROR) - return false; - midimode = false; - - data = (char *)W_CacheLumpNum(lumpnum, PU_MUSIC); - len = W_LumpLength(lumpnum); - #ifdef HAVE_LIBGME if ((UINT8)data[0] == 0x1F && (UINT8)data[1] == 0x8B) @@ -663,8 +672,6 @@ boolean I_StartDigSong(const char *musicname, boolean looping) else if (!gme_open_data(data, len, &gme, 44100)) { gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; - gme_start_track(gme, 0); - current_track = 0; gme_set_equalizer(gme, &eq); Mix_HookMusic(mix_gme, gme); return true; @@ -675,48 +682,62 @@ boolean I_StartDigSong(const char *musicname, boolean looping) if (!music) { CONS_Alert(CONS_ERROR, "Mix_LoadMUS_RW: %s\n", Mix_GetError()); - return true; + return false; } // Find the OGG loop point. loop_point = 0.0f; - if (looping) + + const char *key1 = "LOOP"; + const char *key2 = "POINT="; + const char *key3 = "MS="; + const size_t key1len = strlen(key1); + const size_t key2len = strlen(key2); + const size_t key3len = strlen(key3); + char *p = data; + while ((UINT32)(p - data) < len) { - const char *key1 = "LOOP"; - const char *key2 = "POINT="; - const char *key3 = "MS="; - const size_t key1len = strlen(key1); - const size_t key2len = strlen(key2); - const size_t key3len = strlen(key3); - char *p = data; - while ((UINT32)(p - data) < len) + if (strncmp(p++, key1, key1len)) + continue; + p += key1len-1; // skip OOP (the L was skipped in strncmp) + if (!strncmp(p, key2, key2len)) // is it LOOPPOINT=? { - if (strncmp(p++, key1, key1len)) - continue; - p += key1len-1; // skip OOP (the L was skipped in strncmp) - if (!strncmp(p, key2, key2len)) // is it LOOPPOINT=? - { - p += key2len; // skip POINT= - loop_point = (float)((44.1L+atoi(p)) / 44100.0L); // LOOPPOINT works by sample count. - // because SDL_Mixer is USELESS and can't even tell us - // something simple like the frequency of the streaming music, - // we are unfortunately forced to assume that ALL MUSIC is 44100hz. - // This means a lot of tracks that are only 22050hz for a reasonable downloadable file size will loop VERY badly. - } - else if (!strncmp(p, key3, key3len)) // is it LOOPMS=? - { - p += key3len; // skip MS= - loop_point = (float)(atoi(p) / 1000.0L); // LOOPMS works by real time, as miliseconds. - // Everything that uses LOOPMS will work perfectly with SDL_Mixer. - } - // Neither?! Continue searching. + p += key2len; // skip POINT= + loop_point = (float)((44.1L+atoi(p)) / 44100.0L); // LOOPPOINT works by sample count. + // because SDL_Mixer is USELESS and can't even tell us + // something simple like the frequency of the streaming music, + // we are unfortunately forced to assume that ALL MUSIC is 44100hz. + // This means a lot of tracks that are only 22050hz for a reasonable downloadable file size will loop VERY badly. } + else if (!strncmp(p, key3, key3len)) // is it LOOPMS=? + { + p += key3len; // skip MS= + loop_point = (float)(atoi(p) / 1000.0L); // LOOPMS works by real time, as miliseconds. + // Everything that uses LOOPMS will work perfectly with SDL_Mixer. + } + // Neither?! Continue searching. } + return true; +} + +boolean I_PlaySong(boolean looping) +{ + if (!music) + return false; +#ifdef HAVE_GME + if (gme) + { + gme_start_track(gme, 0); + current_track = 0; + return true; + } +#endif + if (Mix_PlayMusic(music, looping && loop_point == 0.0f ? -1 : 0) == -1) { CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError()); - return true; + return false; } Mix_VolumeMusic((UINT32)music_volume*128/31); @@ -725,7 +746,7 @@ boolean I_StartDigSong(const char *musicname, boolean looping) return true; } -void I_StopDigSong(void) +void I_StopSong(void) { #ifdef HAVE_LIBGME if (gme) @@ -744,132 +765,25 @@ void I_StopDigSong(void) music = NULL; } -void I_SetDigMusicVolume(UINT8 volume) +void I_SetMusicVolume(UINT8 volume) { - music_volume = volume; - if (midimode || !music) - return; - Mix_VolumeMusic((UINT32)volume*128/31); -} - -boolean I_SetSongSpeed(float speed) -{ - if (speed > 250.0f) - speed = 250.0f; //limit speed up to 250x -#ifdef HAVE_LIBGME - if (gme) - { - SDL_LockAudio(); - gme_set_tempo(gme, speed); - SDL_UnlockAudio(); - return true; - } -#else - (void)speed; -#endif - return false; -} - -boolean I_SetSongTrack(int track) -{ -#ifdef HAVE_LIBGME - if (current_track == track) - return false; - - // If the specified track is within the number of tracks playing, then change it - if (gme) - { - SDL_LockAudio(); - if (track >= 0 - && track < gme_track_count(gme)) - { - gme_err_t gme_e = gme_start_track(gme, track); - if (gme_e != NULL) - { - CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); - return false; - } - current_track = track; - SDL_UnlockAudio(); - return true; - } - SDL_UnlockAudio(); - return false; - } -#endif - (void)track; - return false; -} - -// -// MIDI Music -// - -FUNCMATH void I_InitMIDIMusic(void) -{ -} - -void I_ShutdownMIDIMusic(void) -{ - if (!midimode || !music) - return; - Mix_FreeMusic(music); - music = NULL; -} - -void I_SetMIDIMusicVolume(UINT8 volume) -{ - // HACK: Until we stop using native MIDI, - // disable volume changes - (void)volume; - midi_volume = 31; - //midi_volume = volume; - - if (I_GetMusicType() != MU_MID || !music) - return; - Mix_VolumeMusic((UINT32)midi_volume*128/31); -} - -INT32 I_RegisterSong(void *data, size_t len) -{ - music = Mix_LoadMUS_RW(SDL_RWFromMem(data, len), SDL_FALSE); if (!music) - { - CONS_Alert(CONS_ERROR, "Mix_LoadMUS_RW: %s\n", Mix_GetError()); - return -1; - } - return 1337; -} - -boolean I_PlaySong(INT32 handle, boolean looping) -{ - (void)handle; - - midimode = true; - - if (Mix_PlayMusic(music, looping ? -1 : 0) == -1) - { - CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError()); - return false; - } - - Mix_VolumeMusic((UINT32)midi_volume*128/31); - return true; -} - -void I_StopSong(INT32 handle) -{ - if (!midimode || !music) return; - (void)handle; - Mix_HaltMusic(); + if (I_GetMusicType() == MU_MID) + // HACK: Until we stop using native MIDI, + // disable volume changes + music_volume = 31; + else + music_volume = volume; + + Mix_VolumeMusic((UINT32)music_volume*128/31); } -void I_UnRegisterSong(INT32 handle) +void I_UnloadSong(void) { Mix_FreeMusic(music); music = NULL; } -#endif +#endif \ No newline at end of file From e58a8f4fe18609531a5eb06e1d1b302b6cf6c197 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 23 Aug 2018 11:54:58 -0400 Subject: [PATCH 192/306] Consolidate I_SetDigMusicVolume and I_SetMIDIMusicVolume other targets (cherry picked from commit 9fb9386f84b3739fe765a78bcb9683eb7e98bc36) --- src/android/i_sound.c | 7 +------ src/djgppdos/i_sound.c | 12 +----------- src/dummy/i_sound.c | 7 +------ src/sdl/sdl_sound.c | 7 +------ src/win32/win_snd.c | 22 ++++++++++------------ 5 files changed, 14 insertions(+), 41 deletions(-) diff --git a/src/android/i_sound.c b/src/android/i_sound.c index c3fc038e5..80b90d2f7 100644 --- a/src/android/i_sound.c +++ b/src/android/i_sound.c @@ -92,7 +92,7 @@ boolean I_LoadSong(char *data, size_t len) return -1; } -void I_SetMIDIMusicVolume(INT32 volume) +void I_SetMusicVolume(INT32 volume) { (void)volume; } @@ -120,11 +120,6 @@ void I_UnloadSong(void) UINT8 digmusic_started = 0; -void I_SetDigMusicVolume(INT32 volume) -{ - (void)volume; -} - boolean I_SetSongSpeed(float speed) { (void)speed; diff --git a/src/djgppdos/i_sound.c b/src/djgppdos/i_sound.c index 4c8ceb20c..e66bf8e23 100644 --- a/src/djgppdos/i_sound.c +++ b/src/djgppdos/i_sound.c @@ -140,7 +140,7 @@ void I_SetSfxVolume(INT32 volume) set_volume (Volset(volume),-1); } -void I_SetMIDIMusicVolume(INT32 volume) +void I_SetMusicVolume(INT32 volume) { if (nomidimusic) return; @@ -503,16 +503,6 @@ boolean I_LoadSong(char *data, size_t len) return 1; } -void I_SetDigMusicVolume(INT32 volume) -{ - volume = 0; - if (nodigimusic) - return; - - // Now set volume on output device. -// CONS_Printf("Digital music not yet supported under DOS.\n"); -} - boolean I_SetSongSpeed(float speed) { (void)speed; diff --git a/src/dummy/i_sound.c b/src/dummy/i_sound.c index 60cf51f73..f82bf00da 100644 --- a/src/dummy/i_sound.c +++ b/src/dummy/i_sound.c @@ -70,7 +70,7 @@ void I_InitMusic(void){} void I_ShutdownMusic(void){} -void I_SetMIDIMusicVolume(UINT8 volume) +void I_SetMusicVolume(UINT8 volume) { (void)volume; } @@ -117,11 +117,6 @@ void I_UnloadSong(void) // DIGMUSIC I/O // -void I_SetDigMusicVolume(UINT8 volume) -{ - (void)volume; -} - boolean I_SetSongSpeed(float speed) { (void)speed; diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index b729d4d89..5f92cde10 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -1702,7 +1702,7 @@ boolean I_LoadSong(char *data, size_t len) return false; } -void I_SetMIDIMusicVolume(UINT8 volume) +void I_SetMusicVolume(UINT8 volume) { #ifdef HAVE_MIXER if ((nomidimusic && nodigimusic) || !musicStarted) @@ -1951,11 +1951,6 @@ static void I_StopGME(void) #endif } -void I_SetDigMusicVolume(UINT8 volume) -{ - I_SetMIDIMusicVolume(volume); -} - boolean I_SetSongSpeed(float speed) { diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index 295d68680..bfa43d087 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -713,14 +713,6 @@ boolean I_LoadSong(char *data, size_t len) return true; } -void I_SetDigMusicVolume(UINT8 volume) -{ - // volume is 0 to 31. - music_volume = volume; - if (I_GetMusicType() != MU_MID && music_stream) - FMR_MUSIC(FMOD_Channel_SetVolume(music_channel, volume / 31.0)); -} - boolean I_SetSongSpeed(float speed) { FMOD_RESULT e; @@ -803,12 +795,18 @@ boolean I_SetSongTrack(INT32 track) // Fuck MIDI. ... Okay fine, you can have your silly D_-only mode. // -void I_SetMIDIMusicVolume(UINT8 volume) +void I_SetMusicVolume(UINT8 volume) { + if (!music_stream) + return; + // volume is 0 to 31. - midi_volume = volume; - if (I_GetMusicType() != MU_MID && music_stream) - FMR_MUSIC(FMOD_Channel_SetVolume(music_channel, volume / 31.0)); + if (I_GetMusicType() == MU_MID) + music_volume = 31; // windows bug hack + else + music_volume = volume; + + FMR_MUSIC(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); } boolean I_PlaySong(boolean looping) From 011a043dbaaa5706be45f3e900a3d2f031239217 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 23 Aug 2018 12:30:47 -0400 Subject: [PATCH 193/306] Refactoring, music statues * S_Init -> S_InitSfxChannels because it did mostly SFX anyway * S_MusicPlaying, S_MusicPaused, S_MusicName, S_MusicExists new status methods * I_MusicPlaying, I_MusicPaused (cherry picked from commit f5f0b5e76c2fd405c8cc895dde653c5ed2652622) --- src/d_main.c | 4 +- src/i_sound.h | 2 + src/m_menu.c | 6 +- src/s_sound.c | 182 +++++++++++++++++++++--------------------- src/s_sound.h | 17 ++-- src/sdl/mixer_sound.c | 10 +++ 6 files changed, 121 insertions(+), 100 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index df3398752..f2da8586c 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1217,7 +1217,7 @@ void D_SRB2Main(void) } else { - CONS_Printf("S_Init(): Setting up sound.\n"); + CONS_Printf("S_InitSfxChannels(): Setting up sound channels.\n"); } if (M_CheckParm("-nosound")) nosound = true; @@ -1232,7 +1232,7 @@ void D_SRB2Main(void) } I_StartupSound(); I_InitMusic(); - S_Init(cv_soundvolume.value, cv_digmusicvolume.value, cv_midimusicvolume.value); + S_InitSfxChannels(cv_soundvolume.value); CONS_Printf("ST_Init(): Init status bar.\n"); ST_Init(); diff --git a/src/i_sound.h b/src/i_sound.h index 1d4d6ff72..901e6c284 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -125,6 +125,8 @@ void I_SetSfxVolume(UINT8 volume); // musictype_t I_GetMusicType(void); +boolean I_MusicPlaying(void); +boolean I_MusicPaused(void); /** \brief Init the music systems */ diff --git a/src/m_menu.c b/src/m_menu.c index 79ac6800b..82242c0c1 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6955,7 +6955,7 @@ static void M_ToggleSFX(void) nosound = false; I_StartupSound(); if (nosound) return; - S_Init(cv_soundvolume.value, cv_digmusicvolume.value, cv_midimusicvolume.value); + S_InitSfxChannels(cv_soundvolume.value); M_StartMessage(M_GetText("SFX Enabled\n"), NULL, MM_NOTHING); } else @@ -6981,7 +6981,7 @@ static void M_ToggleDigital(void) nodigimusic = false; I_InitDigMusic(); if (nodigimusic) return; - S_Init(cv_soundvolume.value, cv_digmusicvolume.value, cv_midimusicvolume.value); + S_InitSfxChannels(cv_soundvolume.value); S_StopMusic(); S_ChangeMusicInternal("lclear", false); M_StartMessage(M_GetText("Digital Music Enabled\n"), NULL, MM_NOTHING); @@ -7009,7 +7009,7 @@ static void M_ToggleMIDI(void) nomidimusic = false; I_InitMIDIMusic(); if (nomidimusic) return; - S_Init(cv_soundvolume.value, cv_digmusicvolume.value, cv_midimusicvolume.value); + S_InitSfxChannels(cv_soundvolume.value); S_ChangeMusicInternal("lclear", false); M_StartMessage(M_GetText("MIDI Music Enabled\n"), NULL, MM_NOTHING); } diff --git a/src/s_sound.c b/src/s_sound.c index a1c53acd2..e035c4192 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1151,6 +1151,43 @@ void S_StartSoundName(void *mo, const char *soundname) S_StartSound(mo, soundnum); } +// +// Initializes sound stuff, including volume +// Sets channels, SFX volume, +// allocates channel buffer, sets S_sfx lookup. +// +void S_InitSfxChannels(INT32 sfxVolume) +{ + INT32 i; + + if (dedicated) + return; + + S_SetSfxVolume(sfxVolume); + + SetChannelsNum(); + + // Note that sounds have not been cached (yet). + for (i = 1; i < NUMSFX; i++) + { + S_sfx[i].usefulness = -1; // for I_GetSfx() + S_sfx[i].lumpnum = LUMPERROR; + } + + // precache sounds if requested by cmdline, or precachesound var true + if (!nosound && (M_CheckParm("-precachesound") || precachesound.value)) + { + // Initialize external data (all sounds) at start, keep static. + CONS_Printf(M_GetText("Loading sounds... ")); + + for (i = 1; i < NUMSFX; i++) + if (S_sfx[i].name) + S_sfx[i].data = I_GetSfx(&S_sfx[i]); + + CONS_Printf(M_GetText(" pre-cached all sound data\n")); + } +} + /// ------------------------ /// Music /// ------------------------ @@ -1177,10 +1214,7 @@ const char *compat_special_music_slots[16] = }; #endif -#define music_playing (music_name[0]) // String is empty if no music is playing - static char music_name[7]; // up to 6-character name -static boolean mus_paused = 0; // whether songs are mus_paused /// ------------------------ /// Music Status @@ -1206,6 +1240,29 @@ boolean S_MusicDisabled() ); } +boolean S_MusicPlaying(void) +{ + return I_MusicPlaying(); +} + +boolean S_MusicPaused(void) +{ + return I_MusicPaused(); +} + +const char *S_MusicName(void) +{ + return music_name; +} + +boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi) +{ + return ( + (checkDigi ? W_CheckNumForName(va("O_%s", mname)) != LUMPERROR : false) + || (checkMIDI ? W_CheckNumForName(va("D_%s", mname)) != LUMPERROR : false) + ); +} + /// ------------------------ /// Music Properties /// ------------------------ @@ -1229,15 +1286,15 @@ static boolean S_LoadMusic(const char *mname) if (S_DigMusicDisabled()) { - if (W_CheckNumForName(va("d_%s", mname)) == LUMPERROR) + if (!S_MIDIExists(mname)) return false; mlumpnum = W_GetNumForName(va("d_%s", mname)); } else { - if (W_CheckNumForName(va("o_%s", mname)) != LUMPERROR) + if (S_DigExists(mname)) mlumpnum = W_GetNumForName(va("o_%s", mname)); - else if (W_CheckNumForName(va("d_%s", mname)) != LUMPERROR) + else if (S_MIDIExists(mname)) mlumpnum = W_GetNumForName(va("d_%s", mname)); else return false; @@ -1326,10 +1383,10 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) void S_StopMusic(void) { - if (!music_playing) + if (!I_MusicPlaying()) return; - if (mus_paused) + if (I_MusicPaused()) I_ResumeSong(); S_SpeedMusic(1.0f); @@ -1343,6 +1400,31 @@ void S_StopMusic(void) music_name[0] = 0; } +// +// Stop and resume music, during game PAUSE. +// +void S_PauseAudio(void) +{ + if (I_MusicPlaying() && !I_MusicPaused()) + I_PauseSong(); + + // pause cd music +#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) + I_PauseCD(); +#else + I_StopCD(); +#endif +} + +void S_ResumeAudio(void) +{ + if (I_MusicPlaying() && I_MusicPaused()) + I_ResumeSong(); + + // resume cd music + I_ResumeCD(); +} + void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume) { if (digvolume < 0) @@ -1355,7 +1437,7 @@ void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume) CV_SetValue(&cv_digmusicvolume, digvolume&31); actualdigmusicvolume = cv_digmusicvolume.value; //check for change of var - if (digvolume < 0 || digvolume > 31) + if (seqvolume < 0 || seqvolume > 31) CONS_Alert(CONS_WARNING, "midimusicvolume should be between 0-31\n"); CV_SetValue(&cv_midimusicvolume, seqvolume&31); actualmidimusicvolume = cv_midimusicvolume.value; //check for change of var @@ -1375,52 +1457,11 @@ void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume) } } + /// ------------------------ /// Init & Others /// ------------------------ -// -// Initializes sound stuff, including volume -// Sets channels, SFX and music volume, -// allocates channel buffer, sets S_sfx lookup. -// -void S_Init(INT32 sfxVolume, INT32 digMusicVolume, INT32 midiMusicVolume) -{ - INT32 i; - - if (dedicated) - return; - - S_SetSfxVolume(sfxVolume); - S_SetMusicVolume(digMusicVolume, midiMusicVolume); - - SetChannelsNum(); - - // no sounds are playing, and they are not mus_paused - mus_paused = 0; - - // Note that sounds have not been cached (yet). - for (i = 1; i < NUMSFX; i++) - { - S_sfx[i].usefulness = -1; // for I_GetSfx() - S_sfx[i].lumpnum = LUMPERROR; - } - - // precache sounds if requested by cmdline, or precachesound var true - if (!nosound && (M_CheckParm("-precachesound") || precachesound.value)) - { - // Initialize external data (all sounds) at start, keep static. - CONS_Printf(M_GetText("Loading sounds... ")); - - for (i = 1; i < NUMSFX; i++) - if (S_sfx[i].name) - S_sfx[i].data = I_GetSfx(&S_sfx[i]); - - CONS_Printf(M_GetText(" pre-cached all sound data\n")); - } -} - - // // Per level startup code. // Kills playing sounds at start of level, @@ -1435,46 +1476,7 @@ void S_Start(void) mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK); } - mus_paused = 0; - if (cv_resetmusic.value) S_StopMusic(); S_ChangeMusic(mapmusname, mapmusflags, true); } - -// -// Stop and resume music, during game PAUSE. -// -void S_PauseAudio(void) -{ - if (!nodigimusic) - I_PauseSong(); - - if (music_playing && !mus_paused) - { - I_PauseSong(); - mus_paused = true; - } - - // pause cd music -#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) - I_PauseCD(); -#else - I_StopCD(); -#endif -} - -void S_ResumeAudio(void) -{ - if (!nodigimusic) - I_ResumeSong(); - else - if (music_playing && mus_paused) - { - I_ResumeSong(); - mus_paused = false; - } - - // resume cd music - I_ResumeCD(); -} diff --git a/src/s_sound.h b/src/s_sound.h index bce3ab8bb..9a3f2805c 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -69,9 +69,9 @@ void S_RegisterSoundStuff(void); // // Initializes sound stuff, including volume -// Sets channels, SFX and music volume, allocates channel buffer, sets S_sfx lookup. +// Sets channels, SFX, allocates channel buffer, sets S_sfx lookup. // -void S_Init(INT32 sfxVolume, INT32 digMusicVolume, INT32 midiMusicVolume); +void S_InitSfxChannels(INT32 sfxVolume); // // Per level startup code. @@ -101,9 +101,16 @@ void S_StopSound(void *origin); // Music Status // -boolean S_DigMusicDisabled(); -boolean S_MIDIMusicDisabled(); -boolean S_MusicDisabled(); +boolean S_DigMusicDisabled(void); +boolean S_MIDIMusicDisabled(void); +boolean S_MusicDisabled(void); +boolean S_MusicPlaying(void); +boolean S_MusicPaused(void); +const char *S_MusicName(void); +boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi); +#define S_DigExists(a) S_MusicExists(a, false, true) +#define S_MIDIExists(a) S_MusicExists(a, true, false) + // // Music Properties diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 457f74f95..1384f1da0 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -453,6 +453,16 @@ musictype_t I_GetMusicType(void) return (musictype_t)Mix_GetMusicType(music); } +boolean I_MusicPlaying(void) +{ + return (boolean)music; +} + +boolean I_MusicPaused(void) +{ + return songpaused; +} + // Music hooks static void music_loop(void) { From 44557d9c9d6b6ea3df722987bf778f847193db90 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 23 Aug 2018 12:31:01 -0400 Subject: [PATCH 194/306] I_MusicPlaying, I_MusicPaused other targets (cherry picked from commit d5ec38815968e267aceb59a48a6cb6d3292c0b69) --- src/android/i_sound.c | 10 ++++++++++ src/djgppdos/i_sound.c | 17 +++++++++++++++-- src/dummy/i_sound.c | 10 ++++++++++ src/sdl/sdl_sound.c | 10 ++++++++++ src/win32/win_snd.c | 13 +++++++++++++ 5 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/android/i_sound.c b/src/android/i_sound.c index 80b90d2f7..1cbc53fab 100644 --- a/src/android/i_sound.c +++ b/src/android/i_sound.c @@ -65,6 +65,16 @@ musictype_t I_GetMusicType(void) return MU_NONE; } +boolean I_MusicPlaying(void) +{ + return false; +} + +boolean I_MusicPaused(void) +{ + return false; +} + void I_InitMusic(void){} void I_ShutdownMusic(void){} diff --git a/src/djgppdos/i_sound.c b/src/djgppdos/i_sound.c index e66bf8e23..6e351b523 100644 --- a/src/djgppdos/i_sound.c +++ b/src/djgppdos/i_sound.c @@ -321,6 +321,7 @@ static MIDI* currsong; //im assuming only 1 song will be played at once static int islooping=0; static int musicdies=-1; UINT8 music_started=0; +boolean songpaused=false; musictype_t I_GetMusicType(void) { @@ -330,6 +331,16 @@ musictype_t I_GetMusicType(void) return MU_NONE; } +boolean I_MusicPlaying() +{ + return (boolean)currsong; +} + +boolean I_MusicPaused() +{ + return songpaused; +} + /* load_midi_mem: * Loads a standard MIDI file from memory, returning a pointer to * a MIDI structure, * or NULL on error. @@ -403,6 +414,7 @@ void I_InitMusic(void) I_AddExitFunc(I_ShutdownMusic); music_started = true; + songpaused = false; } void I_ShutdownMusic(void) @@ -433,8 +445,8 @@ void I_PauseSong (INT32 handle) handle = 0; if (nomidimusic) return; - midi_pause(); + songpaused = true; } void I_ResumeSong (INT32 handle) @@ -442,8 +454,8 @@ void I_ResumeSong (INT32 handle) handle = 0; if (nomidimusic) return; - midi_resume(); + songpaused = false; } void I_StopSong(void) @@ -455,6 +467,7 @@ void I_StopSong(void) islooping = 0; musicdies = 0; stop_midi(); + songpaused = false; } // Is the song playing? diff --git a/src/dummy/i_sound.c b/src/dummy/i_sound.c index f82bf00da..ca90a7da3 100644 --- a/src/dummy/i_sound.c +++ b/src/dummy/i_sound.c @@ -66,6 +66,16 @@ musictype_t I_GetMusicType(void) return MU_NONE; } +boolean I_MusicPlaying(void) +{ + return false; +} + +boolean I_MusicPaused(void) +{ + return false; +} + void I_InitMusic(void){} void I_ShutdownMusic(void){} diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index 5f92cde10..d8d3e0a95 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -1336,6 +1336,16 @@ musictype_t I_GetMusicType(void) #endif } +boolean I_MusicPlaying(void) +{ + return music_started; +} + +boolean I_MusicPaused(void) +{ + return Mix_PausedMusic(); +} + #ifdef HAVE_LIBGME static void I_ShutdownGMEMusic(void) { diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index bfa43d087..c6a74d999 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -478,6 +478,19 @@ musictype_t I_GetMusicType(void) return MU_NONE; } +boolean I_MusicPlaying(void) +{ + return (boolean)music_stream; +} + +boolean I_MusicPaused(void) +{ + boolean fmpaused = false; + if (music_stream) + FMOD_Channel_GetPaused(music_channel, &fmpaused); + return fmpaused; +} + void I_InitMusic(void) { } From a414ccf24ae6b59b1945cb0b9177bfaebbfb334e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 23 Aug 2018 12:42:15 -0400 Subject: [PATCH 195/306] nodigimusic nomusic nosound -> digital_disabled midi_disabled sound_disabled (cherry picked from commit 07738fb0bcf640a4349337373f451fe68e024b2a) --- src/d_main.c | 26 ++++++++++----------- src/doomstat.h | 5 +--- src/m_menu.c | 62 ++++++++++++++++++++------------------------------ src/p_mobj.c | 2 +- src/s_sound.c | 27 +++++++++------------- 5 files changed, 51 insertions(+), 71 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index f2da8586c..ed1b44684 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -122,17 +122,17 @@ postimg_t postimgtype2 = postimg_none; INT32 postimgparam2; #ifdef _XBOX -boolean nomidimusic = true, nosound = true; -boolean nodigimusic = true; +boolean midi_disabled = true, sound_disabled = true; +boolean digital_disabled = true; #else -boolean nomidimusic = false, nosound = false; -boolean nodigimusic = false; // No fmod-based music +boolean midi_disabled = false, sound_disabled = false; +boolean digital_disabled = false; // No fmod-based music #endif // These variables are only true if -// the respective sound system is initialized -// and active, but no sounds/music should play. -boolean music_disabled = false; +// whether the respective sound system is disabled +// or they're init'ed, but the player just toggled them +boolean midi_disabled = false; boolean sound_disabled = false; boolean digital_disabled = false; @@ -1212,23 +1212,23 @@ void D_SRB2Main(void) // setting up sound if (dedicated) { - nosound = true; - nomidimusic = nodigimusic = true; + sound_disabled = true; + midi_disabled = digital_disabled = true; } else { CONS_Printf("S_InitSfxChannels(): Setting up sound channels.\n"); } if (M_CheckParm("-nosound")) - nosound = true; + sound_disabled = true; if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic - nomidimusic = nodigimusic = true; + midi_disabled = digital_disabled = true; else { if (M_CheckParm("-nomidimusic")) - nomidimusic = true; ; // WARNING: DOS version initmusic in I_StartupSound + midi_disabled = true; ; // WARNING: DOS version initmusic in I_StartupSound if (M_CheckParm("-nodigmusic")) - nodigimusic = true; // WARNING: DOS version initmusic in I_StartupSound + digital_disabled = true; // WARNING: DOS version initmusic in I_StartupSound } I_StartupSound(); I_InitMusic(); diff --git a/src/doomstat.h b/src/doomstat.h index 8072a1552..27bd3fa19 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -85,10 +85,7 @@ extern boolean fromlevelselect; // Internal parameters for sound rendering. // ======================================== -extern boolean nomidimusic; // defined in d_main.c -extern boolean nosound; -extern boolean nodigimusic; -extern boolean music_disabled; +extern boolean midi_disabled; extern boolean sound_disabled; extern boolean digital_disabled; diff --git a/src/m_menu.c b/src/m_menu.c index 82242c0c1..7a5e78a7b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6950,11 +6950,11 @@ static void M_ChangeControl(INT32 choice) // Toggles sound systems in-game. static void M_ToggleSFX(void) { - if (nosound) + if (sound_disabled) { - nosound = false; + sound_disabled = false; I_StartupSound(); - if (nosound) return; + if (sound_disabled) return; S_InitSfxChannels(cv_soundvolume.value); M_StartMessage(M_GetText("SFX Enabled\n"), NULL, MM_NOTHING); } @@ -6976,56 +6976,44 @@ static void M_ToggleSFX(void) static void M_ToggleDigital(void) { - if (nodigimusic) + if (digital_disabled) { - nodigimusic = false; - I_InitDigMusic(); - if (nodigimusic) return; - S_InitSfxChannels(cv_soundvolume.value); + digital_disabled = false; + I_InitMusic(); + if (digital_disabled) return; S_StopMusic(); - S_ChangeMusicInternal("lclear", false); + if (Playing()) + P_RestoreMusic(&players[consoleplayer]); + else + S_ChangeMusicInternal("lclear", false); M_StartMessage(M_GetText("Digital Music Enabled\n"), NULL, MM_NOTHING); } else { - if (digital_disabled) - { - digital_disabled = false; - M_StartMessage(M_GetText("Digital Music Enabled\n"), NULL, MM_NOTHING); - } - else - { - digital_disabled = true; - S_StopMusic(); - M_StartMessage(M_GetText("Digital Music Disabled\n"), NULL, MM_NOTHING); - } + digital_disabled = true; + S_StopMusic(); + M_StartMessage(M_GetText("Digital Music Disabled\n"), NULL, MM_NOTHING); } } static void M_ToggleMIDI(void) { - if (nomidimusic) + if (midi_disabled) { - nomidimusic = false; - I_InitMIDIMusic(); - if (nomidimusic) return; - S_InitSfxChannels(cv_soundvolume.value); - S_ChangeMusicInternal("lclear", false); + midi_disabled = false; + I_InitMusic(); + if (midi_disabled) return; + if (Playing()) + P_RestoreMusic(&players[consoleplayer]); + else + S_ChangeMusicInternal("lclear", false); M_StartMessage(M_GetText("MIDI Music Enabled\n"), NULL, MM_NOTHING); } else { - if (music_disabled) - { - music_disabled = false; - M_StartMessage(M_GetText("MIDI Music Enabled\n"), NULL, MM_NOTHING); - } - else - { - music_disabled = true; - S_StopMusic(); - M_StartMessage(M_GetText("MIDI Music Disabled\n"), NULL, MM_NOTHING); - } + midi_disabled = true; + S_StopMusic(); + M_StartMessage(M_GetText("MIDI Music Disabled\n"), NULL, MM_NOTHING); } } diff --git a/src/p_mobj.c b/src/p_mobj.c index 5f85474c6..a55e5de26 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8228,7 +8228,7 @@ void P_PrecipitationEffects(void) if (!playeringame[displayplayer] || !players[displayplayer].mo) return; - if (nosound || sound_disabled) + if (sound_disabled) return; // Sound off? D'aw, no fun. if (players[displayplayer].mo->subsector->sector->ceilingpic == skyflatnum) diff --git a/src/s_sound.c b/src/s_sound.c index e035c4192..d1993bc87 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -226,7 +226,7 @@ void S_RegisterSoundStuff(void) { if (dedicated) { - nosound = true; + sound_disabled = true; return; } @@ -400,7 +400,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) mobj_t *listenmobj = players[displayplayer].mo; mobj_t *listenmobj2 = NULL; - if (sound_disabled || !sound_started || nosound) + if (sound_disabled || !sound_started) return; // Don't want a sound? Okay then... @@ -716,7 +716,7 @@ void S_UpdateSounds(void) return; } - if (dedicated || nosound) + if (dedicated || sound_disabled) return; if (players[displayplayer].awayviewtics) @@ -1175,7 +1175,7 @@ void S_InitSfxChannels(INT32 sfxVolume) } // precache sounds if requested by cmdline, or precachesound var true - if (!nosound && (M_CheckParm("-precachesound") || precachesound.value)) + if (!sound_disabled && (M_CheckParm("-precachesound") || precachesound.value)) { // Initialize external data (all sounds) at start, keep static. CONS_Printf(M_GetText("Loading sounds... ")); @@ -1220,24 +1220,19 @@ static char music_name[7]; // up to 6-character name /// Music Status /// ------------------------ -boolean S_DigMusicDisabled() +boolean S_DigMusicDisabled(void) { - return (nodigimusic || digital_disabled); + return digital_disabled; } -boolean S_MIDIMusicDisabled() +boolean S_MIDIMusicDisabled(void) { - return (nomidimusic || music_disabled); + return midi_disabled; } -boolean S_MusicDisabled() +boolean S_MusicDisabled(void) { - return ( - (nodigimusic && nomidimusic) || - (music_disabled && digital_disabled) || - (nodigimusic && music_disabled) || - (nomidimusic && digital_disabled) - ); + return (midi_disabled && digital_disabled); } boolean S_MusicPlaying(void) @@ -1333,7 +1328,7 @@ static void S_UnloadMusic(void) static boolean S_PlayMusic(boolean looping) { - if (nodigimusic || digital_disabled) + if (S_DigMusicDisabled()) return false; // try midi if (!I_PlaySong(looping)) From 17cf310b84ebeaa096b2172f55bb9a2fb5494e08 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 23 Aug 2018 12:43:38 -0400 Subject: [PATCH 196/306] nodigimusic nomusic nosound refactor other targets (cherry picked from commit 86f151db654beb14e8d6893cdff2adaa965e8e4b) --- src/djgppdos/i_sound.c | 38 +++++++++++++++++----------------- src/hardware/hw3sound.c | 2 +- src/sdl/sdl_sound.c | 46 ++++++++++++++++++++--------------------- 3 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/djgppdos/i_sound.c b/src/djgppdos/i_sound.c index 6e351b523..d998016a2 100644 --- a/src/djgppdos/i_sound.c +++ b/src/djgppdos/i_sound.c @@ -134,7 +134,7 @@ FUNCINLINE static ATTRINLINE int Volset(int vol) void I_SetSfxVolume(INT32 volume) { - if (nosound) + if (sound_disabled) return; set_volume (Volset(volume),-1); @@ -142,7 +142,7 @@ void I_SetSfxVolume(INT32 volume) void I_SetMusicVolume(INT32 volume) { - if (nomidimusic) + if (midi_disabled) return; // Now set volume on output device. @@ -169,7 +169,7 @@ INT32 I_StartSound ( sfxenum_t id, { int voice; - if (nosound) + if (sound_disabled) return 0; // UNUSED @@ -190,7 +190,7 @@ void I_StopSound (INT32 handle) // an setting the channel to zero. int voice=handle & (VIRTUAL_VOICES-1); - if (nosound) + if (sound_disabled) return; if (voice_check(voice)==S_sfx[handle>>VOICESSHIFT].data) @@ -199,7 +199,7 @@ void I_StopSound (INT32 handle) INT32 I_SoundIsPlaying(INT32 handle) { - if (nosound) + if (sound_disabled) return FALSE; if (voice_check(handle & (VIRTUAL_VOICES-1))==S_sfx[handle>>VOICESSHIFT].data) @@ -229,7 +229,7 @@ void I_UpdateSoundParams( INT32 handle, int voice=handle & (VIRTUAL_VOICES-1); int numsfx=handle>>VOICESSHIFT; - if (nosound) + if (sound_disabled) return; if (voice_check(voice)==S_sfx[numsfx].data) @@ -270,17 +270,17 @@ void I_StartupSound(void) char err[255]; #endif - if (nosound) + if (sound_disabled) sfxcard=DIGI_NONE; else sfxcard=DIGI_AUTODETECT; - if (nomidimusic) + if (midi_disabled) midicard=MIDI_NONE; else midicard=MIDI_AUTODETECT; //DetectMusicCard(); - nodigimusic=true; //Alam: No OGG/MP3/IT/MOD support + digital_disabled=true; //Alam: No OGG/MP3/IT/MOD support // Secure and configure sound device first. CONS_Printf("I_StartupSound: "); @@ -293,8 +293,8 @@ void I_StartupSound(void) { sprintf (err,"Sound init error : %s\n",allegro_error); CONS_Error (err); - nosound=true; - nomidimusic=true; + sound_disabled=true; + midi_disabled=true; } else { @@ -409,7 +409,7 @@ static MIDI *load_midi_mem(char *mempointer,int *e) void I_InitMusic(void) { - if (nomidimusic) + if (midi_disabled) return; I_AddExitFunc(I_ShutdownMusic); @@ -430,7 +430,7 @@ void I_ShutdownMusic(void) boolean I_PlaySong(boolean looping) { handle = 0; - if (nomidimusic) + if (midi_disabled) return false; islooping = looping; @@ -443,7 +443,7 @@ boolean I_PlaySong(boolean looping) void I_PauseSong (INT32 handle) { handle = 0; - if (nomidimusic) + if (midi_disabled) return; midi_pause(); songpaused = true; @@ -452,7 +452,7 @@ void I_PauseSong (INT32 handle) void I_ResumeSong (INT32 handle) { handle = 0; - if (nomidimusic) + if (midi_disabled) return; midi_resume(); songpaused = false; @@ -461,7 +461,7 @@ void I_ResumeSong (INT32 handle) void I_StopSong(void) { handle = 0; - if (nomidimusic) + if (midi_disabled) return; islooping = 0; @@ -474,7 +474,7 @@ void I_StopSong(void) #if 0 int I_QrySongPlaying(int handle) { - if (nomidimusic) + if (midi_disabled) return 0; //return islooping || musicdies > gametic; @@ -485,7 +485,7 @@ int I_QrySongPlaying(int handle) void I_UnloadSong(void) { handle = 0; - if (nomidimusic) + if (midi_disabled) return; //destroy_midi(currsong); @@ -494,7 +494,7 @@ void I_UnloadSong(void) boolean I_LoadSong(char *data, size_t len) { int e = len; //Alam: For error - if (nomidimusic) + if (midi_disabled) return 0; if (memcmp(data,"MThd",4)==0) // support mid file in WAD !!! diff --git a/src/hardware/hw3sound.c b/src/hardware/hw3sound.c index c68430921..f7c6e1da0 100644 --- a/src/hardware/hw3sound.c +++ b/src/hardware/hw3sound.c @@ -361,7 +361,7 @@ INT32 HW3S_I_StartSound(const void *origin_p, source3D_data_t *source_parm, chan if (splitscreen) listenmobj2 = players[secondarydisplayplayer].mo; - if (nosound) + if (sound_disabled) return -1; sfx = &S_sfx[sfx_id]; diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index d8d3e0a95..cf54d7d05 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -194,8 +194,8 @@ static srb2audio_t localdata; static void Snd_LockAudio(void) //Alam: Lock audio data and uninstall audio callback { if (Snd_Mutex) SDL_LockMutex(Snd_Mutex); - else if (nosound) return; - else if (nomidimusic && nodigimusic + else if (sound_disabled) return; + else if (midi_disabled && digital_disabled #ifdef HW3SOUND && hws_mode == HWS_DEFAULT_MODE #endif @@ -208,8 +208,8 @@ static void Snd_LockAudio(void) //Alam: Lock audio data and uninstall audio call static void Snd_UnlockAudio(void) //Alam: Unlock audio data and reinstall audio callback { if (Snd_Mutex) SDL_UnlockMutex(Snd_Mutex); - else if (nosound) return; - else if (nomidimusic && nodigimusic + else if (sound_disabled) return; + else if (midi_disabled && digital_disabled #ifdef HW3SOUND && hws_mode == HWS_DEFAULT_MODE #endif @@ -493,7 +493,7 @@ static inline void I_SetChannels(void) INT32 *steptablemid = steptable + 128; - if (nosound) + if (sound_disabled) return; // This table provides step widths for pitch parameters. @@ -609,7 +609,7 @@ INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priori (void)priority; (void)pitch; - if (nosound) + if (sound_disabled) return 0; if (S_sfx[id].data == NULL) return -1; @@ -1136,7 +1136,7 @@ static INT32 Init3DSDriver(const char *soName) void I_ShutdownSound(void) { - if (nosound || !sound_started) + if (sound_disabled || !sound_started) return; CONS_Printf("I_ShutdownSound: "); @@ -1150,7 +1150,7 @@ void I_ShutdownSound(void) } #endif - if (nomidimusic && nodigimusic) + if (midi_disabled && digital_disabled) SDL_CloseAudio(); CONS_Printf("%s", M_GetText("shut down\n")); sound_started = false; @@ -1170,7 +1170,7 @@ void I_StartupSound(void) const char *sdrv_name = NULL; #endif #ifndef HAVE_MIXER - nomidimusic = nodigimusic = true; + midi_disabled = digital_disabled = true; #endif memset(channels, 0, sizeof (channels)); //Alam: Clean it @@ -1213,7 +1213,7 @@ void I_StartupSound(void) audio.samples /= 2; } - if (nosound) + if (sound_disabled) return; #ifdef HW3SOUND @@ -1261,7 +1261,7 @@ void I_StartupSound(void) { snddev_t snddev; - //nosound = true; + //sound_disabled = true; //I_AddExitFunc(I_ShutdownSound); snddev.bps = 16; snddev.sample_rate = audio.freq; @@ -1288,7 +1288,7 @@ void I_StartupSound(void) if (!musicStarted && SDL_OpenAudio(&audio, &audio) < 0) { CONS_Printf("%s", M_GetText(" couldn't open audio with desired format\n")); - nosound = true; + sound_disabled = true; return; } else @@ -1452,7 +1452,7 @@ static boolean LoadSong(void *data, size_t lumplength, size_t selectpos) void I_ShutdownMusic(void) { #ifdef HAVE_MIXER - if ((nomidimusic && nodigimusic) || !musicStarted) + if ((midi_disabled && digital_disabled) || !musicStarted) return; CONS_Printf("%s", M_GetText("I_ShutdownMusic: ")); @@ -1543,7 +1543,7 @@ void I_InitMusic(void) if (Mix_OpenAudio(audio.freq, audio.format, audio.channels, audio.samples) < 0) //open_music(&audio) { CONS_Printf(M_GetText(" Unable to open music: %s\n"), Mix_GetError()); - nomidimusic = nodigimusic = true; + midi_disabled = digital_disabled = true; if (sound_started #ifdef HW3SOUND && hws_mode == HWS_DEFAULT_MODE @@ -1553,7 +1553,7 @@ void I_InitMusic(void) if (SDL_OpenAudio(&audio, NULL) < 0) //retry { CONS_Printf("%s", M_GetText(" couldn't open audio with desired format\n")); - nosound = true; + sound_disabled = true; sound_started = false; } else @@ -1588,7 +1588,7 @@ boolean I_PlaySong(INT32 handle, boolean looping) { (void)handle; #ifdef HAVE_MIXER - if (nomidimusic || !musicStarted || !music[handle]) + if (midi_disabled || !musicStarted || !music[handle]) return false; #ifdef MIXER_POS @@ -1621,7 +1621,7 @@ void I_PauseSong(void) (void)handle; I_PauseGME(); #ifdef HAVE_MIXER - if ((nomidimusic && nodigimusic) || !musicStarted) + if ((midi_disabled && digital_disabled) || !musicStarted) return; Mix_PauseMusic(); @@ -1641,7 +1641,7 @@ void I_ResumeSong(void) (void)handle; I_ResumeGME(); #ifdef HAVE_MIXER - if ((nomidimusic && nodigimusic) || !musicStarted) + if ((midi_disabled && digital_disabled) || !musicStarted) return; Mix_VolumeMusic(musicvol); @@ -1654,7 +1654,7 @@ void I_StopSong(void) { I_StopGME(); #ifdef HAVE_MIXER - if (nodigimusic) + if (digital_disabled) return; #ifdef MIXER_POS @@ -1676,7 +1676,7 @@ void I_UnloadSong(void) { #ifdef HAVE_MIXER - if (nomidimusic || !musicStarted) + if (midi_disabled || !musicStarted) return; Mix_HaltMusic(); @@ -1695,7 +1695,7 @@ void I_UnloadSong(void) boolean I_LoadSong(char *data, size_t len) { #ifdef HAVE_MIXER - if (nomidimusic || !musicStarted) + if (midi_disabled || !musicStarted) return false; if (!LoadSong(data, len, 0)) @@ -1715,7 +1715,7 @@ boolean I_LoadSong(char *data, size_t len) void I_SetMusicVolume(UINT8 volume) { #ifdef HAVE_MIXER - if ((nomidimusic && nodigimusic) || !musicStarted) + if ((midi_disabled && digital_disabled) || !musicStarted) return; if (Msc_Mutex) SDL_LockMutex(Msc_Mutex); @@ -1802,7 +1802,7 @@ boolean I_StartDigSong(const char *musicname, boolean looping) return true; #ifdef HAVE_MIXER - if (nodigimusic) + if (digital_disabled) return false; snprintf(filename, sizeof filename, "o_%s", musicname); From 7e7899ae831e2203e0cf28b09b8178e66037c554 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 23 Aug 2018 12:51:45 -0400 Subject: [PATCH 197/306] Toggle Digi/MIDI music in menu accurately; add S_MusicType (cherry picked from commit 4aa100aa575cc7fc14a743085222c806ba2c714a) --- src/m_menu.c | 6 ++++-- src/s_sound.c | 36 +++++++++++++++++++++--------------- src/s_sound.h | 2 ++ 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 7a5e78a7b..2c82bf84f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6991,7 +6991,8 @@ static void M_ToggleDigital(void) else { digital_disabled = true; - S_StopMusic(); + if (S_MusicType() != MU_MID) + S_StopMusic(); M_StartMessage(M_GetText("Digital Music Disabled\n"), NULL, MM_NOTHING); } } @@ -7012,7 +7013,8 @@ static void M_ToggleMIDI(void) else { midi_disabled = true; - S_StopMusic(); + if (S_MusicType() == MU_MID) + S_StopMusic(); M_StartMessage(M_GetText("MIDI Music Disabled\n"), NULL, MM_NOTHING); } } diff --git a/src/s_sound.c b/src/s_sound.c index d1993bc87..54ffffc4c 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1245,6 +1245,11 @@ boolean S_MusicPaused(void) return I_MusicPaused(); } +musictype_t S_MusicType(void) +{ + return I_GetMusicType(); +} + const char *S_MusicName(void) { return music_name; @@ -1279,20 +1284,24 @@ static boolean S_LoadMusic(const char *mname) if (S_MusicDisabled()) return false; - if (S_DigMusicDisabled()) - { - if (!S_MIDIExists(mname)) - return false; + if (!S_DigMusicDisabled() && S_DigExists(mname)) + mlumpnum = W_GetNumForName(va("o_%s", mname)); + else if (!S_MIDIMusicDisabled() && S_MIDIExists(mname)) mlumpnum = W_GetNumForName(va("d_%s", mname)); + else if (S_DigMusicDisabled() && S_DigExists(mname)) + { + CONS_Alert(CONS_NOTICE, "Digital music is disabled!\n"); + return false; + } + else if (S_MIDIMusicDisabled() && S_MIDIExists(mname)) + { + CONS_Alert(CONS_NOTICE, "MIDI music is disabled!\n"); + return false; } else { - if (S_DigExists(mname)) - mlumpnum = W_GetNumForName(va("o_%s", mname)); - else if (S_MIDIExists(mname)) - mlumpnum = W_GetNumForName(va("d_%s", mname)); - else - return false; + CONS_Alert(CONS_ERROR, M_GetText("Music lump %.6s not found!\n"), mname); + return false; } // load & register it @@ -1328,8 +1337,8 @@ static void S_UnloadMusic(void) static boolean S_PlayMusic(boolean looping) { - if (S_DigMusicDisabled()) - return false; // try midi + if (S_MusicDisabled()) + return false; if (!I_PlaySong(looping)) { @@ -1362,10 +1371,7 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) S_StopMusic(); // shutdown old music if (!S_LoadMusic(mmusic)) - { - CONS_Alert(CONS_ERROR, M_GetText("Music lump %.6s not found!\n"), mmusic); return; - } if (!S_PlayMusic(looping)) { diff --git a/src/s_sound.h b/src/s_sound.h index 9a3f2805c..a0ac6c158 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -14,6 +14,7 @@ #ifndef __S_SOUND__ #define __S_SOUND__ +#include "i_sound.h" // musictype_t #include "sounds.h" #include "m_fixed.h" #include "command.h" @@ -106,6 +107,7 @@ boolean S_MIDIMusicDisabled(void); boolean S_MusicDisabled(void); boolean S_MusicPlaying(void); boolean S_MusicPaused(void); +musictype_t S_MusicType(void); const char *S_MusicName(void); boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi); #define S_DigExists(a) S_MusicExists(a, false, true) From 8c78d86c3641675e6c5803afab052cf91055af03 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 23 Aug 2018 16:46:40 -0400 Subject: [PATCH 198/306] Play the opposite type music (Digital/MIDI) when toggling between them in menu * S_MusicInfo method to retrieve name, flags, and looping (cherry picked from commit f6ec93198f0dcfa1d053cca88172c3e3c7ba310c) --- src/m_menu.c | 38 ++++++++++++++++++++++++++++++++++++-- src/s_sound.c | 19 +++++++++++++++++-- src/s_sound.h | 2 +- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 2c82bf84f..6a6875aad 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6992,7 +6992,24 @@ static void M_ToggleDigital(void) { digital_disabled = true; if (S_MusicType() != MU_MID) - S_StopMusic(); + { + if (midi_disabled) + S_StopMusic(); + else + { + char mmusic[7]; + UINT16 mflags; + boolean looping; + + if (S_MusicInfo(mmusic, &mflags, &looping) && S_MIDIExists(mmusic)) + { + S_StopMusic(); + S_ChangeMusic(mmusic, mflags, looping); + } + else + S_StopMusic(); + } + } M_StartMessage(M_GetText("Digital Music Disabled\n"), NULL, MM_NOTHING); } } @@ -7014,7 +7031,24 @@ static void M_ToggleMIDI(void) { midi_disabled = true; if (S_MusicType() == MU_MID) - S_StopMusic(); + { + if (digital_disabled) + S_StopMusic(); + else + { + char mmusic[7]; + UINT16 mflags; + boolean looping; + + if (S_MusicInfo(mmusic, &mflags, &looping) && S_DigExists(mmusic)) + { + S_StopMusic(); + S_ChangeMusic(mmusic, mflags, looping); + } + else + S_StopMusic(); + } + } M_StartMessage(M_GetText("MIDI Music Disabled\n"), NULL, MM_NOTHING); } } diff --git a/src/s_sound.c b/src/s_sound.c index 54ffffc4c..32d9c7b06 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1215,6 +1215,8 @@ const char *compat_special_music_slots[16] = #endif static char music_name[7]; // up to 6-character name +static UINT16 music_flags; +static boolean music_looping; /// ------------------------ /// Music Status @@ -1250,9 +1252,17 @@ musictype_t S_MusicType(void) return I_GetMusicType(); } -const char *S_MusicName(void) +boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping) { - return music_name; + if (!I_MusicPlaying()) + return false; + + strncpy(mname, music_name, 7); + mname[6] = 0; + *mflags = music_flags; + *looping = music_looping; + + return (boolean)mname[0]; } boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi) @@ -1333,6 +1343,8 @@ static void S_UnloadMusic(void) { I_UnloadSong(); music_name[0] = 0; + music_flags = 0; + music_looping = false; } static boolean S_PlayMusic(boolean looping) @@ -1373,6 +1385,9 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) if (!S_LoadMusic(mmusic)) return; + music_flags = mflags; + music_looping = looping; + if (!S_PlayMusic(looping)) { CONS_Alert(CONS_ERROR, "Music cannot be played!\n"); diff --git a/src/s_sound.h b/src/s_sound.h index a0ac6c158..a2d51a59b 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -108,7 +108,7 @@ boolean S_MusicDisabled(void); boolean S_MusicPlaying(void); boolean S_MusicPaused(void); musictype_t S_MusicType(void); -const char *S_MusicName(void); +boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping); boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi); #define S_DigExists(a) S_MusicExists(a, false, true) #define S_MIDIExists(a) S_MusicExists(a, true, false) From 5bac836d4c805e37c1bf7d9d75cfa23c0933538f Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 23 Aug 2018 17:05:37 -0400 Subject: [PATCH 199/306] Minor refactoring and reordering * I_GetMusicType() -> I_MusicType() * Wrap MIDI volume hack in #ifdef _WIN32 (cherry picked from commit a7d51bf81030c228937a8e759f8f43b85817fce6) --- src/i_sound.h | 89 ++++++++-------- src/s_sound.c | 8 +- src/sdl/mixer_sound.c | 238 +++++++++++++++++++++++------------------- 3 files changed, 174 insertions(+), 161 deletions(-) diff --git a/src/i_sound.h b/src/i_sound.h index 901e6c284..15126d695 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -66,9 +66,9 @@ void I_StartupSound(void); */ void I_ShutdownSound(void); -// -// SFX I/O -// +/// ------------------------ +/// SFX I/O +/// ------------------------ /** \brief Starts a sound in a particular sound channel. \param id sfxid @@ -120,13 +120,9 @@ void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch); */ void I_SetSfxVolume(UINT8 volume); -// -// MUSIC I/O -// - -musictype_t I_GetMusicType(void); -boolean I_MusicPlaying(void); -boolean I_MusicPaused(void); +/// ------------------------ +// MUSIC SYSTEM +/// ------------------------ /** \brief Init the music systems */ @@ -136,33 +132,23 @@ void I_InitMusic(void); */ void I_ShutdownMusic(void); -/** \brief PAUSE game handling. +/// ------------------------ +// MUSIC PROPERTIES +/// ------------------------ - \param handle song handle +musictype_t I_MusicType(void); +boolean I_MusicPlaying(void); +boolean I_MusicPaused(void); - \return void -*/ -void I_PauseSong(void); +/// ------------------------ +// MUSIC EFFECTS +/// ------------------------ -/** \brief RESUME game handling +boolean I_SetSongSpeed(float speed); - \param handle song handle - - \return void -*/ -void I_ResumeSong(void); - -// -// MIDI I/O -// - -/** \brief The I_SetMIDIMusicVolume function - - \param volume volume to set at - - \return void -*/ -void I_SetMIDIMusicVolume(UINT8 volume); +/// ------------------------ +// MUSIC PLAYBACK +/// ------------------------ /** \brief Registers a song handle to song data. @@ -175,6 +161,15 @@ void I_SetMIDIMusicVolume(UINT8 volume); */ boolean I_LoadSong(char *data, size_t len); +/** \brief See ::I_LoadSong, then think backwards + + \param handle song handle + + \sa I_LoadSong + \todo remove midi handle +*/ +void I_UnloadSong(void); + /** \brief Called by anything that wishes to start music \param handle Song handle @@ -195,35 +190,35 @@ boolean I_PlaySong(boolean looping); */ void I_StopSong(void); -/** \brief See ::I_LoadSong, then think backwards +/** \brief PAUSE game handling. \param handle song handle - \sa I_LoadSong - \todo remove midi handle + \return void */ -void I_UnloadSong(void); +void I_PauseSong(void); -// -// DIGMUSIC I/O -// +/** \brief RESUME game handling -boolean I_SetSongSpeed(float speed); + \param handle song handle -boolean I_SetSongTrack(INT32 track); + \return void +*/ +void I_ResumeSong(void); -/** \brief The I_SetDigMusicVolume function +/** \brief The I_SetMusicVolume function \param volume volume to set at \return void */ -void I_SetDigMusicVolume(UINT8 volume); +void I_SetMusicVolume(UINT8 volume); -// -// CD MUSIC I/O -// +boolean I_SetSongTrack(INT32 track); +/// ------------------------ +// CD MUSIC I/O +/// ------------------------ /** \brief cd music interface */ diff --git a/src/s_sound.c b/src/s_sound.c index 32d9c7b06..bd6022dfb 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1249,7 +1249,7 @@ boolean S_MusicPaused(void) musictype_t S_MusicType(void) { - return I_GetMusicType(); + return I_MusicType(); } boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping) @@ -1274,7 +1274,7 @@ boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi) } /// ------------------------ -/// Music Properties +/// Music Effects /// ------------------------ boolean S_SpeedMusic(float speed) @@ -1283,7 +1283,7 @@ boolean S_SpeedMusic(float speed) } /// ------------------------ -/// Music Routines +/// Music Playback /// ------------------------ static boolean S_LoadMusic(const char *mname) @@ -1462,7 +1462,7 @@ void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume) digvolume = seqvolume = 31; #endif - switch(I_GetMusicType()) + switch(I_MusicType()) { case MU_MID: case MU_MOD: diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 1384f1da0..9c46625fc 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -72,6 +72,10 @@ static Music_Emu *gme; static INT32 current_track; #endif +/// ------------------------ +/// Audio System +/// ------------------------ + void I_StartupSound(void) { I_Assert(!sound_started); @@ -128,6 +132,10 @@ FUNCMATH void I_UpdateSound(void) { } +/// ------------------------ +/// SFX +/// ------------------------ + // this is as fast as I can possibly make it. // sorry. more asm needed. static Mix_Chunk *ds2chunk(void *stream) @@ -430,11 +438,72 @@ void I_SetSfxVolume(UINT8 volume) sfx_volume = volume; } -// -// Music -// +/// ------------------------ +/// Music Hooks +/// ------------------------ -musictype_t I_GetMusicType(void) +static void music_loop(void) +{ + Mix_PlayMusic(music, 0); + Mix_SetMusicPosition(loop_point); +} + +#ifdef HAVE_LIBGME +static void mix_gme(void *udata, Uint8 *stream, int len) +{ + int i; + short *p; + + (void)udata; + + // no gme? no music. + if (!gme || gme_track_ended(gme) || songpaused) + return; + + // play gme into stream + gme_play(gme, len/2, (short *)stream); + + // apply volume to stream + for (i = 0, p = (short *)stream; i < len/2; i++, p++) + *p = ((INT32)*p) * music_volume*2 / 42; +} +#endif + + +/// ------------------------ +/// Music System +/// ------------------------ + +FUNCMATH void I_InitMusic(void) +{ +#ifdef HAVE_LIBGME + gme = NULL; + current_track = -1; +#endif +} + +void I_ShutdownMusic(void) +{ +#ifdef HAVE_LIBGME + if (gme) + { + Mix_HookMusic(NULL, NULL); + gme_delete(gme); + gme = NULL; + } +#endif + if (!music) + return; + Mix_HookMusicFinished(NULL); + Mix_FreeMusic(music); + music = NULL; +} + +/// ------------------------ +/// Music Properties +/// ------------------------ + +musictype_t I_MusicType(void) { #ifdef HAVE_LIBGME if (gme) @@ -463,74 +532,9 @@ boolean I_MusicPaused(void) return songpaused; } -// Music hooks -static void music_loop(void) -{ - Mix_PlayMusic(music, 0); - Mix_SetMusicPosition(loop_point); -} - -#ifdef HAVE_LIBGME -static void mix_gme(void *udata, Uint8 *stream, int len) -{ - int i; - short *p; - - (void)udata; - - // no gme? no music. - if (!gme || gme_track_ended(gme) || songpaused) - return; - - // play gme into stream - gme_play(gme, len/2, (short *)stream); - - // apply volume to stream - for (i = 0, p = (short *)stream; i < len/2; i++, p++) - *p = ((INT32)*p) * music_volume*2 / 42; -} -#endif - -FUNCMATH void I_InitMusic(void) -{ -#ifdef HAVE_LIBGME - gme = NULL; - current_track = -1; -#endif -} - -void I_ShutdownMusic(void) -{ -#ifdef HAVE_LIBGME - if (gme) - { - Mix_HookMusic(NULL, NULL); - gme_delete(gme); - gme = NULL; - } -#endif - if (!music) - return; - Mix_HookMusicFinished(NULL); - Mix_FreeMusic(music); - music = NULL; -} - -void I_PauseSong(void) -{ - Mix_PauseMusic(); - songpaused = true; -} - -void I_ResumeSong(void) -{ - Mix_ResumeMusic(); - songpaused = false; -} - -// -// Digital Music -// +/// ------------------------ +/// Music Effects +/// ------------------------ boolean I_SetSongSpeed(float speed) { @@ -550,40 +554,9 @@ boolean I_SetSongSpeed(float speed) return false; } -boolean I_SetSongTrack(int track) -{ -#ifdef HAVE_LIBGME - if (current_track == track) - return false; - - // If the specified track is within the number of tracks playing, then change it - if (gme) - { - SDL_LockAudio(); - if (track >= 0 - && track < gme_track_count(gme)) - { - gme_err_t gme_e = gme_start_track(gme, track); - if (gme_e != NULL) - { - CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); - return false; - } - current_track = track; - SDL_UnlockAudio(); - return true; - } - SDL_UnlockAudio(); - return false; - } -#endif - (void)track; - return false; -} - -// -// MIDI Music -// +/// ------------------------ +/// Music Playback +/// ------------------------ boolean I_LoadSong(char *data, size_t len) { @@ -731,6 +704,12 @@ boolean I_LoadSong(char *data, size_t len) return true; } +void I_UnloadSong(void) +{ + Mix_FreeMusic(music); + music = NULL; +} + boolean I_PlaySong(boolean looping) { if (!music) @@ -775,25 +754,64 @@ void I_StopSong(void) music = NULL; } +void I_PauseSong(void) +{ + Mix_PauseMusic(); + songpaused = true; +} + +void I_ResumeSong(void) +{ + Mix_ResumeMusic(); + songpaused = false; +} + void I_SetMusicVolume(UINT8 volume) { if (!music) return; - if (I_GetMusicType() == MU_MID) +#ifdef _WIN32 + if (I_MusicType() == MU_MID) // HACK: Until we stop using native MIDI, // disable volume changes music_volume = 31; else +#endif music_volume = volume; Mix_VolumeMusic((UINT32)music_volume*128/31); } -void I_UnloadSong(void) +boolean I_SetSongTrack(int track) { - Mix_FreeMusic(music); - music = NULL; +#ifdef HAVE_LIBGME + if (current_track == track) + return false; + + // If the specified track is within the number of tracks playing, then change it + if (gme) + { + SDL_LockAudio(); + if (track >= 0 + && track < gme_track_count(gme)) + { + gme_err_t gme_e = gme_start_track(gme, track); + if (gme_e != NULL) + { + CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); + return false; + } + current_track = track; + SDL_UnlockAudio(); + return true; + } + SDL_UnlockAudio(); + return false; + } +#endif + (void)track; + return false; } #endif \ No newline at end of file From d535c14fc6b8d5fb25af05075c6804aaae68270c Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 23 Aug 2018 17:05:47 -0400 Subject: [PATCH 200/306] Refactoring and reordering other targets (cherry picked from commit cf065e106f68fb8af3b0568eba188c8235b1656e) --- src/android/i_sound.c | 66 ++++++------ src/djgppdos/i_sound.c | 198 +++++++++++++++++++--------------- src/dummy/i_sound.c | 64 +++++------ src/sdl/sdl_sound.c | 237 +++++++++++++++++++++++------------------ src/win32/win_snd.c | 218 +++++++++++++++++++------------------ 5 files changed, 428 insertions(+), 355 deletions(-) diff --git a/src/android/i_sound.c b/src/android/i_sound.c index 1cbc53fab..bf54c9ff0 100644 --- a/src/android/i_sound.c +++ b/src/android/i_sound.c @@ -55,12 +55,22 @@ void I_SetSfxVolume(INT32 volume) (void)volume; } -// -// MUSIC I/O -// -UINT8 music_started = 0; +/// ------------------------ +// MUSIC SYSTEM +/// ------------------------ -musictype_t I_GetMusicType(void) +UINT8 music_started = 0; +UINT8 digmusic_started = 0; + +void I_InitMusic(void){} + +void I_ShutdownMusic(void){} + +/// ------------------------ +// MUSIC PROPERTIES +/// ------------------------ + +musictype_t I_MusicType(void) { return MU_NONE; } @@ -75,23 +85,19 @@ boolean I_MusicPaused(void) return false; } -void I_InitMusic(void){} +/// ------------------------ +// MUSIC EFFECTS +/// ------------------------ -void I_ShutdownMusic(void){} - -void I_PauseSong(void) +boolean I_SetSongSpeed(float speed) { - (void)handle; + (void)speed; + return false; } -void I_ResumeSong(void) -{ - (void)handle; -} - -// -// MIDI I/O -// +/// ------------------------ +// MUSIC PLAYBACK +/// ------------------------ UINT8 midimusic_started = 0; @@ -102,9 +108,9 @@ boolean I_LoadSong(char *data, size_t len) return -1; } -void I_SetMusicVolume(INT32 volume) +void I_UnloadSong() { - (void)volume; + } boolean I_PlaySong(boolean looping) @@ -119,19 +125,17 @@ void I_StopSong(void) (void)handle; } -void I_UnloadSong(void) +void I_PauseSong(void) { (void)handle; } -// -// DIGMUSIC I/O -// - -UINT8 digmusic_started = 0; - -boolean I_SetSongSpeed(float speed) +void I_ResumeSong(void) { - (void)speed; - return false; -} \ No newline at end of file + (void)handle; +} + +void I_SetMusicVolume(INT32 volume) +{ + (void)volume; +} diff --git a/src/djgppdos/i_sound.c b/src/djgppdos/i_sound.c index d998016a2..339b469d3 100644 --- a/src/djgppdos/i_sound.c +++ b/src/djgppdos/i_sound.c @@ -140,15 +140,6 @@ void I_SetSfxVolume(INT32 volume) set_volume (Volset(volume),-1); } -void I_SetMusicVolume(INT32 volume) -{ - if (midi_disabled) - return; - - // Now set volume on output device. - set_volume (-1, Volset(volume)); -} - // // Starting a sound means adding it // to the current list of active sounds @@ -323,23 +314,9 @@ static int musicdies=-1; UINT8 music_started=0; boolean songpaused=false; -musictype_t I_GetMusicType(void) -{ - if (currsong) - return MU_MID; - else - return MU_NONE; -} - -boolean I_MusicPlaying() -{ - return (boolean)currsong; -} - -boolean I_MusicPaused() -{ - return songpaused; -} +/// ------------------------ +// MUSIC SYSTEM +/// ------------------------ /* load_midi_mem: * Loads a standard MIDI file from memory, returning a pointer to @@ -427,69 +404,41 @@ void I_ShutdownMusic(void) music_started=false; } -boolean I_PlaySong(boolean looping) -{ - handle = 0; - if (midi_disabled) - return false; +/// ------------------------ +// MUSIC PROPERTIES +/// ------------------------ - islooping = looping; - musicdies = gametic + NEWTICRATE*30; - if (play_midi(currsong,looping)==0) - return true; +musictype_t I_MusicType(void) +{ + if (currsong) + return MU_MID; + else + return MU_NONE; +} + +boolean I_MusicPlaying() +{ + return (boolean)currsong; +} + +boolean I_MusicPaused() +{ + return songpaused; +} + +/// ------------------------ +// MUSIC EFFECTS +/// ------------------------ + +boolean I_SetSongSpeed(float speed) +{ + (void)speed; return false; } -void I_PauseSong (INT32 handle) -{ - handle = 0; - if (midi_disabled) - return; - midi_pause(); - songpaused = true; -} - -void I_ResumeSong (INT32 handle) -{ - handle = 0; - if (midi_disabled) - return; - midi_resume(); - songpaused = false; -} - -void I_StopSong(void) -{ - handle = 0; - if (midi_disabled) - return; - - islooping = 0; - musicdies = 0; - stop_midi(); - songpaused = false; -} - -// Is the song playing? -#if 0 -int I_QrySongPlaying(int handle) -{ - if (midi_disabled) - return 0; - - //return islooping || musicdies > gametic; - return (midi_pos==-1); -} -#endif - -void I_UnloadSong(void) -{ - handle = 0; - if (midi_disabled) - return; - - //destroy_midi(currsong); -} +/// ------------------------ +// MUSIC PLAYBACK +/// ------------------------ boolean I_LoadSong(char *data, size_t len) { @@ -516,8 +465,81 @@ boolean I_LoadSong(char *data, size_t len) return 1; } -boolean I_SetSongSpeed(float speed) +void I_UnloadSong(void) { - (void)speed; + handle = 0; + if (midi_disabled) + return; + + //destroy_midi(currsong); +} + +boolean I_PlaySong(boolean looping) +{ + handle = 0; + if (midi_disabled) + return false; + + islooping = looping; + musicdies = gametic + NEWTICRATE*30; + if (play_midi(currsong,looping)==0) + return true; return false; -} \ No newline at end of file +} + +void I_StopSong(void) +{ + handle = 0; + if (midi_disabled) + return; + + islooping = 0; + musicdies = 0; + stop_midi(); + songpaused = false; +} + +void I_PauseSong (INT32 handle) +{ + handle = 0; + if (midi_disabled) + return; + midi_pause(); + songpaused = true; +} + +void I_ResumeSong (INT32 handle) +{ + handle = 0; + if (midi_disabled) + return; + midi_resume(); + songpaused = false; +} + +void I_SetMusicVolume(INT32 volume) +{ + if (midi_disabled) + return; + + // Now set volume on output device. + set_volume (-1, Volset(volume)); +} + +boolean I_SetSongTrack(INT32 track) +{ + (void)track; + return false; +} + +// Is the song playing? +#if 0 +int I_QrySongPlaying(int handle) +{ + if (midi_disabled) + return 0; + + //return islooping || musicdies > gametic; + return (midi_pos==-1); +} +#endif diff --git a/src/dummy/i_sound.c b/src/dummy/i_sound.c index ca90a7da3..fb325c59e 100644 --- a/src/dummy/i_sound.c +++ b/src/dummy/i_sound.c @@ -57,11 +57,19 @@ void I_SetSfxVolume(UINT8 volume) (void)volume; } -// -// MUSIC I/O -// +/// ------------------------ +// MUSIC SYSTEM +/// ------------------------ -musictype_t I_GetMusicType(void) +void I_InitMusic(void){} + +void I_ShutdownMusic(void){} + +/// ------------------------ +// MUSIC PROPERTIES +/// ------------------------ + +musictype_t I_MusicType(void) { return MU_NONE; } @@ -76,28 +84,19 @@ boolean I_MusicPaused(void) return false; } -void I_InitMusic(void){} +/// ------------------------ +// MUSIC EFFECTS +/// ------------------------ -void I_ShutdownMusic(void){} - -void I_SetMusicVolume(UINT8 volume) +boolean I_SetSongSpeed(float speed) { - (void)volume; + (void)speed; + return false; } -void I_PauseSong(void) -{ - (void)handle; -} - -void I_ResumeSong(void) -{ - (void)handle; -} - -// -// MIDI I/O -// +/// ------------------------ +// MUSIC PLAYBACK +/// ------------------------ boolean I_LoadSong(char *data, size_t len) { @@ -106,6 +105,11 @@ boolean I_LoadSong(char *data, size_t len) return -1; } +void I_UnloadSong(void) +{ + (void)handle; +} + boolean I_PlaySong(boolean looping) { (void)handle; @@ -118,19 +122,19 @@ void I_StopSong(void) (void)handle; } -void I_UnloadSong(void) +void I_PauseSong(void) { (void)handle; } -// -// DIGMUSIC I/O -// - -boolean I_SetSongSpeed(float speed) +void I_ResumeSong(void) { - (void)speed; - return false; + (void)handle; +} + +void I_SetMusicVolume(UINT8 volume) +{ + (void)volume; } boolean I_SetSongTrack(int track) diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index cf54d7d05..6a79220c2 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -1313,7 +1313,7 @@ void I_StartupSound(void) // MUSIC API. // -musictype_t I_GetMusicType(void) +musictype_t I_MusicType(void) { #ifdef HAVE_MIXER #ifdef HAVE_LIBGME @@ -1448,28 +1448,9 @@ static boolean LoadSong(void *data, size_t lumplength, size_t selectpos) } #endif - -void I_ShutdownMusic(void) -{ -#ifdef HAVE_MIXER - if ((midi_disabled && digital_disabled) || !musicStarted) - return; - - CONS_Printf("%s", M_GetText("I_ShutdownMusic: ")); - - I_UnloadSong(); - I_StopSong(); - Mix_CloseAudio(); -#ifdef MIX_INIT - Mix_Quit(); -#endif - CONS_Printf("%s", M_GetText("shut down\n")); - musicStarted = SDL_FALSE; - if (Msc_Mutex) - SDL_DestroyMutex(Msc_Mutex); - Msc_Mutex = NULL; -#endif -} +/// ------------------------ +// MUSIC SYSTEM +/// ------------------------ void I_InitMusic(void) { @@ -1584,11 +1565,106 @@ void I_InitMusic(void) #endif } -boolean I_PlaySong(INT32 handle, boolean looping) +void I_ShutdownMusic(void) { - (void)handle; #ifdef HAVE_MIXER - if (midi_disabled || !musicStarted || !music[handle]) + if ((midi_disabled && digital_disabled) || !musicStarted) + return; + + CONS_Printf("%s", M_GetText("I_ShutdownMusic: ")); + + I_UnloadSong(); + I_StopSong(); + Mix_CloseAudio(); +#ifdef MIX_INIT + Mix_Quit(); +#endif + CONS_Printf("%s", M_GetText("shut down\n")); + musicStarted = SDL_FALSE; + if (Msc_Mutex) + SDL_DestroyMutex(Msc_Mutex); + Msc_Mutex = NULL; +#endif +} + +/// ------------------------ +// MUSIC PROPERTIES +/// ------------------------ + +musictype_t I_MusicType(void) +{ + return MU_NONE; +} + +boolean I_MusicPlaying(void) +{ + return false; +} + +boolean I_MusicPaused(void) +{ + return false; +} + +/// ------------------------ +// MUSIC EFFECTS +/// ------------------------ + +boolean I_SetSongSpeed(float speed) +{ + (void)speed; + return false; +} + +/// ------------------------ +// MUSIC PLAYBACK +// \todo Merge Digital and MIDI +/// ------------------------ + +boolean I_LoadSong(char *data, size_t len) +{ +#ifdef HAVE_MIXER + if (midi_disabled || !musicStarted) + return false; + + if (!LoadSong(data, len, 0)) + return false; + + if (music[0]) + return true; + + CONS_Printf(M_GetText("Couldn't load MIDI: %s\n"), Mix_GetError()); +#else + (void)len; + (void)data; +#endif + return false; +} + +void I_UnloadSong(void) +{ +#ifdef HAVE_MIXER + + if (midi_disabled || !musicStarted) + return; + + Mix_HaltMusic(); + while (Mix_PlayingMusic()) + ; + + if (music[handle]) + Mix_FreeMusic(music[handle]); + music[handle] = NULL; + LoadSong(NULL, 0, handle); +#else + (void)handle; +#endif +} + +boolean I_PlaySong(boolean looping) +{ +#ifdef HAVE_MIXER + if (!musicStarted || !music[handle]) return false; #ifdef MIXER_POS @@ -1609,6 +1685,28 @@ boolean I_PlaySong(INT32 handle, boolean looping) return false; } +void I_StopSong(void) +{ + I_StopGME(); +#ifdef HAVE_MIXER + if (digital_disabled) + return; + +#ifdef MIXER_POS + if (canlooping) + Mix_HookMusicFinished(NULL); +#endif + + Mix_HaltMusic(); + while (Mix_PlayingMusic()) + ; + + if (music[1]) + Mix_FreeMusic(music[1]); + music[1] = NULL; + LoadSong(NULL, 0, 1); +} + static void I_PauseGME(void) { #ifdef HAVE_LIBGME @@ -1650,68 +1748,6 @@ void I_ResumeSong(void) #endif } -void I_StopSong(void) -{ - I_StopGME(); -#ifdef HAVE_MIXER - if (digital_disabled) - return; - -#ifdef MIXER_POS - if (canlooping) - Mix_HookMusicFinished(NULL); -#endif - - Mix_HaltMusic(); - while (Mix_PlayingMusic()) - ; - - if (music[1]) - Mix_FreeMusic(music[1]); - music[1] = NULL; - LoadSong(NULL, 0, 1); -} - -void I_UnloadSong(void) -{ -#ifdef HAVE_MIXER - - if (midi_disabled || !musicStarted) - return; - - Mix_HaltMusic(); - while (Mix_PlayingMusic()) - ; - - if (music[handle]) - Mix_FreeMusic(music[handle]); - music[handle] = NULL; - LoadSong(NULL, 0, handle); -#else - (void)handle; -#endif -} - -boolean I_LoadSong(char *data, size_t len) -{ -#ifdef HAVE_MIXER - if (midi_disabled || !musicStarted) - return false; - - if (!LoadSong(data, len, 0)) - return false; - - if (music[0]) - return true; - - CONS_Printf(M_GetText("Couldn't load MIDI: %s\n"), Mix_GetError()); -#else - (void)len; - (void)data; -#endif - return false; -} - void I_SetMusicVolume(UINT8 volume) { #ifdef HAVE_MIXER @@ -1727,6 +1763,18 @@ void I_SetMusicVolume(UINT8 volume) #endif } +boolean I_SetSongTrack(int track) +{ + (void)track; + return false; +} + +/// ------------------------ +// MUSIC LOADING AND CLEANUP +// \todo Split logic between loading and playing, +// then move to Playback section +/// ------------------------ + #ifdef HAVE_LIBGME static void I_CleanupGME(void *userdata) { @@ -1961,19 +2009,6 @@ static void I_StopGME(void) #endif } -boolean I_SetSongSpeed(float speed) -{ - - (void)speed; - return false; -} - -boolean I_SetSongTrack(int track) -{ - (void)track; - return false; -} - #ifdef MIXER_POS static void SDLCALL I_FinishMusic(void) { diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index c6a74d999..3dbe6c572 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -439,11 +439,24 @@ void I_SetSfxVolume(UINT8 volume) sfx_volume = volume; } -// -// MUSIC -// +/// ------------------------ +// MUSIC SYSTEM +/// ------------------------ -musictype_t I_GetMusicType(void) +void I_InitMusic(void) +{ +} + +void I_ShutdownMusic(void) +{ + I_StopSong(); +} + +/// ------------------------ +// MUSIC PROPERTIES +/// ------------------------ + +musictype_t I_MusicType(void) { #ifdef HAVE_LIBGME if (gme) @@ -491,28 +504,46 @@ boolean I_MusicPaused(void) return fmpaused; } -void I_InitMusic(void) +/// ------------------------ +// MUSIC EFFECTS +/// ------------------------ + +boolean I_SetSongSpeed(float speed) { + FMOD_RESULT e; + float frequency; + if (!music_stream) + return false; + if (speed > 250.0f) + speed = 250.0f; //limit speed up to 250x + +#ifdef HAVE_LIBGME + // Try to set GME speed + if (gme) + { + gme_set_tempo(gme, speed); + return true; + } +#endif + + // Try to set Mod/Midi speed + e = FMOD_Sound_SetMusicSpeed(music_stream, speed); + + if (e == FMOD_ERR_FORMAT) + { + // Just change pitch instead for Ogg/etc. + FMR(FMOD_Sound_GetDefaults(music_stream, &frequency, NULL, NULL, NULL)); + FMR_MUSIC(FMOD_Channel_SetFrequency(music_channel, speed*frequency)); + } + else + FMR_MUSIC(e); + + return true; } -void I_ShutdownMusic(void) -{ - I_StopSong(); -} - -void I_PauseSong(void) -{ - UNREFERENCED_PARAMETER(handle); - if (music_stream) - FMR_MUSIC(FMOD_Channel_SetPaused(music_channel, true)); -} - -void I_ResumeSong(void) -{ - UNREFERENCED_PARAMETER(handle); - if (music_stream) - FMR_MUSIC(FMOD_Channel_SetPaused(music_channel, false)); -} +/// ------------------------ +// MUSIC PLAYBACK +/// ------------------------ boolean I_LoadSong(char *data, size_t len) { @@ -726,39 +757,79 @@ boolean I_LoadSong(char *data, size_t len) return true; } -boolean I_SetSongSpeed(float speed) +void I_UnloadSong(void) { - FMOD_RESULT e; - float frequency; - if (!music_stream) - return false; - if (speed > 250.0f) - speed = 250.0f; //limit speed up to 250x + UNREFERENCED_PARAMETER(handle); + if (music_stream) + FMR(FMOD_Sound_Release(music_stream)); + music_stream = NULL; +} +boolean I_PlaySong(boolean looping) +{ #ifdef HAVE_LIBGME - // Try to set GME speed if (gme) { - gme_set_tempo(gme, speed); + gme_start_track(gme, 0); + current_track = 0; + FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel)); + FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); + FMR(FMOD_Channel_SetPriority(music_channel, 0)); return true; } #endif - // Try to set Mod/Midi speed - e = FMOD_Sound_SetMusicSpeed(music_stream, speed); - - if (e == FMOD_ERR_FORMAT) - { - // Just change pitch instead for Ogg/etc. - FMR(FMOD_Sound_GetDefaults(music_stream, &frequency, NULL, NULL, NULL)); - FMR_MUSIC(FMOD_Channel_SetFrequency(music_channel, speed*frequency)); - } + FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel)); + if (I_MusicType() != MU_MID) + FMR(FMOD_Channel_SetVolume(music_channel, midi_volume / 31.0)); else - FMR_MUSIC(e); + FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); + FMR(FMOD_Channel_SetPriority(music_channel, 0)); + current_track = 0; return true; } +void I_StopSong(void) +{ +#ifdef HAVE_LIBGME + if (gme) + gme_delete(gme); + gme = NULL; +#endif + current_track = -1; + + I_UnloadSong(); +} + +void I_PauseSong(void) +{ + UNREFERENCED_PARAMETER(handle); + if (music_stream) + FMR_MUSIC(FMOD_Channel_SetPaused(music_channel, true)); +} + +void I_ResumeSong(void) +{ + UNREFERENCED_PARAMETER(handle); + if (music_stream) + FMR_MUSIC(FMOD_Channel_SetPaused(music_channel, false)); +} + +void I_SetMusicVolume(UINT8 volume) +{ + if (!music_stream) + return; + + // volume is 0 to 31. + if (I_MusicType() == MU_MID) + music_volume = 31; // windows bug hack + else + music_volume = volume; + + FMR_MUSIC(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); +} + boolean I_SetSongTrack(INT32 track) { if (track != current_track) // If the track's already playing, then why bother? @@ -803,66 +874,3 @@ boolean I_SetSongTrack(INT32 track) } return false; } - -// -// Fuck MIDI. ... Okay fine, you can have your silly D_-only mode. -// - -void I_SetMusicVolume(UINT8 volume) -{ - if (!music_stream) - return; - - // volume is 0 to 31. - if (I_GetMusicType() == MU_MID) - music_volume = 31; // windows bug hack - else - music_volume = volume; - - FMR_MUSIC(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); -} - -boolean I_PlaySong(boolean looping) -{ -#ifdef HAVE_LIBGME - if (gme) - { - gme_start_track(gme, 0); - current_track = 0; - FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel)); - FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); - FMR(FMOD_Channel_SetPriority(music_channel, 0)); - return true; - } -#endif - - FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel)); - if (I_GetMusicType() != MU_MID) - FMR(FMOD_Channel_SetVolume(music_channel, midi_volume / 31.0)); - else - FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); - FMR(FMOD_Channel_SetPriority(music_channel, 0)); - current_track = 0; - - return true; -} - -void I_StopSong(void) -{ -#ifdef HAVE_LIBGME - if (gme) - gme_delete(gme); - gme = NULL; -#endif - current_track = -1; - - I_UnloadSong(); -} - -void I_UnloadSong(void) -{ - UNREFERENCED_PARAMETER(handle); - if (music_stream) - FMR(FMOD_Sound_Release(music_stream)); - music_stream = NULL; -} \ No newline at end of file From eacf0ba00bc88eeff112b29fbf18f0a8d6ba2b52 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 23 Aug 2018 20:14:46 -0400 Subject: [PATCH 201/306] Refactor I_MusicType MusicPlaying and MusicPaused -> I_SongType ... (cherry picked from commit 4b82de9e540d6dc0651bbe8db8e5e15cba39f650) --- src/i_sound.h | 6 +++--- src/s_sound.c | 18 +++++++++--------- src/sdl/mixer_sound.c | 8 ++++---- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/i_sound.h b/src/i_sound.h index 15126d695..1be970d2e 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -136,9 +136,9 @@ void I_ShutdownMusic(void); // MUSIC PROPERTIES /// ------------------------ -musictype_t I_MusicType(void); -boolean I_MusicPlaying(void); -boolean I_MusicPaused(void); +musictype_t I_SongType(void); +boolean I_SongPlaying(void); +boolean I_SongPaused(void); /// ------------------------ // MUSIC EFFECTS diff --git a/src/s_sound.c b/src/s_sound.c index bd6022dfb..723401fb2 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1239,22 +1239,22 @@ boolean S_MusicDisabled(void) boolean S_MusicPlaying(void) { - return I_MusicPlaying(); + return I_SongPlaying(); } boolean S_MusicPaused(void) { - return I_MusicPaused(); + return I_SongPaused(); } musictype_t S_MusicType(void) { - return I_MusicType(); + return I_SongType(); } boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping) { - if (!I_MusicPlaying()) + if (!I_SongPlaying()) return false; strncpy(mname, music_name, 7); @@ -1399,10 +1399,10 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) void S_StopMusic(void) { - if (!I_MusicPlaying()) + if (!I_SongPlaying()) return; - if (I_MusicPaused()) + if (I_SongPaused()) I_ResumeSong(); S_SpeedMusic(1.0f); @@ -1421,7 +1421,7 @@ void S_StopMusic(void) // void S_PauseAudio(void) { - if (I_MusicPlaying() && !I_MusicPaused()) + if (I_SongPlaying() && !I_SongPaused()) I_PauseSong(); // pause cd music @@ -1434,7 +1434,7 @@ void S_PauseAudio(void) void S_ResumeAudio(void) { - if (I_MusicPlaying() && I_MusicPaused()) + if (I_SongPlaying() && I_SongPaused()) I_ResumeSong(); // resume cd music @@ -1462,7 +1462,7 @@ void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume) digvolume = seqvolume = 31; #endif - switch(I_MusicType()) + switch(I_SongType()) { case MU_MID: case MU_MOD: diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 9c46625fc..521bcd033 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -503,7 +503,7 @@ void I_ShutdownMusic(void) /// Music Properties /// ------------------------ -musictype_t I_MusicType(void) +musictype_t I_SongType(void) { #ifdef HAVE_LIBGME if (gme) @@ -522,12 +522,12 @@ musictype_t I_MusicType(void) return (musictype_t)Mix_GetMusicType(music); } -boolean I_MusicPlaying(void) +boolean I_SongPlaying(void) { return (boolean)music; } -boolean I_MusicPaused(void) +boolean I_SongPaused(void) { return songpaused; } @@ -772,7 +772,7 @@ void I_SetMusicVolume(UINT8 volume) return; #ifdef _WIN32 - if (I_MusicType() == MU_MID) + if (I_SongType() == MU_MID) // HACK: Until we stop using native MIDI, // disable volume changes music_volume = 31; From 4d61f00b865033a36af0ad246189345a4fa776f8 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 23 Aug 2018 20:14:56 -0400 Subject: [PATCH 202/306] Refactor I_MusicType MusicPlaying and MusicPaused other targets (cherry picked from commit 9e6eebeb8d6b4119d87e9678bb6b0687e3dc5217) --- src/android/i_sound.c | 6 +++--- src/djgppdos/i_sound.c | 6 +++--- src/dummy/i_sound.c | 6 +++--- src/sdl/mixer_sound.c | 4 ++-- src/sdl/sdl_sound.c | 12 ++++++------ src/win32/win_snd.c | 10 +++++----- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/android/i_sound.c b/src/android/i_sound.c index bf54c9ff0..1d16e4df3 100644 --- a/src/android/i_sound.c +++ b/src/android/i_sound.c @@ -70,17 +70,17 @@ void I_ShutdownMusic(void){} // MUSIC PROPERTIES /// ------------------------ -musictype_t I_MusicType(void) +musictype_t I_SongType(void) { return MU_NONE; } -boolean I_MusicPlaying(void) +boolean I_SongPlaying(void) { return false; } -boolean I_MusicPaused(void) +boolean I_SongPaused(void) { return false; } diff --git a/src/djgppdos/i_sound.c b/src/djgppdos/i_sound.c index 339b469d3..5403aef17 100644 --- a/src/djgppdos/i_sound.c +++ b/src/djgppdos/i_sound.c @@ -408,7 +408,7 @@ void I_ShutdownMusic(void) // MUSIC PROPERTIES /// ------------------------ -musictype_t I_MusicType(void) +musictype_t I_SongType(void) { if (currsong) return MU_MID; @@ -416,12 +416,12 @@ musictype_t I_MusicType(void) return MU_NONE; } -boolean I_MusicPlaying() +boolean I_SongPlaying() { return (boolean)currsong; } -boolean I_MusicPaused() +boolean I_SongPaused() { return songpaused; } diff --git a/src/dummy/i_sound.c b/src/dummy/i_sound.c index fb325c59e..4bace7a41 100644 --- a/src/dummy/i_sound.c +++ b/src/dummy/i_sound.c @@ -69,17 +69,17 @@ void I_ShutdownMusic(void){} // MUSIC PROPERTIES /// ------------------------ -musictype_t I_MusicType(void) +musictype_t I_SongType(void) { return MU_NONE; } -boolean I_MusicPlaying(void) +boolean I_SongPlaying(void) { return false; } -boolean I_MusicPaused(void) +boolean I_SongPaused(void) { return false; } diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 521bcd033..9b84a1247 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -63,7 +63,7 @@ UINT8 sound_started = false; static Mix_Music *music; -static UINT8 music_volume, midi_volume, sfx_volume; +static UINT8 music_volume, sfx_volume; static float loop_point; static boolean songpaused; @@ -91,7 +91,7 @@ void I_StartupSound(void) } music = NULL; - music_volume = midi_volume = sfx_volume = 0; + music_volume = sfx_volume = 0; #if SDL_MIXER_VERSION_ATLEAST(1,2,11) Mix_Init(MIX_INIT_FLAC|MIX_INIT_MOD|MIX_INIT_MP3|MIX_INIT_OGG); diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index 6a79220c2..887726ebb 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -1313,7 +1313,7 @@ void I_StartupSound(void) // MUSIC API. // -musictype_t I_MusicType(void) +musictype_t I_SongType(void) { #ifdef HAVE_MIXER #ifdef HAVE_LIBGME @@ -1336,12 +1336,12 @@ musictype_t I_MusicType(void) #endif } -boolean I_MusicPlaying(void) +boolean I_SongPlaying(void) { return music_started; } -boolean I_MusicPaused(void) +boolean I_SongPaused(void) { return Mix_PausedMusic(); } @@ -1591,17 +1591,17 @@ void I_ShutdownMusic(void) // MUSIC PROPERTIES /// ------------------------ -musictype_t I_MusicType(void) +musictype_t I_SongType(void) { return MU_NONE; } -boolean I_MusicPlaying(void) +boolean I_SongPlaying(void) { return false; } -boolean I_MusicPaused(void) +boolean I_SongPaused(void) { return false; } diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index 3dbe6c572..2960ff7d2 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -456,7 +456,7 @@ void I_ShutdownMusic(void) // MUSIC PROPERTIES /// ------------------------ -musictype_t I_MusicType(void) +musictype_t I_SongType(void) { #ifdef HAVE_LIBGME if (gme) @@ -491,12 +491,12 @@ musictype_t I_MusicType(void) return MU_NONE; } -boolean I_MusicPlaying(void) +boolean I_SongPlaying(void) { return (boolean)music_stream; } -boolean I_MusicPaused(void) +boolean I_SongPaused(void) { boolean fmpaused = false; if (music_stream) @@ -780,7 +780,7 @@ boolean I_PlaySong(boolean looping) #endif FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel)); - if (I_MusicType() != MU_MID) + if (I_SongType() != MU_MID) FMR(FMOD_Channel_SetVolume(music_channel, midi_volume / 31.0)); else FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); @@ -822,7 +822,7 @@ void I_SetMusicVolume(UINT8 volume) return; // volume is 0 to 31. - if (I_MusicType() == MU_MID) + if (I_SongType() == MU_MID) music_volume = 31; // windows bug hack else music_volume = volume; From b0c47e2fb12a234a1fa5c41eab54a5b72e734a43 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 24 Aug 2018 13:12:14 -0400 Subject: [PATCH 203/306] GME fix: play song in I_PlaySong, not I_LoadSong (cherry picked from commit 5f21bf230d9716b7cc5b52e4bf3591ebe01e9f3a) --- src/sdl/mixer_sound.c | 8 ++++---- src/win32/win_snd.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 9b84a1247..ca22724b6 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -656,7 +656,6 @@ boolean I_LoadSong(char *data, size_t len) { gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; gme_set_equalizer(gme, &eq); - Mix_HookMusic(mix_gme, gme); return true; } #endif @@ -712,16 +711,17 @@ void I_UnloadSong(void) boolean I_PlaySong(boolean looping) { - if (!music) - return false; -#ifdef HAVE_GME +#ifdef HAVE_LIBGME if (gme) { gme_start_track(gme, 0); current_track = 0; + Mix_HookMusic(mix_gme, gme); return true; } #endif + else if (!music) + return false; if (Mix_PlayMusic(music, looping && loop_point == 0.0f ? -1 : 0) == -1) { diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index 2960ff7d2..2e05c4f72 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -675,7 +675,6 @@ boolean I_LoadSong(char *data, size_t len) fmt.decodebuffersize = (44100 * 2) / 35; fmt.pcmreadcallback = GMEReadCallback; fmt.userdata = gme; - FMR(FMOD_System_CreateStream(fsys, NULL, FMOD_OPENUSER | (looping ? FMOD_LOOP_NORMAL : 0), &fmt, &music_stream)); return true; } #endif @@ -772,6 +771,7 @@ boolean I_PlaySong(boolean looping) { gme_start_track(gme, 0); current_track = 0; + FMR(FMOD_System_CreateStream(fsys, NULL, FMOD_OPENUSER | (looping ? FMOD_LOOP_NORMAL : 0), &fmt, &music_stream)); FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel)); FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); FMR(FMOD_Channel_SetPriority(music_channel, 0)); From 2fbe206ecb6c978f088f7398e970ecbad8b4b90b Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 24 Aug 2018 13:41:26 -0400 Subject: [PATCH 204/306] A word (cherry picked from commit fb6f8c8a0752c229f5b7369729437c8fecb54d45) --- src/sdl/mixer_sound.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index ca22724b6..927065924 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -719,8 +719,9 @@ boolean I_PlaySong(boolean looping) Mix_HookMusic(mix_gme, gme); return true; } + else #endif - else if (!music) + if (!music) return false; if (Mix_PlayMusic(music, looping && loop_point == 0.0f ? -1 : 0) == -1) From 5f22b7d973002eb873551dff56a07a034c564a61 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 24 Aug 2018 18:01:57 -0400 Subject: [PATCH 205/306] Volume fixes # Conflicts: # src/sdl/mixer_sound.c (cherry picked from commit d39b7011c5b12e5b7abe3e493971e003469a1f3d) --- src/s_sound.c | 6 ++++-- src/sdl/mixer_sound.c | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/s_sound.c b/src/s_sound.c index 723401fb2..6b632687b 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1465,11 +1465,13 @@ void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume) switch(I_SongType()) { case MU_MID: - case MU_MOD: - case MU_GME: + //case MU_MOD: + //case MU_GME: I_SetMusicVolume(seqvolume&31); + break; default: I_SetMusicVolume(digvolume&31); + break; } } diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 927065924..49905efd7 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -769,7 +769,7 @@ void I_ResumeSong(void) void I_SetMusicVolume(UINT8 volume) { - if (!music) + if (!I_SongPlaying()) return; #ifdef _WIN32 From d94f7e3cb095b14bad42dc14e39fc40848ed86ee Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 24 Aug 2018 18:02:46 -0400 Subject: [PATCH 206/306] Stub I_UnloadSong because we already unload in I_StopMusic * Stop-gap for now. Ideally the logic would be in the respective places. # Conflicts: # src/sdl/mixer_sound.c (cherry picked from commit eae5d3333f5001512c82f22f2b1433a955b3a6c3) --- src/sdl/mixer_sound.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 49905efd7..676bfc4db 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -705,8 +705,11 @@ boolean I_LoadSong(char *data, size_t len) void I_UnloadSong(void) { - Mix_FreeMusic(music); - music = NULL; + // \todo unhook looper + //var_cleanup(); + //Mix_FreeMusic(music); + //music = NULL; + I_StopSong(); } boolean I_PlaySong(boolean looping) From 8541963c613cfaaff38feef1e00b00a0d5c9ddbc Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 24 Aug 2018 18:00:18 -0400 Subject: [PATCH 207/306] I_SongPlaying detect GME properly (cherry picked from commit e88d1477616ca66472ecb50d371e37dc79c77c0f) --- src/sdl/mixer_sound.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 676bfc4db..dd00d78f7 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -524,7 +524,12 @@ musictype_t I_SongType(void) boolean I_SongPlaying(void) { - return (boolean)music; + return ( +#ifdef HAVE_LIBGME + (I_SongType() == MU_GME && gme) || +#endif + (boolean)music + ); } boolean I_SongPaused(void) From fac7d19637dd29e09622493281744fbfaa045dc0 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 25 Aug 2018 21:42:39 -0400 Subject: [PATCH 208/306] Case-insensitive music_name comparison (cherry picked from commit a7ae059949b320723727aea4468a370bc63c3910) --- src/s_sound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/s_sound.c b/src/s_sound.c index 6b632687b..53b8a9628 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1378,7 +1378,7 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) return; } - if (strncmp(music_name, mmusic, 6)) + if (strnicmp(music_name, newmusic, 6)) { S_StopMusic(); // shutdown old music From 4b1bc53db13198c4746102cff6a0a90eab2e4d88 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Sep 2018 10:58:41 -0400 Subject: [PATCH 209/306] Compile fixes --- src/d_main.c | 11 ++++------- src/s_sound.c | 2 +- src/sdl/i_video.c | 4 ++-- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index ed1b44684..9d2e1bccc 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -121,20 +121,17 @@ INT32 postimgparam; postimg_t postimgtype2 = postimg_none; INT32 postimgparam2; +// These variables are only true if +// whether the respective sound system is disabled +// or they're init'ed, but the player just toggled them #ifdef _XBOX boolean midi_disabled = true, sound_disabled = true; boolean digital_disabled = true; #else -boolean midi_disabled = false, sound_disabled = false; -boolean digital_disabled = false; // No fmod-based music -#endif - -// These variables are only true if -// whether the respective sound system is disabled -// or they're init'ed, but the player just toggled them boolean midi_disabled = false; boolean sound_disabled = false; boolean digital_disabled = false; +#endif boolean advancedemo; #ifdef DEBUGFILE diff --git a/src/s_sound.c b/src/s_sound.c index 53b8a9628..969d9fdee 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1378,7 +1378,7 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) return; } - if (strnicmp(music_name, newmusic, 6)) + if (strnicmp(music_name, mmusic, 6)) { S_StopMusic(); // shutdown old music diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index ce84e86a6..30ef1b27b 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -566,7 +566,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) // Tell game we got focus back, resume music if necessary window_notinfocus = false; if (!paused) - I_ResumeSong(0); //resume it + I_ResumeSong(); //resume it if (!firsttimeonmouse) { @@ -578,7 +578,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) { // Tell game we lost focus, pause music window_notinfocus = true; - I_PauseSong(0); + I_PauseSong(); if (!disable_mouse) { From 691de18fbbe502fe15fa30854a09c028897cc312 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Sep 2018 11:10:38 -0400 Subject: [PATCH 210/306] Menu sound toggle fixes (and add starpost sfx to menu) --- src/m_menu.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 6a6875aad..63794c529 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6954,23 +6954,15 @@ static void M_ToggleSFX(void) { sound_disabled = false; I_StartupSound(); - if (sound_disabled) return; S_InitSfxChannels(cv_soundvolume.value); + S_StartSound(NULL, sfx_strpst); M_StartMessage(M_GetText("SFX Enabled\n"), NULL, MM_NOTHING); } else { - if (sound_disabled) - { - sound_disabled = false; - M_StartMessage(M_GetText("SFX Enabled\n"), NULL, MM_NOTHING); - } - else - { - sound_disabled = true; - S_StopSounds(); - M_StartMessage(M_GetText("SFX Disabled\n"), NULL, MM_NOTHING); - } + sound_disabled = true; + S_StopSounds(); + M_StartMessage(M_GetText("SFX Disabled\n"), NULL, MM_NOTHING); } } @@ -6980,7 +6972,6 @@ static void M_ToggleDigital(void) { digital_disabled = false; I_InitMusic(); - if (digital_disabled) return; S_StopMusic(); if (Playing()) P_RestoreMusic(&players[consoleplayer]); @@ -7020,7 +7011,6 @@ static void M_ToggleMIDI(void) { midi_disabled = false; I_InitMusic(); - if (midi_disabled) return; if (Playing()) P_RestoreMusic(&players[consoleplayer]); else From 8e05de17f07e599ebb0e3030cb6d74a0b1f76e02 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Sep 2018 12:29:58 -0400 Subject: [PATCH 211/306] Bring back music_data handle, for srb2dd --- src/s_sound.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/s_sound.c b/src/s_sound.c index 969d9fdee..13b8beac1 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1215,6 +1215,7 @@ const char *compat_special_music_slots[16] = #endif static char music_name[7]; // up to 6-character name +static void *music_data; static UINT16 music_flags; static boolean music_looping; @@ -1333,6 +1334,7 @@ static boolean S_LoadMusic(const char *mname) { strncpy(music_name, mname, 7); music_name[6] = 0; + music_data = mdata; return true; } else @@ -1343,6 +1345,10 @@ static void S_UnloadMusic(void) { I_UnloadSong(); music_name[0] = 0; +#ifndef HAVE_SDL //SDL uses RWOPS + Z_ChangeTag(music_data, PU_CACHE); +#endif + music_data = NULL; music_flags = 0; music_looping = false; } From e72610a3dc0e7e1d18deb6375daa8bd5ef1e420f Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Sep 2018 12:47:33 -0400 Subject: [PATCH 212/306] Separate StopMusic and UnloadMusic --- src/s_sound.c | 12 ++++------- src/sdl/mixer_sound.c | 50 ++++++++++++++++++------------------------- 2 files changed, 25 insertions(+), 37 deletions(-) diff --git a/src/s_sound.c b/src/s_sound.c index 13b8beac1..2b8e8e721 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1344,11 +1344,13 @@ static boolean S_LoadMusic(const char *mname) static void S_UnloadMusic(void) { I_UnloadSong(); - music_name[0] = 0; + #ifndef HAVE_SDL //SDL uses RWOPS Z_ChangeTag(music_data, PU_CACHE); #endif music_data = NULL; + + music_name[0] = 0; music_flags = 0; music_looping = false; } @@ -1413,13 +1415,7 @@ void S_StopMusic(void) S_SpeedMusic(1.0f); I_StopSong(); - I_UnloadSong(); - -#ifndef HAVE_SDL //SDL uses RWOPS - Z_ChangeTag(music_data, PU_CACHE); -#endif - - music_name[0] = 0; + S_UnloadMusic(); // for now, stopping also means you unload the song } // diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index dd00d78f7..99a379ea2 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -484,19 +484,7 @@ FUNCMATH void I_InitMusic(void) void I_ShutdownMusic(void) { -#ifdef HAVE_LIBGME - if (gme) - { - Mix_HookMusic(NULL, NULL); - gme_delete(gme); - gme = NULL; - } -#endif - if (!music) - return; - Mix_HookMusicFinished(NULL); - Mix_FreeMusic(music); - music = NULL; + I_UnloadSong(); } /// ------------------------ @@ -565,10 +553,8 @@ boolean I_SetSongSpeed(float speed) boolean I_LoadSong(char *data, size_t len) { - I_Assert(!music); -#ifdef HAVE_LIBGME - I_Assert(!gme); -#endif + if (music || gme) + I_UnloadSong(); #ifdef HAVE_LIBGME if ((UINT8)data[0] == 0x1F @@ -710,11 +696,20 @@ boolean I_LoadSong(char *data, size_t len) void I_UnloadSong(void) { - // \todo unhook looper - //var_cleanup(); - //Mix_FreeMusic(music); - //music = NULL; I_StopSong(); + +#ifdef HAVE_LIBGME + if (gme) + { + gme_delete(gme); + gme = NULL; + } +#endif + if (music) + { + Mix_FreeMusic(music); + music = NULL; + } } boolean I_PlaySong(boolean looping) @@ -750,17 +745,14 @@ void I_StopSong(void) if (gme) { Mix_HookMusic(NULL, NULL); - gme_delete(gme); - gme = NULL; current_track = -1; - return; } #endif - if (!music) - return; - Mix_HookMusicFinished(NULL); - Mix_FreeMusic(music); - music = NULL; + if (music) + { + Mix_HookMusicFinished(NULL); + Mix_HaltMusic(); + } } void I_PauseSong(void) From 0999b0f8a8044eae0d8109ba3f0df102bb32c246 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Sep 2018 13:24:15 -0400 Subject: [PATCH 213/306] srb2dd music cleanup fixes --- src/win32/win_cd.c | 2 +- src/win32/win_snd.c | 76 +++++++++++++++++---------------------------- 2 files changed, 29 insertions(+), 49 deletions(-) diff --git a/src/win32/win_cd.c b/src/win32/win_cd.c index f6c430748..2586b8440 100644 --- a/src/win32/win_cd.c +++ b/src/win32/win_cd.c @@ -471,7 +471,7 @@ void I_PlayCD(UINT8 nTrack, UINT8 bLooping) //faB: stop MIDI music, MIDI music will restart if volume is upped later cv_digmusicvolume.value = 0; cv_midimusicvolume.value = 0; - I_StopSong (0); + I_StopSong(); //faB: I don't use the notify message, I'm trying to minimize the delay mciPlay.dwCallback = (DWORD)((size_t)hWndMain); diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index 2e05c4f72..36a5904a5 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -475,11 +475,11 @@ musictype_t I_SongType(void) return MU_WAV; case FMOD_SOUND_TYPE_MOD: return MU_MOD; - case FMOD_SOUND_TYPE_MID: + case FMOD_SOUND_TYPE_MIDI: return MU_MID; case FMOD_SOUND_TYPE_OGGVORBIS: return MU_OGG; - case FMOD_SOUND_TYPE_MP3: + case FMOD_SOUND_TYPE_MPEG: return MU_MP3; case FMOD_SOUND_TYPE_FLAC: return MU_FLAC; @@ -547,20 +547,13 @@ boolean I_SetSongSpeed(float speed) boolean I_LoadSong(char *data, size_t len) { - char *data; - size_t len; FMOD_CREATESOUNDEXINFO fmt; - lumpnum_t lumpnum = W_CheckNumForName(va("O_%s",musicname)); + FMOD_RESULT e; + FMOD_TAG tag; + unsigned int loopstart, loopend; - if (lumpnum == LUMPERROR) - { - lumpnum = W_CheckNumForName(va("D_%s",musicname)); - if (lumpnum == LUMPERROR) - return false; - } - - data = (char *)W_CacheLumpNum(lumpnum, PU_MUSIC); - len = W_LumpLength(lumpnum); + if (gme || music_stream) + I_UnloadSong(); memset(&fmt, 0, sizeof(FMOD_CREATESOUNDEXINFO)); fmt.cbsize = sizeof(FMOD_CREATESOUNDEXINFO); @@ -595,8 +588,6 @@ boolean I_LoadSong(char *data, size_t len) gme_equalizer_t gmeq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; Z_Free(inflatedData); // GME supposedly makes a copy for itself, so we don't need this lying around Z_Free(data); // We don't need this, either. - gme_start_track(gme, 0); - current_track = 0; gme_set_equalizer(gme,&gmeq); fmt.format = FMOD_SOUND_FORMAT_PCM16; fmt.defaultfrequency = 44100; @@ -605,10 +596,7 @@ boolean I_LoadSong(char *data, size_t len) fmt.decodebuffersize = (44100 * 2) / 35; fmt.pcmreadcallback = GMEReadCallback; fmt.userdata = gme; - FMR(FMOD_System_CreateStream(fsys, NULL, FMOD_OPENUSER | (looping ? FMOD_LOOP_NORMAL : 0), &fmt, &music_stream)); - FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel)); - FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); - FMR(FMOD_Channel_SetPriority(music_channel, 0)); + FMR(FMOD_System_CreateStream(fsys, NULL, FMOD_OPENUSER, &fmt, &music_stream)); return true; } } @@ -675,26 +663,24 @@ boolean I_LoadSong(char *data, size_t len) fmt.decodebuffersize = (44100 * 2) / 35; fmt.pcmreadcallback = GMEReadCallback; fmt.userdata = gme; + FMR(FMOD_System_CreateStream(fsys, NULL, FMOD_OPENUSER, &fmt, &music_stream)); return true; } #endif fmt.length = len; - FMOD_RESULT e = FMOD_System_CreateStream(fsys, data, FMOD_OPENMEMORY_POINT|(looping ? FMOD_LOOP_NORMAL : 0), &fmt, &music_stream); + e = FMOD_System_CreateStream(fsys, data, FMOD_OPENMEMORY_POINT, &fmt, &music_stream); if (e != FMOD_OK) { if (e == FMOD_ERR_FORMAT) - CONS_Alert(CONS_WARNING, "Failed to play music lump %s due to invalid format.\n", W_CheckNameForNum(lumpnum)); + CONS_Alert(CONS_WARNING, "Failed to play music lump due to invalid format.\n"); else FMR(e); return false; } // Try to find a loop point in streaming music formats (ogg, mp3) - FMOD_RESULT e; - FMOD_TAG tag; - unsigned int loopstart, loopend; // A proper LOOPPOINT is its own tag, stupid. e = FMOD_Sound_GetTag(music_stream, "LOOPPOINT", 0, &tag); @@ -708,13 +694,6 @@ boolean I_LoadSong(char *data, size_t len) return true; } - // todo - // if(music type == MIDI) - // { - // FMR(FMOD_Sound_SetMode(music_stream, FMOD_LOOP_NORMAL)); - // return true; - // } - // Use LOOPMS for time in miliseconds. e = FMOD_Sound_GetTag(music_stream, "LOOPMS", 0, &tag); if (e != FMOD_ERR_TAGNOTFOUND) @@ -758,10 +737,19 @@ boolean I_LoadSong(char *data, size_t len) void I_UnloadSong(void) { - UNREFERENCED_PARAMETER(handle); + I_StopSong(); +#ifdef HAVE_LIBGME + if (gme) + { + gme_delete(gme); + gme = NULL; + } +#endif if (music_stream) + { FMR(FMOD_Sound_Release(music_stream)); - music_stream = NULL; + music_stream = NULL; + } } boolean I_PlaySong(boolean looping) @@ -771,7 +759,6 @@ boolean I_PlaySong(boolean looping) { gme_start_track(gme, 0); current_track = 0; - FMR(FMOD_System_CreateStream(fsys, NULL, FMOD_OPENUSER | (looping ? FMOD_LOOP_NORMAL : 0), &fmt, &music_stream)); FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel)); FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); FMR(FMOD_Channel_SetPriority(music_channel, 0)); @@ -779,6 +766,7 @@ boolean I_PlaySong(boolean looping) } #endif + FMR(FMOD_Sound_SetMode(music_stream, (looping ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF))); FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel)); if (I_SongType() != MU_MID) FMR(FMOD_Channel_SetVolume(music_channel, midi_volume / 31.0)); @@ -792,33 +780,25 @@ boolean I_PlaySong(boolean looping) void I_StopSong(void) { -#ifdef HAVE_LIBGME - if (gme) - gme_delete(gme); - gme = NULL; -#endif - current_track = -1; - - I_UnloadSong(); + if (music_channel) + FMR_MUSIC(FMOD_Channel_Stop(music_channel)); } void I_PauseSong(void) { - UNREFERENCED_PARAMETER(handle); - if (music_stream) + if (music_channel) FMR_MUSIC(FMOD_Channel_SetPaused(music_channel, true)); } void I_ResumeSong(void) { - UNREFERENCED_PARAMETER(handle); - if (music_stream) + if (music_channel) FMR_MUSIC(FMOD_Channel_SetPaused(music_channel, false)); } void I_SetMusicVolume(UINT8 volume) { - if (!music_stream) + if (!music_channel) return; // volume is 0 to 31. From cb4e075137857a391005cfb12c25b294c4e96031 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Sep 2018 13:36:01 -0400 Subject: [PATCH 214/306] I_InitMusic SDL2: Don't unload GME indiscriminately --- src/sdl/mixer_sound.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 99a379ea2..f39d375ef 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -476,10 +476,6 @@ static void mix_gme(void *udata, Uint8 *stream, int len) FUNCMATH void I_InitMusic(void) { -#ifdef HAVE_LIBGME - gme = NULL; - current_track = -1; -#endif } void I_ShutdownMusic(void) From 76be77b93a2a655cd28983c1709fe058c5878859 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Sep 2018 14:52:24 -0400 Subject: [PATCH 215/306] Rip out SDL Mixer code from sdl_sound.c because superfluous * Mixer code has been in mixer_sound.c; this file is not invoked unless compiling with NOMIXER=1 * Remove everything under #ifdef HAVE_MIXER because this is never triggered * Comment out #ifdef HAVE_LIBGME because we don't support playing music anyway (but theoretically, it could have worked separately from Mixer) * Stub new music calls --- src/sdl/sdl_sound.c | 611 +++----------------------------------------- 1 file changed, 42 insertions(+), 569 deletions(-) diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index 887726ebb..e29ac080b 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -989,7 +989,7 @@ FUNCINLINE static ATTRINLINE void I_UpdateStream16M(Uint8 *stream, int len) if (Snd_Mutex) SDL_UnlockMutex(Snd_Mutex); } -#ifdef HAVE_LIBGME +#if 0 //#ifdef HAVE_LIBGME static void I_UpdateSteamGME(Music_Emu *emu, INT16 *stream, int len, UINT8 looping) { #define GME_BUFFER_LEN 44100*2048 @@ -1049,14 +1049,16 @@ static void SDLCALL I_UpdateStream(void *userdata, Uint8 *stream, int len) else if (audio.channels == 2 && audio.format == AUDIO_S16SYS) { I_UpdateStream16S(stream, len); -#ifdef HAVE_LIBGME - if (userdata) - { - srb2audio_t *sa_userdata = userdata; - if (!sa_userdata->gme_pause) - I_UpdateSteamGME(sa_userdata->gme_emu, (INT16 *)stream, len/4, sa_userdata->gme_loop); - } -#endif + + // Crashes! But no matter; this build doesn't play music anyway... +// #ifdef HAVE_LIBGME +// if (userdata) +// { +// srb2audio_t *sa_userdata = userdata; +// if (!sa_userdata->gme_pause) +// I_UpdateSteamGME(sa_userdata->gme_emu, (INT16 *)stream, len/4, sa_userdata->gme_loop); +// } +// #endif } } @@ -1313,40 +1315,11 @@ void I_StartupSound(void) // MUSIC API. // -musictype_t I_SongType(void) -{ -#ifdef HAVE_MIXER -#ifdef HAVE_LIBGME - if (gme) - return MU_GME; - else -#endif - if (!music) - return MU_NONE; - else if (Mix_GetMusicType(music) == MUS_MID) - return MU_MID; - else if (Mix_GetMusicType(music) == MUS_MOD || Mix_GetMusicType(music) == MUS_MODPLUG_UNUSED) - return MU_MOD; - else if (Mix_GetMusicType(music) == MUS_MP3 || Mix_GetMusicType(music) == MUS_MP3_MAD_UNUSED) - return MU_MP3; - else - return (musictype_t)Mix_GetMusicType(music); -#else - return MU_NONE -#endif -} +/// ------------------------ +// MUSIC SYSTEM +/// ------------------------ -boolean I_SongPlaying(void) -{ - return music_started; -} - -boolean I_SongPaused(void) -{ - return Mix_PausedMusic(); -} - -#ifdef HAVE_LIBGME +#if 0 //#ifdef HAVE_LIBGME static void I_ShutdownGMEMusic(void) { Snd_LockAudio(); @@ -1357,235 +1330,14 @@ static void I_ShutdownGMEMusic(void) } #endif -#ifdef HAVE_MIXER -static boolean LoadSong(void *data, size_t lumplength, size_t selectpos) -{ - FILE *midfile; - const char *tempname; -#ifdef USE_RWOPS - if (canuseRW) - { - SDL_RWops *SDLRW; - void *olddata = Smidi[selectpos]; //quick shortcut to set - - Z_Free(olddata); //free old memory - Smidi[selectpos] = NULL; - - if (!data) - return olddata != NULL; //was there old data? - - SDLRW = SDL_RWFromConstMem(data, (int)lumplength); //new RWops from Z_zone - if (!SDLRW) //ERROR while making RWops! - { - CONS_Printf(M_GetText("Couldn't load music lump: %s\n"), SDL_GetError()); - Z_Free(data); - return false; - } - - music[selectpos] = Mix_LoadMUS_RW(SDLRW); // new Mix_Chuck from RWops - if (music[selectpos]) - Smidi[selectpos] = data; //all done - else //ERROR while making Mix_Chuck - { - CONS_Printf(M_GetText("Couldn't load music data: %s\n"), Mix_GetError()); - Z_Free(data); - SDL_RWclose(SDLRW); - Smidi[selectpos] = NULL; - } - return true; - } -#endif - tempname = va("%s/%s", MIDI_PATH, fmidi[selectpos]); - - if (!data) - { - if (FIL_FileExists(tempname)) - return unlink(tempname)+1; -#ifdef MIDI_PATH2 - else if (FIL_FileExists(tempname = va("%s/%s", MIDI_PATH2, fmidi[selectpos]))) - return unlink(tempname)+1; -#endif - else - return false; - } - - midfile = fopen(tempname, "wb"); - -#ifdef MIDI_PATH2 - if (!midfile) - { - tempname = va("%s/%s", MIDI_PATH2, fmidi[selectpos]); - midfile = fopen(tempname, "wb"); - } -#endif - - if (!midfile) - { - CONS_Printf(M_GetText("Couldn't open file %s to write music in\n"), tempname); - Z_Free(data); - return false; - } - - if (fwrite(data, lumplength, 1, midfile) == 0) - { - CONS_Printf(M_GetText("Couldn't write music into file %s because %s\n"), tempname, strerror(ferror(midfile))); - Z_Free(data); - fclose(midfile); - return false; - } - - fclose(midfile); - - Z_Free(data); - - music[selectpos] = Mix_LoadMUS(tempname); - if (!music[selectpos]) //ERROR while making Mix_Chuck - { - CONS_Printf(M_GetText("Couldn't load music file %s: %s\n"), tempname, Mix_GetError()); - return false; - } - return true; -} -#endif - -/// ------------------------ -// MUSIC SYSTEM -/// ------------------------ - void I_InitMusic(void) { -#ifdef HAVE_MIXER - char ad[100]; - SDL_version MIXcompiled; - const SDL_version *MIXlinked; -#ifdef MIXER_INIT - const int mixstart = MIX_INIT_OGG; - int mixflags; -#endif -#endif -#ifdef HAVE_LIBGME +#if 0 //#ifdef HAVE_LIBGME I_AddExitFunc(I_ShutdownGMEMusic); #endif - -#ifdef HAVE_MIXER - MIX_VERSION(&MIXcompiled) - MIXlinked = Mix_Linked_Version(); - I_OutputMsg("Compiled for SDL_mixer version: %d.%d.%d\n", - MIXcompiled.major, MIXcompiled.minor, MIXcompiled.patch); -#ifdef MIXER_POS - if (MIXlinked->major == 1 && MIXlinked->minor == 2 && MIXlinked->patch < 7) - canlooping = SDL_FALSE; -#endif -#ifdef USE_RWOPS - if (M_CheckParm("-noRW")) - canuseRW = SDL_FALSE; -#endif - I_OutputMsg("Linked with SDL_mixer version: %d.%d.%d\n", - MIXlinked->major, MIXlinked->minor, MIXlinked->patch); - if (audio.freq < 44100 && !M_CheckParm ("-freq")) //I want atleast 44Khz - { - audio.samples = (Uint16)(audio.samples*(INT32)(44100/audio.freq)); - audio.freq = 44100; //Alam: to keep it around the same XX ms - } - - if (sound_started -#ifdef HW3SOUND - && hws_mode == HWS_DEFAULT_MODE -#endif - ) - { - I_OutputMsg("Temp Shutdown of SDL Audio System"); - SDL_CloseAudio(); - I_OutputMsg(" Done\n"); - } - - CONS_Printf("%s", M_GetText("I_InitMusic:")); - -#ifdef MIXER_INIT - mixflags = Mix_Init(mixstart); - if ((mixstart & MIX_INIT_FLAC) != (mixflags & MIX_INIT_FLAC)) - { - CONS_Printf("%s", M_GetText(" Unable to load FLAC support\n")); - } - if ((mixstart & MIX_INIT_MOD ) != (mixflags & MIX_INIT_MOD )) - { - CONS_Printf("%s", M_GetText(" Unable to load MOD support\n")); - } - if ((mixstart & MIX_INIT_MP3 ) != (mixflags & MIX_INIT_MP3 )) - { - CONS_Printf("%s", M_GetText(" Unable to load MP3 support\n")); - } - if ((mixstart & MIX_INIT_OGG ) != (mixflags & MIX_INIT_OGG )) - { - CONS_Printf("%s", M_GetText(" Unable to load OGG support\n")); - } -#endif - - if (Mix_OpenAudio(audio.freq, audio.format, audio.channels, audio.samples) < 0) //open_music(&audio) - { - CONS_Printf(M_GetText(" Unable to open music: %s\n"), Mix_GetError()); - midi_disabled = digital_disabled = true; - if (sound_started -#ifdef HW3SOUND - && hws_mode == HWS_DEFAULT_MODE -#endif - ) - { - if (SDL_OpenAudio(&audio, NULL) < 0) //retry - { - CONS_Printf("%s", M_GetText(" couldn't open audio with desired format\n")); - sound_disabled = true; - sound_started = false; - } - else - { - CONS_Printf(M_GetText(" Starting with audio driver : %s\n"), SDL_AudioDriverName(ad, (int)sizeof ad)); - } - } - return; - } - else - CONS_Printf(M_GetText(" Starting up with audio driver : %s with SDL_Mixer\n"), SDL_AudioDriverName(ad, (int)sizeof ad)); - - samplecount = audio.samples; - CV_SetValue(&cv_samplerate, audio.freq); - if (sound_started -#ifdef HW3SOUND - && hws_mode == HWS_DEFAULT_MODE -#endif - ) - I_OutputMsg(" Reconfigured SDL Audio System"); - else I_OutputMsg(" Configured SDL_Mixer System"); - I_OutputMsg(" with %d samples/slice at %ikhz(%dms buffer)\n", samplecount, audio.freq/1000, (INT32) ((audio.samples * 1000.0f) / audio.freq)); - Mix_SetPostMix(audio.callback, audio.userdata); // after mixing music, add sound effects - Mix_Resume(-1); - CONS_Printf("%s", M_GetText("Music initialized\n")); - musicStarted = SDL_TRUE; - Msc_Mutex = SDL_CreateMutex(); -#endif } -void I_ShutdownMusic(void) -{ -#ifdef HAVE_MIXER - if ((midi_disabled && digital_disabled) || !musicStarted) - return; - - CONS_Printf("%s", M_GetText("I_ShutdownMusic: ")); - - I_UnloadSong(); - I_StopSong(); - Mix_CloseAudio(); -#ifdef MIX_INIT - Mix_Quit(); -#endif - CONS_Printf("%s", M_GetText("shut down\n")); - musicStarted = SDL_FALSE; - if (Msc_Mutex) - SDL_DestroyMutex(Msc_Mutex); - Msc_Mutex = NULL; -#endif -} +void I_ShutdownMusic(void) { } /// ------------------------ // MUSIC PROPERTIES @@ -1618,149 +1370,64 @@ boolean I_SetSongSpeed(float speed) /// ------------------------ // MUSIC PLAYBACK -// \todo Merge Digital and MIDI /// ------------------------ +#if 0 //#ifdef HAVE_LIBGME +static void I_StopGME(void) +{ + Snd_LockAudio(); + gme_seek(localdata.gme_emu, 0); + Snd_UnlockAudio(); +} + +static void I_PauseGME(void) +{ + localdata.gme_pause = true; +} + +static void I_ResumeGME(void) +{ + localdata.gme_pause = false; +} +#endif + boolean I_LoadSong(char *data, size_t len) { -#ifdef HAVE_MIXER - if (midi_disabled || !musicStarted) - return false; - - if (!LoadSong(data, len, 0)) - return false; - - if (music[0]) - return true; - - CONS_Printf(M_GetText("Couldn't load MIDI: %s\n"), Mix_GetError()); -#else - (void)len; - (void)data; -#endif return false; } -void I_UnloadSong(void) -{ -#ifdef HAVE_MIXER - - if (midi_disabled || !musicStarted) - return; - - Mix_HaltMusic(); - while (Mix_PlayingMusic()) - ; - - if (music[handle]) - Mix_FreeMusic(music[handle]); - music[handle] = NULL; - LoadSong(NULL, 0, handle); -#else - (void)handle; -#endif -} +void I_UnloadSong(void) { } boolean I_PlaySong(boolean looping) { -#ifdef HAVE_MIXER - if (!musicStarted || !music[handle]) - return false; - -#ifdef MIXER_POS - if (canlooping) - Mix_HookMusicFinished(NULL); -#endif - - if (Mix_FadeInMusic(music[handle], looping ? -1 : 0, MIDIfade) == -1) - CONS_Printf(M_GetText("Couldn't play song because %s\n"), Mix_GetError()); - else - { - Mix_VolumeMusic(musicvol); - return true; - } -#else (void)looping; -#endif return false; } void I_StopSong(void) { +#if 0 //#ifdef HAVE_LIBGME I_StopGME(); -#ifdef HAVE_MIXER - if (digital_disabled) - return; - -#ifdef MIXER_POS - if (canlooping) - Mix_HookMusicFinished(NULL); -#endif - - Mix_HaltMusic(); - while (Mix_PlayingMusic()) - ; - - if (music[1]) - Mix_FreeMusic(music[1]); - music[1] = NULL; - LoadSong(NULL, 0, 1); -} - -static void I_PauseGME(void) -{ -#ifdef HAVE_LIBGME - localdata.gme_pause = true; #endif } void I_PauseSong(void) { - (void)handle; +#if 0 //#ifdef HAVE_LIBGME I_PauseGME(); -#ifdef HAVE_MIXER - if ((midi_disabled && digital_disabled) || !musicStarted) - return; - - Mix_PauseMusic(); - //I_StopSong(handle); -#endif -} - -static void I_ResumeGME(void) -{ -#ifdef HAVE_LIBGME - localdata.gme_pause = false; #endif } void I_ResumeSong(void) { - (void)handle; +#if 0 I_ResumeGME(); -#ifdef HAVE_MIXER - if ((midi_disabled && digital_disabled) || !musicStarted) - return; - - Mix_VolumeMusic(musicvol); - Mix_ResumeMusic(); - //I_PlaySong(handle, true); #endif } void I_SetMusicVolume(UINT8 volume) { -#ifdef HAVE_MIXER - if ((midi_disabled && digital_disabled) || !musicStarted) - return; - - if (Msc_Mutex) SDL_LockMutex(Msc_Mutex); - musicvol = volume * 2; - if (Msc_Mutex) SDL_UnlockMutex(Msc_Mutex); - Mix_VolumeMusic(musicvol); -#else (void)volume; -#endif } boolean I_SetSongTrack(int track) @@ -1775,16 +1442,14 @@ boolean I_SetSongTrack(int track) // then move to Playback section /// ------------------------ -#ifdef HAVE_LIBGME +#if 0 //#ifdef HAVE_LIBGME static void I_CleanupGME(void *userdata) { Z_Free(userdata); } -#endif static boolean I_StartGMESong(const char *musicname, boolean looping) { -#ifdef HAVE_LIBGME char filename[9]; void *data; lumpnum_t lumpnum; @@ -1830,199 +1495,7 @@ static boolean I_StartGMESong(const char *musicname, boolean looping) Snd_UnlockAudio(); return true; -#else - (void)musicname; - (void)looping; -#endif - return false; -} - -boolean I_StartDigSong(const char *musicname, boolean looping) -{ -#ifdef HAVE_MIXER - char filename[9]; - void *data; - lumpnum_t lumpnum; - size_t lumplength; -#endif - - if(I_StartGMESong(musicname, looping)) - return true; - -#ifdef HAVE_MIXER - if (digital_disabled) - return false; - - snprintf(filename, sizeof filename, "o_%s", musicname); - - lumpnum = W_CheckNumForName(filename); - - I_StopSong(); - - if (lumpnum == LUMPERROR) - { - // Alam_GBC: like in win32/win_snd.c: Graue 02-29-2004: don't worry about missing music, there might still be a MIDI - //I_OutputMsg("Music lump %s not found!\n", filename); - return false; // No music found. Oh well! - } - else - lumplength = W_LumpLength(lumpnum); - - data = W_CacheLumpNum(lumpnum, PU_MUSIC); - - if (Msc_Mutex) SDL_LockMutex(Msc_Mutex); - -#ifdef MIXER_POS - if (canlooping && (loopingDig = looping) == SDL_TRUE && strcmp(data, "OggS") == 0) - looping = false; // Only on looping Ogg files, will we will do our own looping - - // Scan the Ogg Vorbis file for the COMMENT= field for a custom - // loop point - if (!looping && loopingDig) - { - size_t scan; - const char *dataum = data; - char looplength[64]; - UINT32 loopstart = 0; - UINT8 newcount = 0; - - Mix_HookMusicFinished(I_FinishMusic); - - for (scan = 0; scan < lumplength; scan++) - { - if (*dataum++ == 'C'){ - if (*dataum++ == 'O'){ - if (*dataum++ == 'M'){ - if (*dataum++ == 'M'){ - if (*dataum++ == 'E'){ - if (*dataum++ == 'N'){ - if (*dataum++ == 'T'){ - if (*dataum++ == '='){ - if (*dataum++ == 'L'){ - if (*dataum++ == 'O'){ - if (*dataum++ == 'O'){ - if (*dataum++ == 'P'){ - if (*dataum++ == 'P'){ - if (*dataum++ == 'O'){ - if (*dataum++ == 'I'){ - if (*dataum++ == 'N'){ - if (*dataum++ == 'T'){ - if (*dataum++ == '=') - { - - while (*dataum != 1 && newcount != 63) - looplength[newcount++] = *dataum++; - - looplength[newcount] = '\0'; - - loopstart = atoi(looplength); - - } - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - } - - if (loopstart > 0) - { - loopstartDig = (double)((44.1l+loopstart) / 44100.0l); //8 PCM chucks off and PCM to secs -//#ifdef PARANOIA - //I_OutputMsg("I_StartDigSong: setting looping point to %ul PCMs(%f seconds)\n", loopstart, loopstartDig); -//#endif - } - else - { - looping = true; // loopingDig true, but couldn't find start loop point - } - } - else - loopstartDig = 0.0l; -#else - if (looping && strcmp(data, "OggS") == 0) - I_OutputMsg("I_StartDigSong: SRB2 was not compiled with looping music support(no Mix_FadeInMusicPos)\n"); -#endif - - if (!LoadSong(data, lumplength, 1)) - { - if (Msc_Mutex) SDL_UnlockMutex(Msc_Mutex); - return false; - } - - // Note: LoadSong() frees the data. Let's make sure - // we don't try to use the data again. - data = NULL; - - if (Mix_FadeInMusic(music[1], looping ? -1 : 0, Digfade) == -1) - { - if (Msc_Mutex) SDL_UnlockMutex(Msc_Mutex); - I_OutputMsg("I_StartDigSong: Couldn't play song %s because %s\n", musicname, Mix_GetError()); - return false; - } - Mix_VolumeMusic(musicvol); - - if (Msc_Mutex) SDL_UnlockMutex(Msc_Mutex); - return true; -#else - (void)looping; - (void)musicname; - return false; -#endif -} - -static void I_StopGME(void) -{ -#ifdef HAVE_LIBGME - Snd_LockAudio(); - gme_seek(localdata.gme_emu, 0); - Snd_UnlockAudio(); -#endif -} - -#ifdef MIXER_POS -static void SDLCALL I_FinishMusic(void) -{ - if (!music[1]) - return; - else if (Msc_Mutex) SDL_LockMutex(Msc_Mutex); -// I_OutputMsg("I_FinishMusic: Loopping song to %g seconds\n", loopstartDig); - - if (Mix_FadeInMusicPos(music[1], loopstartDig ? 0 : -1, Digfade, loopstartDig) == 0) - Mix_VolumeMusic(musicvol); - else - I_OutputMsg("I_FinishMusic: Couldn't loop song because %s\n", Mix_GetError()); - - if (Msc_Mutex) SDL_UnlockMutex(Msc_Mutex); } #endif + #endif //HAVE_SDL \ No newline at end of file From 546fa383c1c74499552e031b11020ed71a6d8561 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 14 Sep 2018 21:01:07 +0100 Subject: [PATCH 216/306] Make sure that T_MarioBlockChecker is synced in netgames, so that the textures of Mario Blocks can change when there are no more items --- src/p_saveg.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index d1ec8e5ab..6e0c704f6 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -950,6 +950,7 @@ typedef enum tc_bouncecheese, tc_startcrumble, tc_marioblock, + tc_marioblockchecker, tc_spikesector, tc_floatsector, tc_bridgethinker, @@ -1774,6 +1775,11 @@ static void P_NetArchiveThinkers(void) SaveSpecialLevelThinker(th, tc_marioblock); continue; } + else if (th->function.acp1 == (actionf_p1)T_MarioBlockChecker) + { + SaveSpecialLevelThinker(th, tc_marioblockchecker); + continue; + } else if (th->function.acp1 == (actionf_p1)T_SpikeSector) { SaveSpecialLevelThinker(th, tc_spikesector); @@ -2730,6 +2736,10 @@ static void P_NetUnArchiveThinkers(void) LoadSpecialLevelThinker((actionf_p1)T_MarioBlock, 3); break; + case tc_marioblockchecker: + LoadSpecialLevelThinker((actionf_p1)T_MarioBlockChecker, 0); + break; + case tc_spikesector: LoadSpecialLevelThinker((actionf_p1)T_SpikeSector, 0); break; From b330dc23946ecfae91301ababebbfddc97560c7e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Sep 2018 16:39:10 -0400 Subject: [PATCH 217/306] Don't call I_StartupSound in SFX toggle * Mixer: make I_StartupSound return early if already set up * Restartaudio: Add StopSFX call --- src/d_netcmd.c | 1 + src/m_menu.c | 1 - src/sdl/mixer_sound.c | 5 ++++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index ab3201c5c..a58aff3fe 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3955,6 +3955,7 @@ static void Command_RestartAudio_f(void) return; S_StopMusic(); + S_StopSounds(); I_ShutdownMusic(); I_ShutdownSound(); I_StartupSound(); diff --git a/src/m_menu.c b/src/m_menu.c index 63794c529..c9adbfb9c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6953,7 +6953,6 @@ static void M_ToggleSFX(void) if (sound_disabled) { sound_disabled = false; - I_StartupSound(); S_InitSfxChannels(cv_soundvolume.value); S_StartSound(NULL, sfx_strpst); M_StartMessage(M_GetText("SFX Enabled\n"), NULL, MM_NOTHING); diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index f39d375ef..72217482f 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -82,7 +82,10 @@ void I_StartupSound(void) // EE inits audio first so we're following along. if (SDL_WasInit(SDL_INIT_AUDIO) == SDL_INIT_AUDIO) - CONS_Printf("SDL Audio already started\n"); + { + CONS_Debug(DBG_DETAILED, "SDL Audio already started\n"); + return; + } else if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { CONS_Alert(CONS_ERROR, "Error initializing SDL Audio: %s\n", SDL_GetError()); From fdbe3e80f6eac3659093a79f8dabfb92df0b1c10 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Sep 2018 17:07:13 -0400 Subject: [PATCH 218/306] Fix compile errors on buildbots * Check SDL Mixer 2.0.3 for MUS_MODPLUG_UNUSED, MUS_MP3_MAD_UNUSED * Mixed D+C in I_LoadSong --- src/sdl/mixer_sound.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 72217482f..d496aa666 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -501,9 +501,17 @@ musictype_t I_SongType(void) return MU_NONE; else if (Mix_GetMusicType(music) == MUS_MID) return MU_MID; - else if (Mix_GetMusicType(music) == MUS_MOD || Mix_GetMusicType(music) == MUS_MODPLUG_UNUSED) + else if (Mix_GetMusicType(music) == MUS_MOD +#if SDL_MIXER_VERSION_ATLEAST(2,0,3) + || Mix_GetMusicType(music) == MUS_MODPLUG_UNUSED +#endif + ) return MU_MOD; - else if (Mix_GetMusicType(music) == MUS_MP3 || Mix_GetMusicType(music) == MUS_MP3_MAD_UNUSED) + else if (Mix_GetMusicType(music) == MUS_MP3 +#if SDL_MIXER_VERSION_ATLEAST(2,0,3) + || Mix_GetMusicType(music) == MUS_MP3_MAD_UNUSED +#endif + ) return MU_MP3; else return (musictype_t)Mix_GetMusicType(music); @@ -552,6 +560,14 @@ boolean I_SetSongSpeed(float speed) boolean I_LoadSong(char *data, size_t len) { + const char *key1 = "LOOP"; + const char *key2 = "POINT="; + const char *key3 = "MS="; + const size_t key1len = strlen(key1); + const size_t key2len = strlen(key2); + const size_t key3len = strlen(key3); + char *p = data; + if (music || gme) I_UnloadSong(); @@ -660,13 +676,6 @@ boolean I_LoadSong(char *data, size_t len) // Find the OGG loop point. loop_point = 0.0f; - const char *key1 = "LOOP"; - const char *key2 = "POINT="; - const char *key3 = "MS="; - const size_t key1len = strlen(key1); - const size_t key2len = strlen(key2); - const size_t key3len = strlen(key3); - char *p = data; while ((UINT32)(p - data) < len) { if (strncmp(p++, key1, key1len)) From 17ec5d80220b472fe827e5e87b5c05f083a3cd24 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Sep 2018 17:27:00 -0400 Subject: [PATCH 219/306] Mixer: Better MODPLUG/MP3_MAD defines (cherry picked from commit 5b724e18b5268b0492b3f8b8980aadd2dd41e235) --- src/sdl/mixer_sound.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index d496aa666..e46da2755 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -34,6 +34,12 @@ (SDL_MIXER_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z)) #endif +// thanks alam for making the buildbots happy! +#if SDL_MIXER_VERSION_ATLEAST(2,0,3) +#define MUS_MP3_MAD MUS_MP3_MAD_UNUSED +#define MUS_MODPLUG MUS_MODPLUG_UNUSED +#endif + #ifdef HAVE_LIBGME #include "gme/gme.h" #define GME_TREBLE 5.0 @@ -501,17 +507,9 @@ musictype_t I_SongType(void) return MU_NONE; else if (Mix_GetMusicType(music) == MUS_MID) return MU_MID; - else if (Mix_GetMusicType(music) == MUS_MOD -#if SDL_MIXER_VERSION_ATLEAST(2,0,3) - || Mix_GetMusicType(music) == MUS_MODPLUG_UNUSED -#endif - ) + else if (Mix_GetMusicType(music) == MUS_MOD || Mix_GetMusicType(music) == MUS_MODPLUG) return MU_MOD; - else if (Mix_GetMusicType(music) == MUS_MP3 -#if SDL_MIXER_VERSION_ATLEAST(2,0,3) - || Mix_GetMusicType(music) == MUS_MP3_MAD_UNUSED -#endif - ) + else if (Mix_GetMusicType(music) == MUS_MP3 || Mix_GetMusicType(music) == MUS_MP3_MAD) return MU_MP3; else return (musictype_t)Mix_GetMusicType(music); From 9a5eb024590d5b98afa878a6ebd49eef4fcb28ed Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Sep 2018 17:47:04 -0400 Subject: [PATCH 220/306] Fix Windows buildbot for MP3_MAD/MODPLUG define (the header we use is 2.0.2) --- src/sdl/mixer_sound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index e46da2755..7d11c32c6 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -35,7 +35,7 @@ #endif // thanks alam for making the buildbots happy! -#if SDL_MIXER_VERSION_ATLEAST(2,0,3) +#if SDL_MIXER_VERSION_ATLEAST(2,0,2) #define MUS_MP3_MAD MUS_MP3_MAD_UNUSED #define MUS_MODPLUG MUS_MODPLUG_UNUSED #endif From f85d1da54f700cfc88b1a4bcc56260c8141584a5 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Sep 2018 21:42:52 -0400 Subject: [PATCH 221/306] Lua support for floorrover/ceilingrover --- src/lua_mobjlib.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 6efbeff8e..da0e99ab2 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -40,6 +40,8 @@ enum mobj_e { mobj_subsector, mobj_floorz, mobj_ceilingz, + mobj_floorrover, + mobj_ceilingrover, mobj_radius, mobj_height, mobj_momx, @@ -100,6 +102,8 @@ static const char *const mobj_opt[] = { "subsector", "floorz", "ceilingz", + "floorrover", + "ceilingrover", "radius", "height", "momx", @@ -208,6 +212,12 @@ static int mobj_get(lua_State *L) case mobj_ceilingz: lua_pushfixed(L, mo->ceilingz); break; + case mobj_floorrover: + LUA_PushUserdata(L, mo->floorrover, META_FFLOOR); + break; + case mobj_ceilingrover: + LUA_PushUserdata(L, mo->ceilingrover, META_FFLOOR); + break; case mobj_radius: lua_pushfixed(L, mo->radius); break; @@ -432,6 +442,10 @@ static int mobj_set(lua_State *L) return NOSETPOS; case mobj_ceilingz: return NOSETPOS; + case mobj_floorrover: + return NOSET; + case mobj_ceilingrover: + return NOSET; case mobj_radius: { mobj_t *ptmthing = tmthing; From 2f995f4cbeed00a5fb3646a4be8a086d0609fb5a Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Sep 2018 22:35:08 -0400 Subject: [PATCH 222/306] Remove possibly wrong comment about extracolormap_t->fog --- src/r_defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_defs.h b/src/r_defs.h index b9c6fd7dc..e1c1d45c2 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -53,7 +53,7 @@ typedef UINT8 lighttable_t; typedef struct extracolormap_s { UINT8 fadestart, fadeend; - UINT8 fog; // 1 = disable sprite fullbright, 2 = force planes fullbright, see public gitlab !268 + UINT8 fog; // categorical value, not boolean // store rgba values in combined bitwise // also used in OpenGL instead lighttables From 40a8c9c1ee4fc30e82a8ce3d84d309152a07a5a2 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 15 Sep 2018 00:34:55 -0400 Subject: [PATCH 223/306] Mixer: HAVE_LIBGME ifdef in I_LoadSong --- src/sdl/mixer_sound.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 7d11c32c6..87f8fd671 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -566,7 +566,11 @@ boolean I_LoadSong(char *data, size_t len) const size_t key3len = strlen(key3); char *p = data; - if (music || gme) + if (music +#ifdef HAVE_LIBGME + || gme +#endif + ) I_UnloadSong(); #ifdef HAVE_LIBGME From 57959522e20b0bce603fa51ff1d9f76abf30dafe Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 15 Sep 2018 00:48:34 -0400 Subject: [PATCH 224/306] Colormap overhaul r_data: Mixed D+C fix --- src/r_data.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index f1cd519e0..ce0213b36 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1905,6 +1905,8 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha, boolean lighttable) { + INT16 red, green, blue, alpha; + // exc_augend is added (or subtracted) onto by exc_addend // In Rennaisance times, the first number was considered the augend, the second number the addend // But since the commutative property was discovered, today they're both called addends! @@ -1914,8 +1916,6 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex if(!exc_addend) exc_addend = R_GetDefaultColormap(); - INT16 red, green, blue, alpha; - /////////////////// // base rgba /////////////////// From 1db8aee539dea8942dafa30a8281f29f2d8704c8 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 15 Sep 2018 00:51:55 -0400 Subject: [PATCH 225/306] 455: Mixed D+C fix --- src/p_spec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 88a046b37..a408b2140 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7484,6 +7484,8 @@ static void P_ResetColormapFader(sector_t *sector) static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, extracolormap_t *dest_exc, boolean ticbased, INT32 duration) { + fadecolormap_t *d; + P_ResetColormapFader(sector); // nothing to do, set immediately @@ -7493,7 +7495,7 @@ static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, ext return; } - fadecolormap_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); + d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); d->thinker.function.acp1 = (actionf_p1)T_FadeColormap; d->sector = sector; d->source_exc = source_exc; From ca4a94eca5ae9517b4d0d055d4a879b3dc45911e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 15 Sep 2018 00:56:27 -0400 Subject: [PATCH 226/306] 492: Mixed D+C fix --- src/p_spec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 0502b5638..2583c24f3 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1272,6 +1272,7 @@ static boolean PolyFade(line_t *line) { INT32 polyObjNum = line->tag; polyobj_t *po; + polyfadedata_t pfd; if (!(po = Polyobj_GetForNum(polyObjNum))) { @@ -1283,8 +1284,6 @@ static boolean PolyFade(line_t *line) if (po->isBad) return 0; - polyfadedata_t pfd; - pfd.polyObjNum = polyObjNum; // if DONTPEGBOTTOM, specify raw translucency value in Front X Offset From 5585edf4599efccfafb3d5ae93c2b91466d0adf2 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 15 Sep 2018 01:04:15 -0400 Subject: [PATCH 227/306] 453: Mixed D+C fixes; unused param cast in P_FadeFakeFloor --- src/p_saveg.c | 3 ++- src/p_spec.c | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 5b1cc5b27..7d6215643 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2621,6 +2621,7 @@ static inline void LoadDisappearThinker(actionf_p1 thinker) // static inline void LoadFadeThinker(actionf_p1 thinker) { + sector_t *ss; fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; ht->dest_exc = LoadExtraColormap(save_p); @@ -2641,7 +2642,7 @@ static inline void LoadFadeThinker(actionf_p1 thinker) ht->doghostfade = READUINT8(save_p); ht->exactalpha = READUINT8(save_p); - sector_t *ss = LoadSector(ht->sectornum); + ss = LoadSector(ht->sectornum); if (ss) { size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc diff --git a/src/p_spec.c b/src/p_spec.c index 87146ab54..30eb393dd 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7574,6 +7574,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destval boolean stillfading = false; INT32 alpha; fade_t *fadingdata = (fade_t *)rover->fadingdata; + (void)docolormap; // *shrug* maybe we can use this in the future. For now, let's be consistent with our other function params if (rover->master->special == 258) // Laser block return false; @@ -7832,6 +7833,8 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor boolean doexists, boolean dotranslucent, boolean dolighting, boolean docolormap, boolean docollision, boolean doghostfade, boolean exactalpha) { + fade_t *d; + // If fading an invisible FOF whose render flags we did not yet set, // initialize its alpha to 1 if (dotranslucent && @@ -7845,7 +7848,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor if (rover->alpha == max(1, min(256, relative ? rover->alpha + destvalue : destvalue))) return; - fade_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); + d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); d->thinker.function.acp1 = (actionf_p1)T_Fade; d->rover = rover; From 6844ed37c5ae95dfb7294eaaaf84538cf45e6f27 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 15 Sep 2018 01:47:56 -0400 Subject: [PATCH 228/306] Colormap overhaul: %d format size_t -> UINT32 fix --- src/p_saveg.c | 5 ++--- src/r_data.c | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 2d39ccfa2..f9841717e 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -494,7 +494,6 @@ static void SaveExtraColormap(UINT8 *put, extracolormap_t *exc) static extracolormap_t *LoadExtraColormap(UINT8 *get) { extracolormap_t *exc, *exc_exist; - //size_t dbg_i = 0; UINT8 fadestart = READUINT8(get), fadeend = READUINT8(get), @@ -515,8 +514,8 @@ static extracolormap_t *LoadExtraColormap(UINT8 *get) if (!exc) { // CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - // (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF, - // (fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF); + // R_GetRgbaR(rgba), R_GetRgbaG(rgba), R_GetRgbaB(rgba), R_GetRgbaA(rgba), + // R_GetRgbaR(fadergba), R_GetRgbaG(fadergba), R_GetRgbaB(fadergba), R_GetRgbaA(fadergba)); exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); diff --git a/src/r_data.c b/src/r_data.c index ce0213b36..cfc1a734e 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1510,7 +1510,7 @@ extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 #endif { extracolormap_t *exc; - size_t dbg_i = 0; + UINT32 dbg_i = 0; for (exc = extra_colormaps; exc; exc = exc->next) { @@ -1525,8 +1525,8 @@ extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 ) { CONS_Debug(DBG_RENDER, "Found Colormap %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - dbg_i, (rgba)&0xFF, (rgba>>8)&0xFF, (rgba>>16)&0xFF, (rgba>>24)&0xFF, - (fadergba)&0xFF, (fadergba>>8)&0xFF, (fadergba>>16)&0xFF, (fadergba>>24)&0xFF); + dbg_i, R_GetRgbaR(rgba), R_GetRgbaG(rgba), R_GetRgbaB(rgba), R_GetRgbaA(rgba), + R_GetRgbaR(fadergba), R_GetRgbaG(fadergba), R_GetRgbaB(fadergba), R_GetRgbaA(fadergba)); return exc; } dbg_i++; From efe0af960dd2d084f5a9ec8e9c56eda67ca57a65 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 15 Sep 2018 02:10:17 -0400 Subject: [PATCH 229/306] Colormap overhaul: Wrap R_CheckNumForNameList under ifdef EXTRACOLORMAPLUMPS --- src/r_data.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index cfc1a734e..08e3d91b6 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1144,6 +1144,10 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex) Z_Free((void *)texturesText); } +#ifdef EXTRACOLORMAPLUMPS +static lumplist_t *colormaplumps = NULL; ///\todo free leak +static size_t numcolormaplumps = 0; + static inline lumpnum_t R_CheckNumForNameList(const char *name, lumplist_t *list, size_t listsize) { size_t i; @@ -1160,10 +1164,6 @@ static inline lumpnum_t R_CheckNumForNameList(const char *name, lumplist_t *list return LUMPERROR; } -#ifdef EXTRACOLORMAPLUMPS -static lumplist_t *colormaplumps = NULL; ///\todo free leak -static size_t numcolormaplumps = 0; - static void R_InitExtraColormaps(void) { lumpnum_t startnum, endnum; From a85953a9038c4aa3c7ad6237166962e64ae98601 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 15 Sep 2018 02:15:37 -0400 Subject: [PATCH 230/306] 453: P_ResetFakeFloorFader stray & address if condition --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 30eb393dd..bb464c0dc 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7534,7 +7534,7 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz // find any existing thinkers and remove them, then replace with new data if (fadingdata != data) { - if (&fadingdata->thinker) + if (fadingdata->thinker) { if (finalize) P_FadeFakeFloor(rover, From 809646e7fe36ce05d388b59b0fbdb4011d9a7f47 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 15 Sep 2018 02:24:44 -0400 Subject: [PATCH 231/306] 453: Try ResetFakeFloorFader if condition again --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index bb464c0dc..8cbe2e369 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7534,7 +7534,7 @@ static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finaliz // find any existing thinkers and remove them, then replace with new data if (fadingdata != data) { - if (fadingdata->thinker) + if (fadingdata) { if (finalize) P_FadeFakeFloor(rover, From ab4a825385bee6aa3fd4577d4744e3e1e1830134 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 15 Sep 2018 19:00:50 -0400 Subject: [PATCH 232/306] 420: Combine speed and duration logic for fade lighting --- src/p_lights.c | 61 ++++++++++++++------------------------------------ src/p_saveg.c | 4 ++-- src/p_spec.h | 4 ++-- 3 files changed, 21 insertions(+), 48 deletions(-) diff --git a/src/p_lights.c b/src/p_lights.c index 8bcdd8ce0..6eb9b02ca 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -13,6 +13,7 @@ /// Fire flicker, light flash, strobe flash, lightning flash, glow, and fade. #include "doomdef.h" +#include "doomstat.h" #include "p_local.h" #include "r_state.h" #include "z_zone.h" @@ -327,7 +328,8 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, * * \param sector Target sector * \param destvalue The final light value in these sectors. - * \param speed Speed of the fade; the change to the ligh + * \param speed If tic-based: total duration of effect. + * If speed-based: Speed of the fade; the change to the ligh * level in each sector per tic. * \param ticbased Use a specific duration for the fade, defined by speed * \sa T_LightFade @@ -357,13 +359,13 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean if (ticbased) { ll->ticbased = true; - ll->timer = ll->speed = abs(speed); // use ll->speed for total duration + ll->timer = ll->duration = abs(speed); // speed means duration } else { ll->ticbased = false; - ll->timer = -1; - ll->speed = abs(speed); + ll->timer = abs(ll->destlevel - ll->sourcelevel); + ll->duration = abs(speed); // ll->duration is used as speed } } @@ -382,49 +384,20 @@ void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased) */ void T_LightFade(lightlevel_t *ll) { - if (ll->ticbased) + if ((ll->ticbased && --ll->timer <= 0) + || (!ll->ticbased && (ll->timer -= ll->duration) <= 0)) { - if (--ll->timer <= 0) - { - ll->sector->lightlevel = ll->destlevel; // set to dest lightlevel - P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker - } - else - { - INT16 delta = abs(ll->destlevel - ll->sourcelevel); - fixed_t factor = min(FixedDiv(ll->speed - ll->timer, ll->speed), 1*FRACUNIT); - if (ll->destlevel < ll->sourcelevel) - ll->sector->lightlevel = max(min(ll->sector->lightlevel, ll->sourcelevel - (INT16)FixedMul(delta, factor)), ll->destlevel); - else if (ll->destlevel > ll->sourcelevel) - ll->sector->lightlevel = min(max(ll->sector->lightlevel, ll->sourcelevel + (INT16)FixedMul(delta, factor)), ll->destlevel); - } - return; - } - - if (ll->sector->lightlevel < ll->destlevel) - { - // increase the lightlevel - if (ll->sector->lightlevel + ll->speed >= ll->destlevel) - { - // stop changing light level - ll->sector->lightlevel = ll->destlevel; // set to dest lightlevel - - P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker - } - else - ll->sector->lightlevel += ll->speed; // move lightlevel + ll->sector->lightlevel = ll->destlevel; // set to dest lightlevel + P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker } else { - // decrease lightlevel - if (ll->sector->lightlevel - ll->speed <= ll->destlevel) - { - // stop changing light level - ll->sector->lightlevel = ll->destlevel; // set to dest lightlevel - - P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker - } - else - ll->sector->lightlevel -= ll->speed; // move lightlevel + INT16 delta = abs(ll->destlevel - ll->sourcelevel); + INT32 duration = ll->ticbased ? ll->duration : delta; // speed-based: timer's initial value is equal to delta + fixed_t factor = min(FixedDiv(duration - ll->timer, duration), 1*FRACUNIT); + if (ll->destlevel < ll->sourcelevel) + ll->sector->lightlevel = max(min(ll->sector->lightlevel, ll->sourcelevel - (INT16)FixedMul(delta, factor)), ll->destlevel); + else if (ll->destlevel > ll->sourcelevel) + ll->sector->lightlevel = min(max(ll->sector->lightlevel, ll->sourcelevel + (INT16)FixedMul(delta, factor)), ll->destlevel); } } diff --git a/src/p_saveg.c b/src/p_saveg.c index 574f871bb..b2d430d1e 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1561,8 +1561,8 @@ static void SaveLightlevelThinker(const thinker_t *th, const UINT8 type) WRITEUINT32(save_p, SaveSector(ht->sector)); WRITEINT16(save_p, ht->sourcelevel); WRITEINT16(save_p, ht->destlevel); - WRITEINT16(save_p, ht->speed); WRITEUINT8(save_p, (UINT8)ht->ticbased); + WRITEINT16(save_p, ht->duration); WRITEINT32(save_p, ht->timer); } @@ -2537,8 +2537,8 @@ static inline void LoadLightlevelThinker(actionf_p1 thinker) ht->sector = LoadSector(READUINT32(save_p)); ht->sourcelevel = READINT16(save_p); ht->destlevel = READINT16(save_p); - ht->speed = READINT16(save_p); ht->ticbased = (boolean)READUINT8(save_p); + ht->duration = READINT16(save_p); ht->timer = READINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; diff --git a/src/p_spec.h b/src/p_spec.h index 69087d6c4..daa6dd18a 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -138,11 +138,11 @@ typedef struct sector_t *sector; ///< Sector where action is taking place. INT16 sourcelevel; ///< Light level we're fading from. INT16 destlevel; ///< Light level we're fading to. - INT16 speed; ///< Speed at which to change light level. OR: Tic-based duration // Tic-based behavior boolean ticbased; ///< Tic-based logic - INT32 timer; ///< Tic-based timer + INT16 duration; ///< If tic-based: duration of effect. If speed-based: amount to increment + INT32 timer; ///< Internal timer } lightlevel_t; #define GLOWSPEED 8 From d939e597a5a5fa5a8e89c34edfcc12cce6e3fc2e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 15 Sep 2018 20:03:43 -0400 Subject: [PATCH 233/306] 420: Unncessary include --- src/p_lights.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/p_lights.c b/src/p_lights.c index 6eb9b02ca..e4d7ebe9d 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -13,7 +13,6 @@ /// Fire flicker, light flash, strobe flash, lightning flash, glow, and fade. #include "doomdef.h" -#include "doomstat.h" #include "p_local.h" #include "r_state.h" #include "z_zone.h" From 350cd1435b55449a0ed9b6feee21cd8ba289fd19 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sat, 15 Sep 2018 12:21:25 +0200 Subject: [PATCH 234/306] The thinker is entirely unified now, and there is no difference in the light levels between the "old" behavior and this one now. --- src/p_lights.c | 33 ++++++++++++++++----------------- src/p_saveg.c | 8 ++++---- src/p_spec.h | 16 ++++++++-------- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/p_lights.c b/src/p_lights.c index e4d7ebe9d..00c0e960f 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -355,17 +355,21 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ll->sourcelevel = sector->lightlevel; ll->destlevel = destvalue; + ll->fixedcurlevel = sector->lightlevel<ticbased = true; - ll->timer = ll->duration = abs(speed); // speed means duration + // Speed means duration. + ll->timer = abs(speed); + ll->fixedpertic = FixedDiv((destvalue<fixedcurlevel, speed<ticbased = false; - ll->timer = abs(ll->destlevel - ll->sourcelevel); - ll->duration = abs(speed); // ll->duration is used as speed + // Speed means increment per tic (literally speed). + ll->timer = FixedDiv((destvalue<fixedcurlevel, speed<>FRACBITS; + ll->fixedpertic = speed<sector->lightlevel, destvalue, ll->fixedpertic>>FRACBITS, ll->timer); } void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased) @@ -383,20 +387,15 @@ void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased) */ void T_LightFade(lightlevel_t *ll) { - if ((ll->ticbased && --ll->timer <= 0) - || (!ll->ticbased && (ll->timer -= ll->duration) <= 0)) + if (--ll->timer <= 0) { ll->sector->lightlevel = ll->destlevel; // set to dest lightlevel P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker + CONS_Printf("End tic, final light value: %d\n", ll->sector->lightlevel); + return; } - else - { - INT16 delta = abs(ll->destlevel - ll->sourcelevel); - INT32 duration = ll->ticbased ? ll->duration : delta; // speed-based: timer's initial value is equal to delta - fixed_t factor = min(FixedDiv(duration - ll->timer, duration), 1*FRACUNIT); - if (ll->destlevel < ll->sourcelevel) - ll->sector->lightlevel = max(min(ll->sector->lightlevel, ll->sourcelevel - (INT16)FixedMul(delta, factor)), ll->destlevel); - else if (ll->destlevel > ll->sourcelevel) - ll->sector->lightlevel = min(max(ll->sector->lightlevel, ll->sourcelevel + (INT16)FixedMul(delta, factor)), ll->destlevel); - } + + ll->fixedcurlevel = ll->fixedcurlevel + ll->fixedpertic; + ll->sector->lightlevel = (ll->fixedcurlevel)>>FRACBITS; + CONS_Printf("Light %d\n", ll->sector->lightlevel); } diff --git a/src/p_saveg.c b/src/p_saveg.c index b2d430d1e..c95a08361 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1561,8 +1561,8 @@ static void SaveLightlevelThinker(const thinker_t *th, const UINT8 type) WRITEUINT32(save_p, SaveSector(ht->sector)); WRITEINT16(save_p, ht->sourcelevel); WRITEINT16(save_p, ht->destlevel); - WRITEUINT8(save_p, (UINT8)ht->ticbased); - WRITEINT16(save_p, ht->duration); + WRITEFIXED(save_p, ht->fixedcurlevel); + WRITEFIXED(save_p, ht->fixedpertic); WRITEINT32(save_p, ht->timer); } @@ -2537,8 +2537,8 @@ static inline void LoadLightlevelThinker(actionf_p1 thinker) ht->sector = LoadSector(READUINT32(save_p)); ht->sourcelevel = READINT16(save_p); ht->destlevel = READINT16(save_p); - ht->ticbased = (boolean)READUINT8(save_p); - ht->duration = READINT16(save_p); + ht->fixedcurlevel = READFIXED(save_p); + ht->fixedpertic = READFIXED(save_p); ht->timer = READINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; diff --git a/src/p_spec.h b/src/p_spec.h index daa6dd18a..2c9e986ce 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -134,15 +134,15 @@ typedef struct */ typedef struct { - thinker_t thinker; ///< Thinker in use for the effect. - sector_t *sector; ///< Sector where action is taking place. - INT16 sourcelevel; ///< Light level we're fading from. - INT16 destlevel; ///< Light level we're fading to. + thinker_t thinker; ///< Thinker in use for the effect. + sector_t *sector; ///< Sector where action is taking place. + INT16 sourcelevel; ///< Light level we're fading from. + INT16 destlevel; ///< Light level we're fading to. - // Tic-based behavior - boolean ticbased; ///< Tic-based logic - INT16 duration; ///< If tic-based: duration of effect. If speed-based: amount to increment - INT32 timer; ///< Internal timer + fixed_t fixedcurlevel; ///< Fixed point for current light level. + fixed_t fixedpertic; ///< Fixed point for increment per tic. + // The reason for those two above to be fixed point is to deal with decimal values that would otherwise get trimmed away. + INT32 timer; ///< Internal timer. } lightlevel_t; #define GLOWSPEED 8 From 17e23f55eb700a28d19029e6b5a4938acdd21473 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 15 Sep 2018 20:00:04 -0400 Subject: [PATCH 235/306] 492: Merge speed and duration logic for fade polyobject --- src/p_polyobj.c | 68 ++++++++++++++++--------------------------------- src/p_polyobj.h | 2 +- src/p_saveg.c | 4 +-- 3 files changed, 25 insertions(+), 49 deletions(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index f7545e5bd..bbcf4f42a 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -2873,54 +2873,29 @@ void T_PolyObjFade(polyfade_t *th) if (po->thinker == NULL) po->thinker = &th->thinker; - if (th->ticbased) + stillfading = th->ticbased ? !(--(th->timer) <= 0) + : !((th->timer -= th->duration) <= 0); + + if (th->timer <= 0) { - stillfading = !(--(th->timer) <= 0); + po->translucency = max(min(th->destvalue, NUMTRANSMAPS), 0); - if (th->timer <= 0) - { - po->translucency = max(min(th->destvalue, NUMTRANSMAPS), 0); - - // remove thinker - if (po->thinker == &th->thinker) - po->thinker = NULL; - P_RemoveThinker(&th->thinker); - } - else - { - INT16 delta = abs(th->destvalue - th->sourcevalue); - fixed_t factor = min(FixedDiv(th->speed - th->timer, th->speed), 1*FRACUNIT); - if (th->destvalue < th->sourcevalue) - po->translucency = max(min(po->translucency, th->sourcevalue - (INT16)FixedMul(delta, factor)), th->destvalue); - else if (th->destvalue > th->sourcevalue) - po->translucency = min(max(po->translucency, th->sourcevalue + (INT16)FixedMul(delta, factor)), th->destvalue); - } + // remove thinker + if (po->thinker == &th->thinker) + po->thinker = NULL; + P_RemoveThinker(&th->thinker); } else { - fixed_t timerdest = FixedMul(FixedDiv(256, NUMTRANSMAPS), NUMTRANSMAPS-th->destvalue); - - if (th->destvalue > th->sourcevalue) // fading out, destvalue is higher - { - // for timer, lower is transparent, higher is opaque - stillfading = (th->timer > timerdest); - th->timer = max(timerdest, th->timer - th->speed); - } - else if (th->destvalue < th->sourcevalue) // fading in, destvalue is lower - { stillfading = (th->timer < timerdest); - th->timer = min(timerdest, th->timer + th->speed); - } - - if (!stillfading) - { - po->translucency = max(min(th->destvalue, NUMTRANSMAPS), 0); - // remove thinker - if (po->thinker == &th->thinker) - po->thinker = NULL; - P_RemoveThinker(&th->thinker); - } - else - po->translucency = FixedDiv(256-th->timer, FixedDiv(256, NUMTRANSMAPS)); + INT16 delta = abs(th->destvalue - th->sourcevalue); + INT32 duration = th->ticbased ? th->duration + : abs(FixedMul(FixedDiv(256, NUMTRANSMAPS), NUMTRANSMAPS - th->destvalue) + - FixedMul(FixedDiv(256, NUMTRANSMAPS), NUMTRANSMAPS - th->sourcevalue)); // speed-based internal counter duration: delta in 256 scale + fixed_t factor = min(FixedDiv(duration - th->timer, duration), 1*FRACUNIT); + if (th->destvalue < th->sourcevalue) + po->translucency = max(min(po->translucency, th->sourcevalue - (INT16)FixedMul(delta, factor)), th->destvalue); + else if (th->destvalue > th->sourcevalue) + po->translucency = min(max(po->translucency, th->sourcevalue + (INT16)FixedMul(delta, factor)), th->destvalue); } if (!stillfading) @@ -3010,13 +2985,14 @@ INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata) if (pfdata->ticbased) { th->ticbased = true; - th->timer = th->speed = abs(pfdata->speed); // use th->speed for total duration + th->timer = th->duration = abs(pfdata->speed); // pfdata->speed is duration } else { th->ticbased = false; - th->timer = FixedMul(FixedDiv(256, NUMTRANSMAPS), NUMTRANSMAPS - po->translucency); // use as internal counter - th->speed = pfdata->speed; + th->timer = abs(FixedMul(FixedDiv(256, NUMTRANSMAPS), NUMTRANSMAPS - th->destvalue) + - FixedMul(FixedDiv(256, NUMTRANSMAPS), NUMTRANSMAPS - th->sourcevalue)); // delta converted to 256 scale, use as internal counter + th->duration = abs(pfdata->speed); // use th->duration as speed decrement } oldpo = po; diff --git a/src/p_polyobj.h b/src/p_polyobj.h index 61404112c..524518f2a 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -217,8 +217,8 @@ typedef struct polyfade_s boolean docollision; boolean doghostfade; boolean ticbased; + INT32 duration; INT32 timer; - INT32 speed; } polyfade_t; // diff --git a/src/p_saveg.c b/src/p_saveg.c index 2bfc5859a..11c481be8 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1710,8 +1710,8 @@ static void SavePolyfadeThinker(const thinker_t *th, const UINT8 type) WRITEUINT8(save_p, (UINT8)ht->docollision); WRITEUINT8(save_p, (UINT8)ht->doghostfade); WRITEUINT8(save_p, (UINT8)ht->ticbased); + WRITEINT32(save_p, ht->duration); WRITEINT32(save_p, ht->timer); - WRITEINT32(save_p, ht->speed); } #endif @@ -2725,8 +2725,8 @@ static void LoadPolyfadeThinker(actionf_p1 thinker) ht->docollision = (boolean)READUINT8(save_p); ht->doghostfade = (boolean)READUINT8(save_p); ht->ticbased = (boolean)READUINT8(save_p); + ht->duration = READINT32(save_p); ht->timer = READINT32(save_p); - ht->speed = READINT32(save_p); P_AddThinker(&ht->thinker); } #endif From 1321ab9d927868a565af6f0d0be1c31c5d023722 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 15 Sep 2018 20:34:19 -0400 Subject: [PATCH 236/306] 453: Extra parameter for Add_ColormapFader --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 8cbe2e369..b5607e2b2 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7945,7 +7945,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor Z_Free(exc); } - Add_ColormapFader(§ors[rover->secnum], source_exc, d->dest_exc, + Add_ColormapFader(§ors[rover->secnum], source_exc, d->dest_exc, true, ticbased ? d->timer : FixedFloor(FixedDiv(abs(d->destvalue - d->alpha), d->speed))/FRACUNIT); } From d49f0be4ee11b57678c8ef1230063463d6c0c432 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 16 Sep 2018 08:20:14 -0400 Subject: [PATCH 237/306] 420: Strip test comments --- src/p_lights.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/p_lights.c b/src/p_lights.c index 00c0e960f..2ea93b796 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -369,7 +369,6 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ll->timer = FixedDiv((destvalue<fixedcurlevel, speed<>FRACBITS; ll->fixedpertic = speed<sector->lightlevel, destvalue, ll->fixedpertic>>FRACBITS, ll->timer); } void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased) @@ -391,11 +390,9 @@ void T_LightFade(lightlevel_t *ll) { ll->sector->lightlevel = ll->destlevel; // set to dest lightlevel P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker - CONS_Printf("End tic, final light value: %d\n", ll->sector->lightlevel); return; } ll->fixedcurlevel = ll->fixedcurlevel + ll->fixedpertic; ll->sector->lightlevel = (ll->fixedcurlevel)>>FRACBITS; - CONS_Printf("Light %d\n", ll->sector->lightlevel); } From 1b7b1f3f796eb08385f86e817b4486ec3a25361a Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 16 Sep 2018 20:25:07 +0100 Subject: [PATCH 238/306] Fix order of operations messups by adding brackets --- src/m_anigif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_anigif.c b/src/m_anigif.c index d46d889bb..e2af70095 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -492,7 +492,7 @@ static void GIF_framewrite(void) // screen regions are handled in GIF_lzw { - int d1 = (int)((100.0/NEWTICRATE)*gif_frames+1); + int d1 = (int)((100.0/NEWTICRATE)*(gif_frames+1)); int d2 = (int)((100.0/NEWTICRATE)*(gif_frames)); UINT16 delay = d1-d2; INT32 startline; From 4cdbc7249ff5a6af8d1b01994950359b16554c73 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 16 Sep 2018 20:02:29 -0400 Subject: [PATCH 239/306] Streamlined colormap netsyncing so duplicates are not saved to $$$.sav per sector --- src/p_saveg.c | 196 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 155 insertions(+), 41 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index f9841717e..a63ef1276 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -474,50 +474,144 @@ static void P_NetUnArchivePlayers(void) } } -static void SaveExtraColormap(UINT8 *put, extracolormap_t *exc) +/// +/// Colormaps +/// + +static extracolormap_t *net_colormaps = NULL; +static UINT32 num_net_colormaps = 0; + +// Copypasta from r_data.c AddColormapToList +// But also check for equality and return the matching index +static UINT32 CheckAddNetColormapToList(extracolormap_t *extra_colormap) { - if (!exc) // Just give it default values, we done goofed. (or sector->extra_colormap was intentionally set to default (NULL)) - exc = R_GetDefaultColormap(); + extracolormap_t *exc; + UINT32 i = 0; - WRITEUINT8(put, exc->fadestart); - WRITEUINT8(put, exc->fadeend); - WRITEUINT8(put, exc->fog); + if (!net_colormaps) + { + net_colormaps = extra_colormap; + net_colormaps->next = 0; + net_colormaps->prev = 0; + return i; + } - WRITEINT32(put, exc->rgba); - WRITEINT32(put, exc->fadergba); + for (exc = net_colormaps; exc->next; exc = exc->next) + { + if (R_CheckEqualColormaps(exc, extra_colormap, true, true, true)) + return i; + i++; + } -#ifdef EXTRACOLORMAPLUMPS - WRITESTRINGN(put, exc->lumpname, 9); -#endif + exc->next = extra_colormap; + extra_colormap->prev = exc; + extra_colormap->next = 0; + + num_net_colormaps = i; + return i; } -static extracolormap_t *LoadExtraColormap(UINT8 *get) +static extracolormap_t *GetNetColormapFromList(UINT32 index) { - extracolormap_t *exc, *exc_exist; + // For loading, we have to be tricky: + // We load the sectors BEFORE knowing the colormap values + // So if an index doesn't exist, fill our list with dummy colormaps + // until we get the index we want + // Then when we load the color data, we set up the dummy colormaps - UINT8 fadestart = READUINT8(get), - fadeend = READUINT8(get), - fog = READUINT8(get); + extracolormap_t *exc, *last_exc = NULL; + UINT32 i = 0; - INT32 rgba = READINT32(get), - fadergba = READINT32(get); + for (exc = net_colormaps; exc; last_exc = exc, exc = exc->next) + { + if (i++ == index) + return exc; + } + + // our index doesn't exist, so just make the entry + for (; i <= index && i < num_net_colormaps; i++) + { + exc = R_CreateDefaultColormap(false); + if (last_exc) + last_exc->next = exc; + exc->prev = last_exc; + exc->next = NULL; + last_exc = exc; + } + return exc; +} + +static void ClearNetColormaps(void) +{ + // We're actually Z_Freeing each entry here, + // so don't call this in P_NetUnArchiveColormaps (where entries will be used in-game) + extracolormap_t *exc, *exc_next; + + for (exc = net_colormaps; exc; exc = exc_next) + { + exc_next = exc->next; + Z_Free(exc); + } + num_net_colormaps = 0; + net_colormaps = NULL; +} + +static void P_NetArchiveColormaps() +{ + // We save and then we clean up our colormap mess + extracolormap_t *exc, *exc_next; + + WRITEUINT32(save_p, num_net_colormaps); // save for safety + + for (exc = net_colormaps; exc; exc = exc_next) + { + WRITEUINT8(save_p, exc->fadestart); + WRITEUINT8(save_p, exc->fadeend); + WRITEUINT8(save_p, exc->fog); + + WRITEINT32(save_p, exc->rgba); + WRITEINT32(save_p, exc->fadergba); #ifdef EXTRACOLORMAPLUMPS - char lumpname[9]; - READSTRINGN(get, lumpname, 9); - - if (lumpname[0]) - return R_ColormapForName(lumpname); + WRITESTRINGN(save_p, exc->lumpname, 9); #endif - exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog); - if (!exc) + exc_next = exc->next; + Z_Free(exc); // don't need anymore + } + + num_net_colormaps = 0; +} + +static void P_NetUnArchiveColormaps() +{ + // When we reach this point, we already populated our list with + // dummy colormaps. Now that we are loading the color data, + // set up the dummies. + extracolormap_t *exc, *existing_exc; + num_net_colormaps = READUINT32(save_p); + + for (exc = net_colormaps; exc; exc = exc->next) { - // CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - // R_GetRgbaR(rgba), R_GetRgbaG(rgba), R_GetRgbaB(rgba), R_GetRgbaA(rgba), - // R_GetRgbaR(fadergba), R_GetRgbaG(fadergba), R_GetRgbaB(fadergba), R_GetRgbaA(fadergba)); + UINT8 fadestart = READUINT8(save_p), + fadeend = READUINT8(save_p), + fog = READUINT8(save_p); - exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); + INT32 rgba = READINT32(save_p), + fadergba = READINT32(save_p); + +#ifdef EXTRACOLORMAPLUMPS + char lumpname[9]; + READSTRINGN(save_p, lumpname, 9); + + if (lumpname[0]) + { + existing_exc = R_ColormapForName(lumpname); + *exc = *existing_exc; + R_AddColormapToList(exc); // see HACK note below on why we're adding duplicates + continue; + } +#endif exc->fadestart = fadestart; exc->fadeend = fadeend; @@ -531,21 +625,32 @@ static extracolormap_t *LoadExtraColormap(UINT8 *get) exc->lumpname[0] = 0; #endif - if (!(exc_exist = R_GetColormapFromList(exc))) - { - exc->colormap = R_CreateLightTable(exc); - R_AddColormapToList(exc); - } + existing_exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog); + + if (existing_exc) + exc->colormap = existing_exc->colormap; else - { - Z_Free(exc); - exc = R_CheckDefaultColormap(exc_exist, true, true, true) ? NULL : exc_exist; - } + // CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + // R_GetRgbaR(rgba), R_GetRgbaG(rgba), R_GetRgbaB(rgba), R_GetRgbaA(rgba), + // R_GetRgbaR(fadergba), R_GetRgbaG(fadergba), R_GetRgbaB(fadergba), R_GetRgbaA(fadergba)); + exc->colormap = R_CreateLightTable(exc); + + // HACK: If this dummy is a duplicate, we're going to add it + // to the extra_colormaps list anyway. I think this is faster + // than going through every loaded sector and correcting their + // colormap address to the pre-existing one, PER net_colormap entry + R_AddColormapToList(exc); } - return exc; + // Don't need these anymore + num_net_colormaps = 0; + net_colormaps = NULL; } +/// +/// World Archiving +/// + #define SD_FLOORHT 0x01 #define SD_CEILHT 0x02 #define SD_FLOORPIC 0x04 @@ -595,6 +700,9 @@ static void P_NetArchiveWorld(void) const side_t *si; UINT8 *put; + // initialize colormap vars because paranoia + ClearNetColormaps(); + // reload the map just to see difference mapsector_t *ms; mapsidedef_t *msd; @@ -730,7 +838,8 @@ static void P_NetArchiveWorld(void) } if (diff3 & SD_COLORMAP) - SaveExtraColormap(put, ss->extra_colormap); + WRITEUINT32(put, CheckAddNetColormapToList(ss->extra_colormap)); + // returns existing index if already added, or appends to net_colormaps and returns new index // Special case: save the stats of all modified ffloors along with their ffloor "number"s // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed @@ -865,6 +974,9 @@ static void P_NetUnArchiveWorld(void) if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD) I_Error("Bad $$$.sav at archive block World"); + // initialize colormap vars because paranoia + ClearNetColormaps(); + get = save_p; for (;;) @@ -927,7 +1039,7 @@ static void P_NetUnArchiveWorld(void) } if (diff3 & SD_COLORMAP) - sectors[i].extra_colormap = LoadExtraColormap(get); + sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(get)); if (diff & SD_FFLOORS) { @@ -3536,6 +3648,7 @@ void P_SaveNetGame(void) #endif P_NetArchiveThinkers(); P_NetArchiveSpecials(); + P_NetArchiveColormaps(); } #ifdef HAVE_BLUA LUA_Archive(); @@ -3578,6 +3691,7 @@ boolean P_LoadNetGame(void) #endif P_NetUnArchiveThinkers(); P_NetUnArchiveSpecials(); + P_NetUnArchiveColormaps(); P_RelinkPointers(); P_FinishMobjs(); } From d4a18fd456749c6d3db6c1055bf2e1972d60c460 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 16 Sep 2018 20:27:24 -0400 Subject: [PATCH 240/306] 455: Fade colormap netsync use new colormap saving --- src/p_saveg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index cea40a4e9..109102dfc 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1795,8 +1795,8 @@ static void SaveFadeColormapThinker(const thinker_t *th, const UINT8 type) const fadecolormap_t *ht = (const void *)th; WRITEUINT8(save_p, type); WRITEUINT32(save_p, SaveSector(ht->sector)); - SaveExtraColormap(save_p, ht->source_exc); - SaveExtraColormap(save_p, ht->dest_exc); + WRITEUINT32(save_p, CheckAddNetColormapToList(ht->source_exc)); + WRITEUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc)); WRITEUINT8(save_p, (UINT8)ht->ticbased); WRITEINT32(save_p, ht->duration); WRITEINT32(save_p, ht->timer); @@ -2795,8 +2795,8 @@ static inline void LoadFadeColormapThinker(actionf_p1 thinker) fadecolormap_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; ht->sector = LoadSector(READUINT32(save_p)); - ht->source_exc = LoadExtraColormap(save_p); - ht->dest_exc = LoadExtraColormap(save_p); + ht->source_exc = GetNetColormapFromList(READUINT32(save_p)); + ht->dest_exc = GetNetColormapFromList(READUINT32(save_p)); ht->ticbased = (boolean)READUINT8(save_p); ht->duration = READINT32(save_p); ht->timer = READINT32(save_p); From 0a998fec02a84981008fad81163d40765d979341 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 16 Sep 2018 22:41:08 -0400 Subject: [PATCH 241/306] New colormap netsync fixes --- src/p_saveg.c | 79 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 109102dfc..517211726 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -485,29 +485,30 @@ static UINT32 num_net_colormaps = 0; // But also check for equality and return the matching index static UINT32 CheckAddNetColormapToList(extracolormap_t *extra_colormap) { - extracolormap_t *exc; + extracolormap_t *exc, *exc_prev; UINT32 i = 0; if (!net_colormaps) { - net_colormaps = extra_colormap; + net_colormaps = R_CopyColormap(extra_colormap, false); net_colormaps->next = 0; net_colormaps->prev = 0; + num_net_colormaps = i+1; return i; } - for (exc = net_colormaps; exc->next; exc = exc->next) + for (exc = net_colormaps; exc; exc_prev = exc, exc = exc->next) { if (R_CheckEqualColormaps(exc, extra_colormap, true, true, true)) return i; i++; } - exc->next = extra_colormap; - extra_colormap->prev = exc; + exc_prev->next = R_CopyColormap(extra_colormap, false); + extra_colormap->prev = exc_prev; extra_colormap->next = 0; - num_net_colormaps = i; + num_net_colormaps = i+1; return i; } @@ -522,14 +523,24 @@ static extracolormap_t *GetNetColormapFromList(UINT32 index) extracolormap_t *exc, *last_exc = NULL; UINT32 i = 0; + if (!net_colormaps) // initialize our list + net_colormaps = R_CreateDefaultColormap(false); + for (exc = net_colormaps; exc; last_exc = exc, exc = exc->next) { if (i++ == index) return exc; } + + // LET'S HOPE that index is a sane value, because we create up to [index] + // entries in net_colormaps. At this point, we don't know + // what the total colormap count is + if (index >= numsectors*3) // if every sector had a unique colormap change AND a fade thinker which has two colormap entries + I_Error("Colormap %d from server is too high for sectors %d", index, numsectors); + // our index doesn't exist, so just make the entry - for (; i <= index && i < num_net_colormaps; i++) + for (; i <= index; i++) { exc = R_CreateDefaultColormap(false); if (last_exc) @@ -556,15 +567,20 @@ static void ClearNetColormaps(void) net_colormaps = NULL; } -static void P_NetArchiveColormaps() +static void P_NetArchiveColormaps(void) { // We save and then we clean up our colormap mess extracolormap_t *exc, *exc_next; - + UINT32 i = 0; WRITEUINT32(save_p, num_net_colormaps); // save for safety - for (exc = net_colormaps; exc; exc = exc_next) + for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next) { + // We must save num_net_colormaps worth of data + // So fill non-existent entries with default. + if (!exc) + exc = R_CreateDefaultColormap(false); + WRITEUINT8(save_p, exc->fadestart); WRITEUINT8(save_p, exc->fadeend); WRITEUINT8(save_p, exc->fog); @@ -581,31 +597,44 @@ static void P_NetArchiveColormaps() } num_net_colormaps = 0; + net_colormaps = NULL; } -static void P_NetUnArchiveColormaps() +static void P_NetUnArchiveColormaps(void) { // When we reach this point, we already populated our list with // dummy colormaps. Now that we are loading the color data, // set up the dummies. - extracolormap_t *exc, *existing_exc; + extracolormap_t *exc, *existing_exc, *exc_next = NULL; num_net_colormaps = READUINT32(save_p); + UINT32 i = 0; - for (exc = net_colormaps; exc; exc = exc->next) + for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next) { - UINT8 fadestart = READUINT8(save_p), - fadeend = READUINT8(save_p), - fog = READUINT8(save_p); - - INT32 rgba = READINT32(save_p), - fadergba = READINT32(save_p); - + UINT8 fadestart, fadeend, fog; + INT32 rgba, fadergba; #ifdef EXTRACOLORMAPLUMPS char lumpname[9]; +#endif + + fadestart = READUINT8(save_p); + fadeend = READUINT8(save_p); + fog = READUINT8(save_p); + + rgba = READINT32(save_p); + fadergba = READINT32(save_p); + +#ifdef EXTRACOLORMAPLUMPS READSTRINGN(save_p, lumpname, 9); if (lumpname[0]) { + if (!exc) + // no point making a new entry since nothing points to it, + // but we needed to read the data so now continue + continue; + + exc_next = exc->next; // this gets overwritten during our operations here, so get it now existing_exc = R_ColormapForName(lumpname); *exc = *existing_exc; R_AddColormapToList(exc); // see HACK note below on why we're adding duplicates @@ -613,6 +642,13 @@ static void P_NetUnArchiveColormaps() } #endif + if (!exc) + // no point making a new entry since nothing points to it, + // but we needed to read the data so now continue + continue; + + exc_next = exc->next; // this gets overwritten during our operations here, so get it now + exc->fadestart = fadestart; exc->fadeend = fadeend; exc->fog = fog; @@ -640,6 +676,9 @@ static void P_NetUnArchiveColormaps() // than going through every loaded sector and correcting their // colormap address to the pre-existing one, PER net_colormap entry R_AddColormapToList(exc); + + if (i < num_net_colormaps-1 && !exc_next) + exc_next = R_CreateDefaultColormap(false); } // Don't need these anymore From 4b55415add356e051d494cd5bc8d36c316f54456 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 16 Sep 2018 22:41:08 -0400 Subject: [PATCH 242/306] New colormap netsync fixes --- src/p_saveg.c | 79 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index a63ef1276..34d08d709 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -485,29 +485,30 @@ static UINT32 num_net_colormaps = 0; // But also check for equality and return the matching index static UINT32 CheckAddNetColormapToList(extracolormap_t *extra_colormap) { - extracolormap_t *exc; + extracolormap_t *exc, *exc_prev; UINT32 i = 0; if (!net_colormaps) { - net_colormaps = extra_colormap; + net_colormaps = R_CopyColormap(extra_colormap, false); net_colormaps->next = 0; net_colormaps->prev = 0; + num_net_colormaps = i+1; return i; } - for (exc = net_colormaps; exc->next; exc = exc->next) + for (exc = net_colormaps; exc; exc_prev = exc, exc = exc->next) { if (R_CheckEqualColormaps(exc, extra_colormap, true, true, true)) return i; i++; } - exc->next = extra_colormap; - extra_colormap->prev = exc; + exc_prev->next = R_CopyColormap(extra_colormap, false); + extra_colormap->prev = exc_prev; extra_colormap->next = 0; - num_net_colormaps = i; + num_net_colormaps = i+1; return i; } @@ -522,14 +523,24 @@ static extracolormap_t *GetNetColormapFromList(UINT32 index) extracolormap_t *exc, *last_exc = NULL; UINT32 i = 0; + if (!net_colormaps) // initialize our list + net_colormaps = R_CreateDefaultColormap(false); + for (exc = net_colormaps; exc; last_exc = exc, exc = exc->next) { if (i++ == index) return exc; } + + // LET'S HOPE that index is a sane value, because we create up to [index] + // entries in net_colormaps. At this point, we don't know + // what the total colormap count is + if (index >= numsectors*3) // if every sector had a unique colormap change AND a fade thinker which has two colormap entries + I_Error("Colormap %d from server is too high for sectors %d", index, numsectors); + // our index doesn't exist, so just make the entry - for (; i <= index && i < num_net_colormaps; i++) + for (; i <= index; i++) { exc = R_CreateDefaultColormap(false); if (last_exc) @@ -556,15 +567,20 @@ static void ClearNetColormaps(void) net_colormaps = NULL; } -static void P_NetArchiveColormaps() +static void P_NetArchiveColormaps(void) { // We save and then we clean up our colormap mess extracolormap_t *exc, *exc_next; - + UINT32 i = 0; WRITEUINT32(save_p, num_net_colormaps); // save for safety - for (exc = net_colormaps; exc; exc = exc_next) + for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next) { + // We must save num_net_colormaps worth of data + // So fill non-existent entries with default. + if (!exc) + exc = R_CreateDefaultColormap(false); + WRITEUINT8(save_p, exc->fadestart); WRITEUINT8(save_p, exc->fadeend); WRITEUINT8(save_p, exc->fog); @@ -581,31 +597,44 @@ static void P_NetArchiveColormaps() } num_net_colormaps = 0; + net_colormaps = NULL; } -static void P_NetUnArchiveColormaps() +static void P_NetUnArchiveColormaps(void) { // When we reach this point, we already populated our list with // dummy colormaps. Now that we are loading the color data, // set up the dummies. - extracolormap_t *exc, *existing_exc; + extracolormap_t *exc, *existing_exc, *exc_next = NULL; num_net_colormaps = READUINT32(save_p); + UINT32 i = 0; - for (exc = net_colormaps; exc; exc = exc->next) + for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next) { - UINT8 fadestart = READUINT8(save_p), - fadeend = READUINT8(save_p), - fog = READUINT8(save_p); - - INT32 rgba = READINT32(save_p), - fadergba = READINT32(save_p); - + UINT8 fadestart, fadeend, fog; + INT32 rgba, fadergba; #ifdef EXTRACOLORMAPLUMPS char lumpname[9]; +#endif + + fadestart = READUINT8(save_p); + fadeend = READUINT8(save_p); + fog = READUINT8(save_p); + + rgba = READINT32(save_p); + fadergba = READINT32(save_p); + +#ifdef EXTRACOLORMAPLUMPS READSTRINGN(save_p, lumpname, 9); if (lumpname[0]) { + if (!exc) + // no point making a new entry since nothing points to it, + // but we needed to read the data so now continue + continue; + + exc_next = exc->next; // this gets overwritten during our operations here, so get it now existing_exc = R_ColormapForName(lumpname); *exc = *existing_exc; R_AddColormapToList(exc); // see HACK note below on why we're adding duplicates @@ -613,6 +642,13 @@ static void P_NetUnArchiveColormaps() } #endif + if (!exc) + // no point making a new entry since nothing points to it, + // but we needed to read the data so now continue + continue; + + exc_next = exc->next; // this gets overwritten during our operations here, so get it now + exc->fadestart = fadestart; exc->fadeend = fadeend; exc->fog = fog; @@ -640,6 +676,9 @@ static void P_NetUnArchiveColormaps() // than going through every loaded sector and correcting their // colormap address to the pre-existing one, PER net_colormap entry R_AddColormapToList(exc); + + if (i < num_net_colormaps-1 && !exc_next) + exc_next = R_CreateDefaultColormap(false); } // Don't need these anymore From f3e1d280d07a234c7070384f6d514fba32085808 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 17 Sep 2018 00:26:58 -0400 Subject: [PATCH 243/306] Colormap netsync: Mixed D+C fixes --- src/p_saveg.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 34d08d709..ec0ef2e7a 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -606,9 +606,10 @@ static void P_NetUnArchiveColormaps(void) // dummy colormaps. Now that we are loading the color data, // set up the dummies. extracolormap_t *exc, *existing_exc, *exc_next = NULL; - num_net_colormaps = READUINT32(save_p); UINT32 i = 0; + num_net_colormaps = READUINT32(save_p); + for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next) { UINT8 fadestart, fadeend, fog; @@ -739,9 +740,6 @@ static void P_NetArchiveWorld(void) const side_t *si; UINT8 *put; - // initialize colormap vars because paranoia - ClearNetColormaps(); - // reload the map just to see difference mapsector_t *ms; mapsidedef_t *msd; @@ -749,6 +747,9 @@ static void P_NetArchiveWorld(void) const sector_t *ss = sectors; UINT8 diff, diff2, diff3; + // initialize colormap vars because paranoia + ClearNetColormaps(); + WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD); put = save_p; From 14339d651d970c9c382443200da62ffc321cf46d Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 17 Sep 2018 00:34:03 -0400 Subject: [PATCH 244/306] 453: Use new colormap netsync for fade FOF thinker --- src/p_saveg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index f57b44817..f4f698d4f 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1609,7 +1609,7 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type) { const fade_t *ht = (const void *)th; WRITEUINT8(save_p, type); - SaveExtraColormap(save_p, ht->dest_exc); + WRITEUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc)); WRITEUINT32(save_p, ht->sectornum); WRITEUINT32(save_p, ht->ffloornum); WRITEINT32(save_p, ht->alpha); @@ -2624,7 +2624,7 @@ static inline void LoadFadeThinker(actionf_p1 thinker) sector_t *ss; fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->dest_exc = LoadExtraColormap(save_p); + ht->dest_exc = GetNetColormapFromList(READUINT32(save_p)); ht->sectornum = READUINT32(save_p); ht->ffloornum = READUINT32(save_p); ht->alpha = READINT32(save_p); From 752a9630372d787625459050053ffae98a8a6689 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 17 Sep 2018 08:05:51 -0400 Subject: [PATCH 245/306] Colormap netsync: String format numsectors to UINT32 (thanks buildbot) --- src/p_saveg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index ec0ef2e7a..b98a34436 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -537,7 +537,7 @@ static extracolormap_t *GetNetColormapFromList(UINT32 index) // entries in net_colormaps. At this point, we don't know // what the total colormap count is if (index >= numsectors*3) // if every sector had a unique colormap change AND a fade thinker which has two colormap entries - I_Error("Colormap %d from server is too high for sectors %d", index, numsectors); + I_Error("Colormap %d from server is too high for sectors %d", index, (UINT32)numsectors); // our index doesn't exist, so just make the entry for (; i <= index; i++) From d417f733e5b00c54233c36d8b61b69f14d5ba996 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 17 Sep 2018 10:24:55 -0400 Subject: [PATCH 246/306] Colormap netsync: Handle unaccounted dummy colormaps properly --- src/p_saveg.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index b98a34436..c0f98d88b 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -682,6 +682,20 @@ static void P_NetUnArchiveColormaps(void) exc_next = R_CreateDefaultColormap(false); } + // if we still have a valid net_colormap after iterating up to num_net_colormaps, + // some sector had a colormap index higher than num_net_colormaps. We done goofed or $$$ was corrupted. + // In any case, add them to the colormap list too so that at least the sectors' colormap + // addresses are valid and accounted properly + if (exc_next) + { + existing_exc = R_GetDefaultColormap(); + for (exc = exc_next; exc; exc = exc->next) + { + exc->colormap = existing_exc->colormap; // all our dummies are default values + R_AddColormapToList(exc); + } + } + // Don't need these anymore num_net_colormaps = 0; net_colormaps = NULL; From 69a4906911aa206ac0dffc10a5b5536e692edbb7 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 17 Sep 2018 10:38:09 -0400 Subject: [PATCH 247/306] Colormap netsync: Count ffloors for colormap loading upper limit --- src/p_saveg.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index c0f98d88b..b8af7cff6 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -480,6 +480,7 @@ static void P_NetUnArchivePlayers(void) static extracolormap_t *net_colormaps = NULL; static UINT32 num_net_colormaps = 0; +static UINT32 num_ffloors = 0; // for loading // Copypasta from r_data.c AddColormapToList // But also check for equality and return the matching index @@ -536,7 +537,9 @@ static extracolormap_t *GetNetColormapFromList(UINT32 index) // LET'S HOPE that index is a sane value, because we create up to [index] // entries in net_colormaps. At this point, we don't know // what the total colormap count is - if (index >= numsectors*3) // if every sector had a unique colormap change AND a fade thinker which has two colormap entries + if (index >= numsectors*3 + num_ffloors) + // if every sector had a unique colormap change AND a fade color thinker which has two colormap entries + // AND every ffloor had a fade FOF thinker with one colormap entry I_Error("Colormap %d from server is too high for sectors %d", index, (UINT32)numsectors); // our index doesn't exist, so just make the entry @@ -564,6 +567,7 @@ static void ClearNetColormaps(void) Z_Free(exc); } num_net_colormaps = 0; + num_ffloors = 0; net_colormaps = NULL; } @@ -597,6 +601,7 @@ static void P_NetArchiveColormaps(void) } num_net_colormaps = 0; + num_ffloors = 0; net_colormaps = NULL; } @@ -698,6 +703,7 @@ static void P_NetUnArchiveColormaps(void) // Don't need these anymore num_net_colormaps = 0; + num_ffloors = 0; net_colormaps = NULL; } @@ -1031,6 +1037,14 @@ static void P_NetUnArchiveWorld(void) // initialize colormap vars because paranoia ClearNetColormaps(); + // count the level's ffloors so that colormap loading can have an upper limit + for (i = 0; i < numsectors; i++) + { + ffloor_t *rover; + for (rover = sectors[i].ffloors; rover; rover = rover->next) + num_ffloors++; + } + get = save_p; for (;;) From 20c4702986f6f3f99d30bf3efe19a10bc13141cc Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 17 Sep 2018 14:12:16 -0400 Subject: [PATCH 248/306] Line exec trigger netsync: Save var2s in addition to vars --- src/p_saveg.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index 6e0c704f6..6010a1d24 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1260,7 +1260,10 @@ static void SaveSpecialLevelThinker(const thinker_t *th, const UINT8 type) size_t i; WRITEUINT8(save_p, type); for (i = 0; i < 16; i++) + { WRITEFIXED(save_p, ht->vars[i]); //var[16] + WRITEFIXED(save_p, ht->var2s[i]); //var[16] + } WRITEUINT32(save_p, SaveLine(ht->sourceline)); WRITEUINT32(save_p, SaveSector(ht->sector)); } @@ -2163,7 +2166,10 @@ static void LoadSpecialLevelThinker(actionf_p1 thinker, UINT8 floorOrCeiling) size_t i; ht->thinker.function.acp1 = thinker; for (i = 0; i < 16; i++) + { ht->vars[i] = READFIXED(save_p); //var[16] + ht->var2s[i] = READFIXED(save_p); //var[16] + } ht->sourceline = LoadLine(READUINT32(save_p)); ht->sector = LoadSector(READUINT32(save_p)); From 5b16590ba24bbe09e2bfe2f9abb58993e1023134 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 17 Sep 2018 21:03:51 -0400 Subject: [PATCH 249/306] 453: Don't interrupt current FOF fade unless EFFECT5 --- src/p_spec.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index b5607e2b2..e53d386cf 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3403,7 +3403,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 destvalue = line->sidenum[1] != 0xffff ? (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : (INT16)(line->dx>>FRACBITS); INT16 speed = line->sidenum[1] != 0xffff ? - (INT16)(sides[line->sidenum[1]].rowoffset>>FRACBITS) : (INT16)(abs(line->dy)>>FRACBITS); + (INT16)(abs(sides[line->sidenum[1]].rowoffset>>FRACBITS)) : (INT16)(abs(line->dy)>>FRACBITS); INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in @@ -3433,6 +3433,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) return; } + // Prevent continuous execs from interfering on an existing fade + if (!(line->flags & ML_EFFECT5) + && rover->fadingdata) + continue; + if (speed > 0) P_AddFakeFloorFader(rover, secnum, j, destvalue, From f5b25c91f50cea0c7a055898dbf803c558e0f9e7 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 05:50:14 -0400 Subject: [PATCH 250/306] 453: Commented out, but allow existing fade overlap of 2 tics (or speed*2) --- src/p_spec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/p_spec.c b/src/p_spec.c index e53d386cf..5a42cefed 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3436,7 +3436,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // Prevent continuous execs from interfering on an existing fade if (!(line->flags & ML_EFFECT5) && rover->fadingdata) + //&& ((fade_t*)rover->fadingdata)->timer > (ticbased ? 2 : speed*2)) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Fade FOF thinker already exists, timer: %d", ((fade_t*)rover->fadingdata)->timer); continue; + } if (speed > 0) P_AddFakeFloorFader(rover, secnum, j, From 27aa35705323a3d9fabb8022f8245b2032aabc56 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 07:07:46 -0400 Subject: [PATCH 251/306] 453: A line break --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 5a42cefed..06ef4839b 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3438,7 +3438,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) && rover->fadingdata) //&& ((fade_t*)rover->fadingdata)->timer > (ticbased ? 2 : speed*2)) { - CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Fade FOF thinker already exists, timer: %d", ((fade_t*)rover->fadingdata)->timer); + CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Fade FOF thinker already exists, timer: %d\n", ((fade_t*)rover->fadingdata)->timer); continue; } From 64b96c7192565b1f47561c9f4210ef2425e60b94 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 17 Sep 2018 21:16:27 -0400 Subject: [PATCH 252/306] 455: Don't interrupt current color fading --- src/p_spec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/p_spec.c b/src/p_spec.c index a408b2140..b855e9641 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3378,6 +3378,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { extracolormap_t *source_exc, *dest_exc, *exc; + // Prevent continuous execs from interfering on an existing fade + if (!(line->flags & ML_EFFECT5) + && sectors[secnum].fadecolormapdata) + continue; + if (line->flags & ML_TFERLINE) // use back colormap instead of target sector sectors[secnum].extra_colormap = (line->sidenum[1] != 0xFFFF) ? sides[line->sidenum[1]].colormap_data : NULL; From 56ee711f332daad06ecec3d612d0d8b84318be59 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 05:45:28 -0400 Subject: [PATCH 253/306] 455: Commented out, but allow existing fade overlap of 2 tics (or speed*2) --- src/p_spec.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index b855e9641..95119cfd3 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3377,11 +3377,18 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;) { extracolormap_t *source_exc, *dest_exc, *exc; + INT32 speed = (INT32)((line->flags & ML_DONTPEGBOTTOM) || !sides[line->sidenum[0]].rowoffset) && line->sidenum[1] != 0xFFFF ? + abs(sides[line->sidenum[1]].rowoffset >> FRACBITS) + : abs(sides[line->sidenum[0]].rowoffset >> FRACBITS); // Prevent continuous execs from interfering on an existing fade if (!(line->flags & ML_EFFECT5) && sectors[secnum].fadecolormapdata) + //&& ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer > (ticbased ? 2 : speed*2)) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 455 Executor: Fade color thinker already exists, timer: %d", ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer); continue; + } if (line->flags & ML_TFERLINE) // use back colormap instead of target sector sectors[secnum].extra_colormap = (line->sidenum[1] != 0xFFFF) ? @@ -3451,9 +3458,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) Z_Free(exc); Add_ColormapFader(§ors[secnum], source_exc, dest_exc, (line->flags & ML_EFFECT4), // tic-based timing - ((line->flags & ML_DONTPEGBOTTOM) || !sides[line->sidenum[0]].rowoffset) && line->sidenum[1] != 0xFFFF ? - abs(sides[line->sidenum[1]].rowoffset >> FRACBITS) - : abs(sides[line->sidenum[0]].rowoffset >> FRACBITS)); + speed); } break; From 9778cc2ad57bbc1c4c4a51a93b4aea4e88f91a38 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 07:07:30 -0400 Subject: [PATCH 254/306] 455: A line break --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 95119cfd3..80580403c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3386,7 +3386,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) && sectors[secnum].fadecolormapdata) //&& ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer > (ticbased ? 2 : speed*2)) { - CONS_Debug(DBG_GAMELOGIC, "Line type 455 Executor: Fade color thinker already exists, timer: %d", ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer); + CONS_Debug(DBG_GAMELOGIC, "Line type 455 Executor: Fade color thinker already exists, timer: %d\n", ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer); continue; } From 6567872229cb3535c7dbf3e79027ca89a51aa947 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 07:06:59 -0400 Subject: [PATCH 255/306] 492: Don't interrupt existing polyobj fader unless EFFECT5 --- src/p_spec.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 2583c24f3..481580b79 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1276,7 +1276,7 @@ static boolean PolyFade(line_t *line) if (!(po = Polyobj_GetForNum(polyObjNum))) { - CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: bad polyobj %d\n", polyObjNum); + CONS_Debug(DBG_POLYOBJ, "PolyFade: bad polyobj %d\n", polyObjNum); return 0; } @@ -1284,6 +1284,15 @@ static boolean PolyFade(line_t *line) if (po->isBad) return 0; + // Prevent continuous execs from interfering on an existing fade + if (!(line->flags & ML_EFFECT5) + && po->thinker + && po->thinker->function.acp1 == (actionf_p1)T_PolyObjFade) + { + CONS_Debug(DBG_POLYOBJ, "Line type 492 Executor: Fade PolyObject thinker already exists\n"); + return 0; + } + pfd.polyObjNum = polyObjNum; // if DONTPEGBOTTOM, specify raw translucency value in Front X Offset From 5029c01c2b4e9ae9cfba49e76e805b0f73e817cf Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 07:11:31 -0400 Subject: [PATCH 256/306] 492: Remove pre-existing thinker when setting up new fade --- src/p_polyobj.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index bbcf4f42a..c2b3ba399 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -2969,6 +2969,9 @@ INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata) if (po->translucency == pfdata->destvalue) return 1; + if (po->thinker && po->thinker->function.acp1 == (actionf_p1)T_PolyObjFade) + P_RemoveThinker(po->thinker); + // create a new thinker th = Z_Malloc(sizeof(polyfade_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyObjFade; From e7ecd84e80e5c57d64ff0827bb49d21b927bdc2c Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 07:36:38 -0400 Subject: [PATCH 257/306] p_setup: Don't fudge texture offsets if EFFECT5 and a linedef exec --- src/p_setup.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index f0ce69598..ae44c4cea 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1331,7 +1331,8 @@ static void P_LoadLineDefs2(void) ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0; // Repeat count for midtexture - if ((ld->flags & ML_EFFECT5) && (ld->sidenum[1] != 0xffff)) + if ((ld->flags & ML_EFFECT5) && (ld->sidenum[1] != 0xffff) + && !(ld->special >= 300 && ld->special < 500)) // exempt linedef exec specials { sides[ld->sidenum[0]].repeatcnt = (INT16)(((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) >> 12); sides[ld->sidenum[0]].textureoffset = (((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) & 2047) << FRACBITS; From 34e403afcb501ae5e456dc292b8a3632a7e5fab9 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 08:32:34 -0400 Subject: [PATCH 258/306] S_ChangeMusic: More specific load/play fail messages --- src/s_sound.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/s_sound.c b/src/s_sound.c index 2b8e8e721..ea129a109 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1391,14 +1391,17 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) S_StopMusic(); // shutdown old music if (!S_LoadMusic(mmusic)) + { + CONS_Alert(CONS_ERROR, "Music %.6s could not be loaded!\n", mmusic); return; + } music_flags = mflags; music_looping = looping; if (!S_PlayMusic(looping)) { - CONS_Alert(CONS_ERROR, "Music cannot be played!\n"); + CONS_Alert(CONS_ERROR, "Music %.6s could not be played!\n", mmusic); return; } } From c45d523e8f2e1505283e614695bfe05d71b1ff82 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 18 Sep 2018 06:27:30 -0400 Subject: [PATCH 259/306] 420: Don't interrupt existing light fade on duration timing except EFFECT5 (cherry picked from commit 3b957c32517a8f5148940c0067af7e88a51d1fee) --- src/lua_baselib.c | 3 ++- src/p_lights.c | 12 +++++++++++- src/p_spec.c | 3 ++- src/p_spec.h | 2 +- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 840863eb0..ce017620c 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1810,9 +1810,10 @@ static int lib_pFadeLight(lua_State *L) INT32 destvalue = (INT32)luaL_checkinteger(L, 2); INT32 speed = (INT32)luaL_checkinteger(L, 3); boolean ticbased = lua_optboolean(L, 4); + boolean force = lua_optboolean(L, 5); NOHUD INLEVEL - P_FadeLight(tag, destvalue, speed, ticbased); + P_FadeLight(tag, destvalue, speed, ticbased, force); return 0; } diff --git a/src/p_lights.c b/src/p_lights.c index 2ea93b796..12abc9e05 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -371,12 +371,22 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean } } -void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased) +void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force) { INT32 i; // search all sectors for ones with tag for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0 ;) + { + if (!force && ticbased // always let speed fader execute + && sectors[i].lightingdata + && ((lightlevel_t*)sectors[i].lightingdata)->thinker.function.acp1 == (actionf_p1)T_LightFade) + // && ((lightlevel_t*)sectors[i].lightingdata)->timer > 2) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 420 Executor: Fade light thinker already exists, timer: %d\n", ((lightlevel_t*)sectors[i].lightingdata)->timer); + continue; + } P_FadeLightBySector(§ors[i], destvalue, speed, ticbased); + } } /** Fades the light level in a sector to a new value. diff --git a/src/p_spec.c b/src/p_spec.c index b0a976a10..42cff1282 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2877,7 +2877,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) max(min(sides[line->sidenum[1]].rowoffset>>FRACBITS, 255), 0) : max(min(sides[line->sidenum[0]].rowoffset>>FRACBITS, 255), 0)) : abs(P_AproxDistance(line->dx, line->dy))>>FRACBITS, - (line->flags & ML_EFFECT4)); + (line->flags & ML_EFFECT4), + (line->flags & ML_EFFECT5)); break; case 421: // Stop lighting effect in tagged sectors diff --git a/src/p_spec.h b/src/p_spec.h index 56684b496..848b80ecf 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -162,7 +162,7 @@ void T_Glow(glow_t *g); glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, INT32 length); void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ticbased); -void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased); +void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force); void T_LightFade(lightlevel_t *ll); typedef enum From 1dadee68040faf4f1e42f5c8c8bcae4e019a8c2e Mon Sep 17 00:00:00 2001 From: Digiku Date: Wed, 19 Sep 2018 10:45:51 -0400 Subject: [PATCH 260/306] Nights intermission dehacked: a comment --- src/dehacked.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dehacked.c b/src/dehacked.c index 1f56210ac..ae1be6da2 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1199,7 +1199,7 @@ static void readlevelheader(MYFILE *f, INT32 num) else if (fastcmp(word2, "NIGHTS")) i = 3; else if (fastcmp(word2, "NIGHTSLINK")) i = 4; - if (i >= -1 && i <= 4) // -1 for no bonus. Max is 3. + if (i >= -1 && i <= 4) // -1 for no bonus. Max is 4. mapheaderinfo[num-1]->bonustype = (SINT8)i; else deh_warning("Level header %d: invalid bonus type number %d", num, i); From e3ecb61173c671ee80d673b8985690539d6c4989 Mon Sep 17 00:00:00 2001 From: Digiku Date: Wed, 19 Sep 2018 10:53:11 -0400 Subject: [PATCH 261/306] Nights intermission bonus y_inter.c: A comment --- src/y_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/y_inter.c b/src/y_inter.c index 2c77a577a..45ecd49e6 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1945,7 +1945,7 @@ static void Y_AwardSpecialStageBonus(void) if (!playeringame[i] || players[i].lives < 1) // not active or game over Y_SetNullBonus(&players[i], &localbonus); - else if (maptol & TOL_NIGHTS) // Link instead of Rings + else if (maptol & TOL_NIGHTS) // Mare score instead of Rings Y_SetNightsBonus(&players[i], &localbonus); else Y_SetRingBonus(&players[i], &localbonus); From 24938473a5ae66616b17c9c8d3e4b8c0a7961775 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Sep 2018 17:49:03 -0400 Subject: [PATCH 262/306] Linedef exec FOF specials: Move logic into for (rover =...) block so procedure happens on every FOF match --- src/p_spec.c | 238 +++++++++++++++++++++++++++------------------------ 1 file changed, 125 insertions(+), 113 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index d152b59c1..e63ec4a92 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3090,7 +3090,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover; // FOF that we are going to crumble + ffloor_t *rover, *foundrover; // FOF that we are going to crumble for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) { @@ -3105,16 +3105,18 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) for (rover = sec->ffloors; rover; rover = rover->next) { if (rover->master->frontsector->tag == foftag) - break; + { + foundrover = rover; // for debug, "Can't find a FOF" message below + + EV_CrumbleChain(sec, rover); + } } - if (!rover) + if (!foundrover) { CONS_Debug(DBG_GAMELOGIC, "Line type 436 Executor: Can't find a FOF control sector with tag %d\n", foftag); return; } - - EV_CrumbleChain(sec, rover); } } break; @@ -3274,7 +3276,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible (or not visible) in - ffloor_t *rover; // FOF to vanish/un-vanish + ffloor_t *rover, *foundrover; // FOF to vanish/un-vanish ffloortype_e oldflags; // store FOF's old flags for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) @@ -3290,26 +3292,28 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) for (rover = sec->ffloors; rover; rover = rover->next) { if (rover->master->frontsector->tag == foftag) - break; + { + foundrover = rover; // for debug, "Can't find a FOF" message below + + oldflags = rover->flags; + + // Abracadabra! + if (line->flags & ML_NOCLIMB) + rover->flags |= FF_EXISTS; + else + rover->flags &= ~FF_EXISTS; + + // if flags changed, reset sector's light list + if (rover->flags != oldflags) + sec->moved = true; + } } - if (!rover) + if (!foundrover) { CONS_Debug(DBG_GAMELOGIC, "Line type 445 Executor: Can't find a FOF control sector with tag %d\n", foftag); return; } - - oldflags = rover->flags; - - // Abracadabra! - if (line->flags & ML_NOCLIMB) - rover->flags |= FF_EXISTS; - else - rover->flags &= ~FF_EXISTS; - - // if flags changed, reset sector's light list - if (rover->flags != oldflags) - sec->moved = true; } } break; @@ -3319,7 +3323,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover; // FOF that we are going to make fall down + ffloor_t *rover, *foundrover; // FOF that we are going to make fall down player_t *player = NULL; // player that caused FOF to fall boolean respawn = true; // should the fallen FOF respawn? @@ -3342,19 +3346,21 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) for (rover = sec->ffloors; rover; rover = rover->next) { if (rover->master->frontsector->tag == foftag) - break; + { + foundrover = rover; // for debug, "Can't find a FOF" message below + + if (line->flags & ML_BLOCKMONSTERS) // FOF flags determine respawn ability instead? + respawn = !(rover->flags & FF_NORETURN) ^ !!(line->flags & ML_NOCLIMB); // no climb inverts + + EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), player, rover->alpha, respawn); + } } - if (!rover) + if (!foundrover) { CONS_Debug(DBG_GAMELOGIC, "Line type 446 Executor: Can't find a FOF control sector with tag %d\n", foftag); return; } - - if (line->flags & ML_BLOCKMONSTERS) // FOF flags determine respawn ability instead? - respawn = !(rover->flags & FF_NORETURN) ^ !!(line->flags & ML_NOCLIMB); // no climb inverts - - EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), player, rover->alpha, respawn); } } break; @@ -3486,7 +3492,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover; // FOF that we are going to operate + ffloor_t *rover, *foundrover; // FOF that we are going to operate for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) { @@ -3501,38 +3507,40 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) for (rover = sec->ffloors; rover; rover = rover->next) { if (rover->master->frontsector->tag == foftag) - break; + { + foundrover = rover; // for debug, "Can't find a FOF" message below + + // If fading an invisible FOF whose render flags we did not yet set, + // initialize its alpha to 1 + // for relative alpha calc + if (!(line->flags & ML_NOCLIMB) && // do translucent + (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES) && + !(rover->flags & FF_RENDERALL)) + rover->alpha = 1; + + P_RemoveFakeFloorFader(rover); + P_FadeFakeFloor(rover, + rover->alpha, + max(1, min(256, (line->flags & ML_EFFECT3) ? rover->alpha + destvalue : destvalue)), + 0, // set alpha immediately + false, NULL, // tic-based logic + false, // do not handle FF_EXISTS + !(line->flags & ML_NOCLIMB), // handle FF_TRANSLUCENT + false, // do not handle lighting + false, // do not handle colormap + false, // do not handle collision + false, // do not do ghost fade (no collision during fade) + true); // use exact alpha values (for opengl) + } } - if (!rover) + if (!foundrover) { CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Can't find a FOF control sector with tag %d\n", foftag); return; } - - // If fading an invisible FOF whose render flags we did not yet set, - // initialize its alpha to 1 - // for relative alpha calc - if (!(line->flags & ML_NOCLIMB) && // do translucent - (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE - !(rover->spawnflags & FF_RENDERSIDES) && - !(rover->spawnflags & FF_RENDERPLANES) && - !(rover->flags & FF_RENDERALL)) - rover->alpha = 1; - - P_RemoveFakeFloorFader(rover); - P_FadeFakeFloor(rover, - rover->alpha, - max(1, min(256, (line->flags & ML_EFFECT3) ? rover->alpha + destvalue : destvalue)), - 0, // set alpha immediately - false, NULL, // tic-based logic - false, // do not handle FF_EXISTS - !(line->flags & ML_NOCLIMB), // handle FF_TRANSLUCENT - false, // do not handle lighting - false, // do not handle colormap - false, // do not handle collision - false, // do not do ghost fade (no collision during fade) - true); // use exact alpha values (for opengl) } break; } @@ -3546,7 +3554,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover; // FOF that we are going to operate + ffloor_t *rover, *foundrover; // FOF that we are going to operate size_t j = 0; // sec->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) @@ -3562,64 +3570,66 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) for (rover = sec->ffloors; rover; rover = rover->next) { if (rover->master->frontsector->tag == foftag) - break; + { + foundrover = rover; // for debug, "Can't find a FOF" message below + + // Prevent continuous execs from interfering on an existing fade + if (!(line->flags & ML_EFFECT5) + && rover->fadingdata) + //&& ((fade_t*)rover->fadingdata)->timer > (ticbased ? 2 : speed*2)) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Fade FOF thinker already exists, timer: %d\n", ((fade_t*)rover->fadingdata)->timer); + continue; + } + + if (speed > 0) + P_AddFakeFloorFader(rover, secnum, j, + destvalue, + speed, + (line->flags & ML_EFFECT4), // tic-based logic + (line->flags & ML_EFFECT3), // Relative destvalue + !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS + !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT + !(line->flags & ML_EFFECT2), // do not handle lighting + !(line->flags & ML_EFFECT2), // do not handle colormap (ran out of flags) + !(line->flags & ML_BOUNCY), // do not handle collision + (line->flags & ML_EFFECT1), // do ghost fade (no collision during fade) + (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) + else + { + // If fading an invisible FOF whose render flags we did not yet set, + // initialize its alpha to 1 + // for relative alpha calc + if (!(line->flags & ML_NOCLIMB) && // do translucent + (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES) && + !(rover->flags & FF_RENDERALL)) + rover->alpha = 1; + + P_RemoveFakeFloorFader(rover); + P_FadeFakeFloor(rover, + rover->alpha, + max(1, min(256, (line->flags & ML_EFFECT3) ? rover->alpha + destvalue : destvalue)), + 0, // set alpha immediately + false, NULL, // tic-based logic + !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS + !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT + !(line->flags & ML_EFFECT2), // do not handle lighting + !(line->flags & ML_EFFECT2), // do not handle colormap (ran out of flags) + !(line->flags & ML_BOUNCY), // do not handle collision + (line->flags & ML_EFFECT1), // do ghost fade (no collision during fade) + (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) + } + } j++; } - if (!rover) + if (!foundrover) { CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Can't find a FOF control sector with tag %d\n", foftag); return; } - - // Prevent continuous execs from interfering on an existing fade - if (!(line->flags & ML_EFFECT5) - && rover->fadingdata) - //&& ((fade_t*)rover->fadingdata)->timer > (ticbased ? 2 : speed*2)) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Fade FOF thinker already exists, timer: %d\n", ((fade_t*)rover->fadingdata)->timer); - continue; - } - - if (speed > 0) - P_AddFakeFloorFader(rover, secnum, j, - destvalue, - speed, - (line->flags & ML_EFFECT4), // tic-based logic - (line->flags & ML_EFFECT3), // Relative destvalue - !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS - !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT - !(line->flags & ML_EFFECT2), // do not handle lighting - !(line->flags & ML_EFFECT2), // do not handle colormap (ran out of flags) - !(line->flags & ML_BOUNCY), // do not handle collision - (line->flags & ML_EFFECT1), // do ghost fade (no collision during fade) - (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) - else - { - // If fading an invisible FOF whose render flags we did not yet set, - // initialize its alpha to 1 - // for relative alpha calc - if (!(line->flags & ML_NOCLIMB) && // do translucent - (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE - !(rover->spawnflags & FF_RENDERSIDES) && - !(rover->spawnflags & FF_RENDERPLANES) && - !(rover->flags & FF_RENDERALL)) - rover->alpha = 1; - - P_RemoveFakeFloorFader(rover); - P_FadeFakeFloor(rover, - rover->alpha, - max(1, min(256, (line->flags & ML_EFFECT3) ? rover->alpha + destvalue : destvalue)), - 0, // set alpha immediately - false, NULL, // tic-based logic - !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS - !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT - !(line->flags & ML_EFFECT2), // do not handle lighting - !(line->flags & ML_EFFECT2), // do not handle colormap (ran out of flags) - !(line->flags & ML_BOUNCY), // do not handle collision - (line->flags & ML_EFFECT1), // do ghost fade (no collision during fade) - (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) - } } break; } @@ -3629,7 +3639,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover; // FOF that we are going to operate + ffloor_t *rover, *foundrover; // FOF that we are going to operate for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) { @@ -3644,17 +3654,19 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) for (rover = sec->ffloors; rover; rover = rover->next) { if (rover->master->frontsector->tag == foftag) - break; + { + foundrover = rover; // for debug, "Can't find a FOF" message below + + P_ResetFakeFloorFader(rover, NULL, + !(line->flags & ML_BLOCKMONSTERS)); // do not finalize collision flags + } } - if (!rover) + if (!foundrover) { CONS_Debug(DBG_GAMELOGIC, "Line type 454 Executor: Can't find a FOF control sector with tag %d\n", foftag); return; } - - P_ResetFakeFloorFader(rover, NULL, - !(line->flags & ML_BLOCKMONSTERS)); // do not finalize collision flags } break; } From 5e1b4272c1c835b2d6cb074b5c00acc2dd26a5bb Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Sep 2018 17:50:05 -0400 Subject: [PATCH 263/306] Initialize foundrover to NULL (for debug checking) --- src/p_spec.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index e63ec4a92..dfc75a4e3 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3090,7 +3090,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover, *foundrover; // FOF that we are going to crumble + ffloor_t *rover, *foundrover = NULL; // FOF that we are going to crumble for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) { @@ -3276,7 +3276,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible (or not visible) in - ffloor_t *rover, *foundrover; // FOF to vanish/un-vanish + ffloor_t *rover, *foundrover = NULL; // FOF to vanish/un-vanish ffloortype_e oldflags; // store FOF's old flags for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) @@ -3323,7 +3323,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover, *foundrover; // FOF that we are going to make fall down + ffloor_t *rover, *foundrover = NULL; // FOF that we are going to make fall down player_t *player = NULL; // player that caused FOF to fall boolean respawn = true; // should the fallen FOF respawn? @@ -3492,7 +3492,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover, *foundrover; // FOF that we are going to operate + ffloor_t *rover, *foundrover = NULL; // FOF that we are going to operate for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) { @@ -3554,7 +3554,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover, *foundrover; // FOF that we are going to operate + ffloor_t *rover, *foundrover = NULL; // FOF that we are going to operate size_t j = 0; // sec->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) @@ -3639,7 +3639,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover, *foundrover; // FOF that we are going to operate + ffloor_t *rover, *foundrover = NULL; // FOF that we are going to operate for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) { From 31343be41be36f219630ff02001750ed9b6b3c51 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 19 Sep 2018 20:11:30 -0400 Subject: [PATCH 264/306] foundrover ffloor_t -> boolean --- src/p_spec.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index dfc75a4e3..2f6558175 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3090,7 +3090,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover, *foundrover = NULL; // FOF that we are going to crumble + ffloor_t *rover; // FOF that we are going to crumble + boolean foundrover = false; // for debug, "Can't find a FOF" message for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) { @@ -3106,7 +3107,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { if (rover->master->frontsector->tag == foftag) { - foundrover = rover; // for debug, "Can't find a FOF" message below + foundrover = true; EV_CrumbleChain(sec, rover); } @@ -3276,7 +3277,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible (or not visible) in - ffloor_t *rover, *foundrover = NULL; // FOF to vanish/un-vanish + ffloor_t *rover; // FOF to vanish/un-vanish + boolean foundrover = false; // for debug, "Can't find a FOF" message ffloortype_e oldflags; // store FOF's old flags for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) @@ -3293,7 +3295,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { if (rover->master->frontsector->tag == foftag) { - foundrover = rover; // for debug, "Can't find a FOF" message below + foundrover = true; oldflags = rover->flags; @@ -3323,7 +3325,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover, *foundrover = NULL; // FOF that we are going to make fall down + ffloor_t *rover; // FOF that we are going to make fall down + boolean foundrover = false; // for debug, "Can't find a FOF" message player_t *player = NULL; // player that caused FOF to fall boolean respawn = true; // should the fallen FOF respawn? @@ -3347,7 +3350,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { if (rover->master->frontsector->tag == foftag) { - foundrover = rover; // for debug, "Can't find a FOF" message below + foundrover = true; if (line->flags & ML_BLOCKMONSTERS) // FOF flags determine respawn ability instead? respawn = !(rover->flags & FF_NORETURN) ^ !!(line->flags & ML_NOCLIMB); // no climb inverts @@ -3492,7 +3495,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover, *foundrover = NULL; // FOF that we are going to operate + ffloor_t *rover; // FOF that we are going to operate + boolean foundrover = false; // for debug, "Can't find a FOF" message for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) { @@ -3508,7 +3512,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { if (rover->master->frontsector->tag == foftag) { - foundrover = rover; // for debug, "Can't find a FOF" message below + foundrover = true; // If fading an invisible FOF whose render flags we did not yet set, // initialize its alpha to 1 @@ -3554,7 +3558,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover, *foundrover = NULL; // FOF that we are going to operate + ffloor_t *rover; // FOF that we are going to operate + boolean foundrover = false; // for debug, "Can't find a FOF" message size_t j = 0; // sec->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) @@ -3571,7 +3576,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { if (rover->master->frontsector->tag == foftag) { - foundrover = rover; // for debug, "Can't find a FOF" message below + foundrover = true; // Prevent continuous execs from interfering on an existing fade if (!(line->flags & ML_EFFECT5) @@ -3639,7 +3644,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover, *foundrover = NULL; // FOF that we are going to operate + ffloor_t *rover; // FOF that we are going to operate + boolean foundrover = false; // for debug, "Can't find a FOF" message for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) { @@ -3655,7 +3661,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { if (rover->master->frontsector->tag == foftag) { - foundrover = rover; // for debug, "Can't find a FOF" message below + foundrover = true; P_ResetFakeFloorFader(rover, NULL, !(line->flags & ML_BLOCKMONSTERS)); // do not finalize collision flags From a53f036149a4ff1d7c9371f9f082fbfe5b65a5b7 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 20 Sep 2018 18:26:59 -0400 Subject: [PATCH 265/306] Use MemAvailable instead --- src/sdl/i_system.c | 49 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index e86a39cab..984f6dd22 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -124,6 +124,10 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #include "macosx/mac_resources.h" #endif +#ifndef errno +#include +#endif + // Locations for searching the srb2.srb #if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) #define DEFAULTWADLOCATION1 "/usr/local/share/games/SRB2" @@ -2712,9 +2716,31 @@ const char *I_LocateWad(void) #ifdef __linux__ #define MEMINFO_FILE "/proc/meminfo" #define MEMTOTAL "MemTotal:" +#define MEMAVAILABLE "MemAvailable:" #define MEMFREE "MemFree:" +#define CACHED "Cached:" +#define BUFFERS "Buffers:" +#define SHMEM "Shmem:" #endif +/* Parse the contents of /proc/meminfo (in buf), return value of "name" + * (example: MemTotal) */ +static long get_entry(const char* name, const char* buf) +{ + char* hit = strstr(buf, name); + if (hit == NULL) { + return -1; + } + + errno = 0; + long val = strtol(hit + strlen(name), NULL, 10); + if (errno != 0) { + CONS_Alert(CONS_ERROR, M_GetText("get_entry: strtol() failed: %s\n"), strerror(errno)); + return -1; + } + return val; +} + // quick fix for compil UINT32 I_GetFreeMem(UINT32 *total) { @@ -2809,7 +2835,17 @@ UINT32 I_GetFreeMem(UINT32 *total) memTag += sizeof (MEMTOTAL); totalKBytes = atoi(memTag); - if ((memTag = strstr(buf, MEMFREE)) == NULL) + if ((memTag = strstr(buf, MEMAVAILABLE)) == NULL) + { + Cached = get_entry(CACHED, buf); + MemFree = get_entry(MEMFREE, buf); + Buffers = get_entry(BUFFERS, buf); + Shmem = get_entry(SHMEM, buf); + MemAvailable = Cached + MemFree + Buffers - Shmem; + guessed = true; + } + + if (MemAvailable == -1 && guessed) { // Error if (total) @@ -2817,8 +2853,15 @@ UINT32 I_GetFreeMem(UINT32 *total) return 0; } - memTag += sizeof (MEMFREE); - freeKBytes = atoi(memTag); + if (guessed) + { + freeKBytes = MemAvailable; + } + else + { + memTag += sizeof (MEMAVAILABLE); + freeKBytes = atoi(memTag); + } if (total) *total = totalKBytes << 10; From 378495cb2b8337c37b6bfefc3f510cf9b6117e61 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 20 Sep 2018 18:33:50 -0400 Subject: [PATCH 266/306] Add some stuff --- src/sdl/i_system.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 984f6dd22..3610a534d 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2810,6 +2810,12 @@ UINT32 I_GetFreeMem(UINT32 *total) UINT32 totalKBytes; INT32 n; INT32 meminfo_fd = -1; + long Cached; + long MemFree; + long Buffers; + long Shmem; + long MemAvailable = -1; + boolean guessed = false; // Stupid way to verify if the amount was guessed or not. meminfo_fd = open(MEMINFO_FILE, O_RDONLY); n = read(meminfo_fd, buf, 1023); From be74b4e58b93974bc56a7f96f3f175b541b04230 Mon Sep 17 00:00:00 2001 From: Steel Date: Fri, 21 Sep 2018 07:16:54 -0400 Subject: [PATCH 267/306] Fix up errors with buildbots --- src/sdl/i_system.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 3610a534d..e9e1ae92d 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1,6 +1,6 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- -// +- // // Copyright (C) 1993-1996 by id Software, Inc. // Portions Copyright (C) 1998-2000 by DooM Legacy Team. // @@ -2095,7 +2095,6 @@ INT32 I_StartupSystem(void) return 0; } - // // I_Quit // @@ -2721,25 +2720,26 @@ const char *I_LocateWad(void) #define CACHED "Cached:" #define BUFFERS "Buffers:" #define SHMEM "Shmem:" -#endif /* Parse the contents of /proc/meminfo (in buf), return value of "name" * (example: MemTotal) */ static long get_entry(const char* name, const char* buf) { + long val; char* hit = strstr(buf, name); if (hit == NULL) { return -1; } errno = 0; - long val = strtol(hit + strlen(name), NULL, 10); + val = strtol(hit + strlen(name), NULL, 10); if (errno != 0) { CONS_Alert(CONS_ERROR, M_GetText("get_entry: strtol() failed: %s\n"), strerror(errno)); return -1; } return val; } +#endif // quick fix for compil UINT32 I_GetFreeMem(UINT32 *total) From af58ba9ae3fa661ea406bca3b134ae2ac6b76a2c Mon Sep 17 00:00:00 2001 From: Steel Date: Fri, 21 Sep 2018 07:21:49 -0400 Subject: [PATCH 268/306] Remove this that somehow slipped in. --- src/sdl/i_system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index e9e1ae92d..b7326b066 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1,6 +1,6 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- -- // +// // Copyright (C) 1993-1996 by id Software, Inc. // Portions Copyright (C) 1998-2000 by DooM Legacy Team. // From 68ec8119096c3744e25115337fd03ea3e124df2a Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Fri, 21 Sep 2018 11:26:08 -0400 Subject: [PATCH 269/306] Rearrange the code. Thanks again MonsterIestyn! --- src/sdl/i_system.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index b7326b066..05d9e092f 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2815,7 +2815,6 @@ UINT32 I_GetFreeMem(UINT32 *total) long Buffers; long Shmem; long MemAvailable = -1; - boolean guessed = false; // Stupid way to verify if the amount was guessed or not. meminfo_fd = open(MEMINFO_FILE, O_RDONLY); n = read(meminfo_fd, buf, 1023); @@ -2848,26 +2847,21 @@ UINT32 I_GetFreeMem(UINT32 *total) Buffers = get_entry(BUFFERS, buf); Shmem = get_entry(SHMEM, buf); MemAvailable = Cached + MemFree + Buffers - Shmem; - guessed = true; - } - if (MemAvailable == -1 && guessed) - { - // Error - if (total) - *total = 0L; - return 0; - } - - if (guessed) - { + if (MemAvailable == -1) + { + // Error + if (total) + *total = 0L; + return 0; + } freeKBytes = MemAvailable; - } - else - { + } + else + { memTag += sizeof (MEMAVAILABLE); freeKBytes = atoi(memTag); - } + } if (total) *total = totalKBytes << 10; From f88708bb75810e5ef089b5cf5246d3a2f9154d02 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Fri, 21 Sep 2018 12:05:52 -0400 Subject: [PATCH 270/306] Fix the weird indentation --- src/sdl/i_system.c | 76 +++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 05d9e092f..f92cd4b6e 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1683,7 +1683,7 @@ static void I_ShutdownMouse2(void) EscapeCommFunction(mouse2filehandle, CLRRTS); PurgeComm(mouse2filehandle, PURGE_TXABORT | PURGE_RXABORT | - PURGE_TXCLEAR | PURGE_RXCLEAR); + PURGE_TXCLEAR | PURGE_RXCLEAR); CloseHandle(mouse2filehandle); @@ -1876,11 +1876,11 @@ void I_StartupMouse2(void) { // COM file handle mouse2filehandle = CreateFileA(cv_mouse2port.string, GENERIC_READ | GENERIC_WRITE, - 0, // exclusive access - NULL, // no security attrs - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); + 0, // exclusive access + NULL, // no security attrs + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); if (mouse2filehandle == INVALID_HANDLE_VALUE) { INT32 e = GetLastError(); @@ -1900,7 +1900,7 @@ void I_StartupMouse2(void) // purge buffers PurgeComm(mouse2filehandle, PURGE_TXABORT | PURGE_RXABORT - | PURGE_TXCLEAR | PURGE_RXCLEAR); + | PURGE_TXCLEAR | PURGE_RXCLEAR); // setup port to 1200 7N1 dcb.DCBlength = sizeof (DCB); @@ -2029,7 +2029,7 @@ static void I_ShutdownTimer(void) tic_t I_GetTime (void) { static Uint32 basetime = 0; - Uint32 ticks = SDL_GetTicks(); + Uint32 ticks = SDL_GetTicks(); if (!basetime) basetime = ticks; @@ -2373,7 +2373,7 @@ void I_GetDiskFreeSpace(INT64 *freespace) { DWORD SectorsPerCluster, BytesPerSector, NumberOfFreeClusters, TotalNumberOfClusters; GetDiskFreeSpace(NULL, &SectorsPerCluster, &BytesPerSector, - &NumberOfFreeClusters, &TotalNumberOfClusters); + &NumberOfFreeClusters, &TotalNumberOfClusters); *freespace = BytesPerSector*SectorsPerCluster*NumberOfFreeClusters; } #else // Dummy for platform independent; 1GB should be enough @@ -2595,22 +2595,22 @@ static const char *locateWad(void) #ifdef CMAKECONFIG #ifndef NDEBUG - I_OutputMsg(","CMAKE_ASSETS_DIR); - strcpy(returnWadPath, CMAKE_ASSETS_DIR); - if (isWadPathOk(returnWadPath)) - { - return returnWadPath; - } + I_OutputMsg(","CMAKE_ASSETS_DIR); + strcpy(returnWadPath, CMAKE_ASSETS_DIR); + if (isWadPathOk(returnWadPath)) + { + return returnWadPath; + } #endif #endif #ifdef __APPLE__ - OSX_GetResourcesPath(returnWadPath); - I_OutputMsg(",%s", returnWadPath); - if (isWadPathOk(returnWadPath)) - { - return returnWadPath; - } + OSX_GetResourcesPath(returnWadPath); + I_OutputMsg(",%s", returnWadPath); + if (isWadPathOk(returnWadPath)) + { + return returnWadPath; + } #endif // examine default dirs @@ -2725,19 +2725,19 @@ const char *I_LocateWad(void) * (example: MemTotal) */ static long get_entry(const char* name, const char* buf) { - long val; - char* hit = strstr(buf, name); - if (hit == NULL) { - return -1; - } + long val; + char* hit = strstr(buf, name); + if (hit == NULL) { + return -1; + } - errno = 0; - val = strtol(hit + strlen(name), NULL, 10); - if (errno != 0) { - CONS_Alert(CONS_ERROR, M_GetText("get_entry: strtol() failed: %s\n"), strerror(errno)); - return -1; - } - return val; + errno = 0; + val = strtol(hit + strlen(name), NULL, 10); + if (errno != 0) { + CONS_Alert(CONS_ERROR, M_GetText("get_entry: strtol() failed: %s\n"), strerror(errno)); + return -1; + } + return val; } #endif @@ -2850,18 +2850,18 @@ UINT32 I_GetFreeMem(UINT32 *total) if (MemAvailable == -1) { - // Error + // Error if (total) *total = 0L; return 0; } freeKBytes = MemAvailable; - } - else - { + } + else + { memTag += sizeof (MEMAVAILABLE); freeKBytes = atoi(memTag); - } + } if (total) *total = totalKBytes << 10; From 872e2f82c154359ac5f8e33e5c9ffeeef5a84017 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 28 Sep 2018 17:02:02 +0100 Subject: [PATCH 271/306] Redo OpenGL skewing support, so that it now itself supports the lower unpegged effect for FOFs in OpenGL! --- src/hardware/hw_main.c | 46 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index d7c73415a..92925c9bf 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -2183,6 +2183,10 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) else if (drawtextured) { fixed_t texturevpeg; + boolean attachtobottom = false; +#ifdef ESLOPE + boolean slopeskew = false; // skew FOF walls with slopes? +#endif // Wow, how was this missing from OpenGL for so long? // ...Oh well, anyway, Lower Unpegged now changes pegging of FOFs like in software @@ -2190,24 +2194,50 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) if (newline) { texturevpeg = sides[newline->sidenum[0]].rowoffset; - if (newline->flags & ML_DONTPEGBOTTOM) - texturevpeg -= *rover->topheight - *rover->bottomheight; + attachtobottom = !!(newline->flags & ML_DONTPEGBOTTOM); +#ifdef ESLOPE + slopeskew = !!(newline->flags & ML_DONTPEGTOP); +#endif } else { texturevpeg = sides[rover->master->sidenum[0]].rowoffset; - if (gr_linedef->flags & ML_DONTPEGBOTTOM) - texturevpeg -= *rover->topheight - *rover->bottomheight; + attachtobottom = !!(gr_linedef->flags & ML_DONTPEGBOTTOM); +#ifdef ESLOPE + slopeskew = !!(rover->master->flags & ML_DONTPEGTOP); +#endif } grTex = HWR_GetTexture(texnum); #ifdef ESLOPE - wallVerts[3].t = (*rover->topheight - h + texturevpeg) * grTex->scaleY; - wallVerts[2].t = (*rover->topheight - hS + texturevpeg) * grTex->scaleY; - wallVerts[0].t = (*rover->topheight - l + texturevpeg) * grTex->scaleY; - wallVerts[1].t = (*rover->topheight - lS + texturevpeg) * grTex->scaleY; + if (!slopeskew) // no skewing + { + if (attachtobottom) + texturevpeg -= *rover->topheight - *rover->bottomheight; + wallVerts[3].t = (*rover->topheight - h + texturevpeg) * grTex->scaleY; + wallVerts[2].t = (*rover->topheight - hS + texturevpeg) * grTex->scaleY; + wallVerts[0].t = (*rover->topheight - l + texturevpeg) * grTex->scaleY; + wallVerts[1].t = (*rover->topheight - lS + texturevpeg) * grTex->scaleY; + } + else + { + if (!attachtobottom) // skew by top + { + wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; + wallVerts[0].t = (h - l + texturevpeg) * grTex->scaleY; + wallVerts[1].t = (hS - lS + texturevpeg) * grTex->scaleY; + } + else // skew by bottom + { + wallVerts[0].t = wallVerts[1].t = texturevpeg * grTex->scaleY; + wallVerts[3].t = wallVerts[0].t - (h - l) * grTex->scaleY; + wallVerts[2].t = wallVerts[1].t - (hS - lS) * grTex->scaleY; + } + } #else + if (attachtobottom) + texturevpeg -= *rover->topheight - *rover->bottomheight; wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + texturevpeg) * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (*rover->topheight - l + texturevpeg) * grTex->scaleY; #endif From 800b3bb2407f793730b88f2b6c70c583f3a2f8a8 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 30 Sep 2018 22:18:48 +0100 Subject: [PATCH 272/306] Move player + player mobj existence checks to top of P_MoveChaseCamera. This is the only place it makes sense to even check them tbh. While I'm at it, let's also use the "mo" variable instead of player->mo throughout the function (to be consistent) --- src/p_user.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index da8e19caa..91b5feb85 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -7853,7 +7853,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall subsector_t *newsubsec; fixed_t f1, f2; - cameranoclip = (player->pflags & (PF_NOCLIP|PF_NIGHTSMODE)) || (player->mo->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)); // Noclipping player camera noclips too!! + // We probably shouldn't move the camera if there is no player or player mobj somehow + if (!player || !player->mo) + return true; + + mo = player->mo; + + cameranoclip = (player->pflags & (PF_NOCLIP|PF_NIGHTSMODE)) || (mo->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)); // Noclipping player camera noclips too!! if (!(player->climbing || (player->pflags & PF_NIGHTSMODE) || player->playerstate == PST_DEAD)) { @@ -7874,7 +7880,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall else if (player == &players[secondarydisplayplayer]) focusangle = localangle2; else - focusangle = player->mo->angle; + focusangle = mo->angle; if (thiscam == &camera) camrotate = cv_cam_rotate.value; else if (thiscam == &camera2) @@ -7886,17 +7892,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall return true; } - if (!player || !player->mo) - return true; - - mo = player->mo; - thiscam->radius = FixedMul(20*FRACUNIT, mo->scale); thiscam->height = FixedMul(16*FRACUNIT, mo->scale); - if (!mo) - return true; - // Don't run while respawning from a starpost // Inu 4/8/13 Why not?! // if (leveltime > 0 && timeinmap <= 0) @@ -7904,7 +7902,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (player->pflags & PF_NIGHTSMODE) { - focusangle = player->mo->angle; + focusangle = mo->angle; focusaiming = 0; } else if (player == &players[consoleplayer]) @@ -7919,7 +7917,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } else { - focusangle = player->mo->angle; + focusangle = mo->angle; focusaiming = player->aiming; } @@ -7966,12 +7964,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall angle = R_PointToAngle2(player->axis1->x, player->axis1->y, player->axis2->x, player->axis2->y); angle += ANGLE_90; } - else if (player->mo->target) + else if (mo->target) { - if (player->mo->target->flags & MF_AMBUSH) - angle = R_PointToAngle2(player->mo->target->x, player->mo->target->y, player->mo->x, player->mo->y); + if (mo->target->flags & MF_AMBUSH) + angle = R_PointToAngle2(mo->target->x, mo->target->y, mo->x, mo->y); else - angle = R_PointToAngle2(player->mo->x, player->mo->y, player->mo->target->x, player->mo->target->y); + angle = R_PointToAngle2(mo->x, mo->y, mo->target->x, mo->target->y); } } else if (P_AnalogMove(player)) // Analog @@ -8066,7 +8064,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (twodlevel || (mo->flags2 & MF2_TWOD)) { // Camera doesn't ALWAYS need to move, only when running... - if (abs(player->mo->momx) > 10) + if (abs(mo->momx) > 10) { // Move the camera all smooth-like, not jerk it around... if (mo->momx > 0) @@ -8384,13 +8382,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall vy = thiscam->y; } - if (P_AproxDistance(vx - player->mo->x, vy - player->mo->y) < FixedMul(48*FRACUNIT, mo->scale)) - player->mo->flags2 |= MF2_SHADOW; + if (P_AproxDistance(vx - mo->x, vy - mo->y) < FixedMul(48*FRACUNIT, mo->scale)) + mo->flags2 |= MF2_SHADOW; else - player->mo->flags2 &= ~MF2_SHADOW; + mo->flags2 &= ~MF2_SHADOW; } else - player->mo->flags2 &= ~MF2_SHADOW; + mo->flags2 &= ~MF2_SHADOW; /* if (!resetcalled && (player->pflags & PF_NIGHTSMODE && player->exiting)) { From 79f5f4885c70e373cd6d4afc275c2141aa545736 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 4 Oct 2018 19:47:19 -0400 Subject: [PATCH 273/306] Split zlib and libpng --- src/Makefile | 22 +++++++++++++++------- src/sdl/mixer_sound.c | 17 ++++++++--------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/Makefile b/src/Makefile index dd250b0bc..7a67c3f02 100644 --- a/src/Makefile +++ b/src/Makefile @@ -66,6 +66,7 @@ # Compile without 3D sound support, add 'NOHS=1' # Compile with GDBstubs, add 'RDB=1' # Compile without PNG, add 'NOPNG=1' +# Compile without zlib, add 'NOZLIB=1' # # Addon for SDL: # To Cross-Compile, add 'SDL_CONFIG=/usr/*/bin/sdl-config' @@ -119,6 +120,7 @@ include Makefile.cfg ifdef DUMMY NOPNG=1 +NOZLIB=1 NONET=1 NOHW=1 NOHS=1 @@ -199,6 +201,7 @@ endif ifdef NDS NOPNG=1 +NOZLIB=1 NONET=1 #NOHW=1 NOHS=1 @@ -325,13 +328,6 @@ LIBS+=$(PNG_LDFLAGS) CFLAGS+=$(PNG_CFLAGS) endif -ZLIB_PKGCONFIG?=zlib -ZLIB_CFLAGS?=$(shell $(PKG_CONFIG) $(ZLIB_PKGCONFIG) --cflags) -ZLIB_LDFLAGS?=$(shell $(PKG_CONFIG) $(ZLIB_PKGCONFIG) --libs) - -LIBS+=$(ZLIB_LDFLAGS) -CFLAGS+=$(ZLIB_CFLAGS) - ifdef HAVE_LIBGME OPTS+=-DHAVE_LIBGME @@ -343,6 +339,18 @@ LIBS+=$(LIBGME_LDFLAGS) CFLAGS+=$(LIBGME_CFLAGS) endif +ifndef NOZLIB +OPTS+=-DHAVE_ZLIB +ZLIB_PKGCONFIG?=zlib +ZLIB_CFLAGS?=$(shell $(PKG_CONFIG) $(ZLIB_PKGCONFIG) --cflags) +ZLIB_LDFLAGS?=$(shell $(PKG_CONFIG) $(ZLIB_PKGCONFIG) --libs) + +LIBS+=$(ZLIB_LDFLAGS) +CFLAGS+=$(ZLIB_CFLAGS) +else +NOPNG=1 +endif + ifdef STATIC LIBS:=-static $(LIBS) endif diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 5211efe0a..362d7f264 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -38,9 +38,6 @@ #include "gme/gme.h" #define GME_TREBLE 5.0 #define GME_BASS 1.0 -#ifdef HAVE_PNG /// TODO: compile with zlib support without libpng - -#define HAVE_ZLIB #ifndef _MSC_VER #ifndef _LARGEFILE64_SOURCE @@ -56,10 +53,13 @@ #define _FILE_OFFSET_BITS 0 #endif -#include "zlib.h" #endif #endif +#ifdef HAVE_ZLIB +#include "zlib.h" +#endif + UINT8 sound_started = false; static boolean midimode; @@ -361,7 +361,7 @@ void *I_GetSfx(sfxinfo_t *sfx) } Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up #else - //CONS_Alert(CONS_ERROR,"Cannot decompress VGZ; no zlib support\n"); + return NULL; // No zlib support #endif } // Try to read it as a GME sound @@ -621,7 +621,8 @@ boolean I_StartDigSong(const char *musicname, boolean looping) } Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up #else - //CONS_Alert(CONS_ERROR,"Cannot decompress VGZ; no zlib support\n"); + CONS_Alert(CONS_ERROR,"Cannot decompress VGZ; no zlib support\n"); + return true; #endif } else if (!gme_open_data(data, len, &gme, 44100)) @@ -840,6 +841,4 @@ void I_UnRegisterSong(INT32 handle) (void)handle; Mix_FreeMusic(music); music = NULL; -} - -#endif +} \ No newline at end of file From 49cb1ffe9fb578f8abb29a3f45355ded6211dc03 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 4 Oct 2018 22:38:59 -0400 Subject: [PATCH 274/306] Restore deleted endif --- src/sdl/mixer_sound.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 362d7f264..d1083518a 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -51,8 +51,6 @@ #ifndef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 0 -#endif - #endif #endif @@ -841,4 +839,6 @@ void I_UnRegisterSong(INT32 handle) (void)handle; Mix_FreeMusic(music); music = NULL; -} \ No newline at end of file +} + +#endif \ No newline at end of file From fc5d969642f57f54c12acd137355473f14d84acd Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 4 Oct 2018 22:44:26 -0400 Subject: [PATCH 275/306] Fix DD compiling --- src/win32/win_snd.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index f168f1fe3..c030eec5c 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -17,9 +17,6 @@ #include "gme/gme.h" #define GME_TREBLE 5.0 #define GME_BASS 1.0 -#ifdef HAVE_PNG /// TODO: compile with zlib support without libpng - -#define HAVE_ZLIB #ifndef _MSC_VER #ifndef _WII From b812a6a4abdf705d65c6f204291ec6645fe5d729 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 4 Oct 2018 22:56:11 -0400 Subject: [PATCH 276/306] Really fix DD compiling this time. --- src/win32/win_snd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index c030eec5c..bc04bd6df 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -34,6 +34,7 @@ #define _FILE_OFFSET_BITS 0 #endif +#ifdef HAVE_ZLIB #include "zlib.h" #endif #endif From 1ec601af6b989f7ebdc0fa89f4bc2452977ae209 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 5 Oct 2018 22:42:36 +0100 Subject: [PATCH 277/306] Draw a star for continues if invalid skin numbers are somehow supplied --- src/v_video.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index aa2852c01..802a4d388 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -653,14 +653,10 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ // void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skincolor) { - if (skins[skinnum].flags & SF_HIRES -#ifdef HWRENDER -// || (rendermode != render_soft && rendermode != render_none) -#endif - ) - V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_CACHE)); + if (skinnum < 0 || skinnum >= numskins || (skins[skinnum].flags & SF_HIRES)) + V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_CACHE)); // Draw a star else - { + { // Find front angle of the first waiting frame of the character's actual sprites spriteframe_t *sprframe = &skins[skinnum].spritedef.spriteframes[2 & FF_FRAMEMASK]; patch_t *patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); const UINT8 *colormap = R_GetTranslationColormap(skinnum, skincolor, GTC_CACHE); From 725a65c1f7eff77e5632b6a7d7fdb11c47ee0c3f Mon Sep 17 00:00:00 2001 From: Sryder Date: Sat, 6 Oct 2018 21:44:40 +0100 Subject: [PATCH 278/306] Call SDL_RWclose after an SDL_RWFromMem call to close the RWops. --- src/sdl/mixer_sound.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 5211efe0a..e835a55ce 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -387,7 +387,15 @@ void *I_GetSfx(sfxinfo_t *sfx) #endif // Try to load it as a WAVE or OGG using Mixer. - return Mix_LoadWAV_RW(SDL_RWFromMem(lump, sfx->length), 1); + SDL_RWops *rw = SDL_RWFromMem(lump, sfx->length); + if (rw != NULL) + { + Mix_Chunk *chunk = Mix_LoadWAV_RW(rw, 1); + SDL_RWclose(rw); + return chunk; + } + + return NULL; // haven't been able to get anything } void I_FreeSfx(sfxinfo_t *sfx) @@ -635,7 +643,12 @@ boolean I_StartDigSong(const char *musicname, boolean looping) } #endif - music = Mix_LoadMUS_RW(SDL_RWFromMem(data, len), SDL_FALSE); + SDL_RWops *rw = SDL_RWFromMem(data, len); + if (rw != NULL) + { + music = Mix_LoadMUS_RW(rw, SDL_FALSE); + SDL_RWclose(rw); + } if (!music) { CONS_Alert(CONS_ERROR, "Mix_LoadMUS_RW: %s\n", Mix_GetError()); @@ -798,7 +811,12 @@ void I_SetMIDIMusicVolume(UINT8 volume) INT32 I_RegisterSong(void *data, size_t len) { - music = Mix_LoadMUS_RW(SDL_RWFromMem(data, len), SDL_FALSE); + SDL_RWops *rw = SDL_RWFromMem(data, len); + if (rw != NULL) + { + music = Mix_LoadMUS_RW(rw, SDL_FALSE); + SDL_RWclose(rw); + } if (!music) { CONS_Alert(CONS_ERROR, "Mix_LoadMUS_RW: %s\n", Mix_GetError()); From 7b417b573c61eeaeb325366196d78ace780f1b5a Mon Sep 17 00:00:00 2001 From: Sryder Date: Sat, 6 Oct 2018 23:59:39 +0100 Subject: [PATCH 279/306] Mix_QuickLoad_RAW sets a flag in the Mix_Chunk so that Mix_FreeChunk doesn't actually Free the sound. Checks for the flag when freeing, and if it's 0, we free the data manually after Mix_FreeChunk. I went back to Z_Malloc and Z_Free for this because they still work after this. --- src/sdl/mixer_sound.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index e835a55ce..15f1595ce 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -178,7 +178,7 @@ static Mix_Chunk *ds2chunk(void *stream) return NULL; // would and/or did wrap, can't store. break; } - sound = malloc(newsamples<<2); // samples * frequency shift * bytes per sample * channels + sound = Z_Malloc(newsamples<<2, PU_SOUND, 0); // samples * frequency shift * bytes per sample * channels s = (SINT8 *)stream; d = (INT16 *)sound; @@ -401,7 +401,22 @@ void *I_GetSfx(sfxinfo_t *sfx) void I_FreeSfx(sfxinfo_t *sfx) { if (sfx->data) + { + Mix_Chunk *chunk = (Mix_Chunk*)sfx->data; + UINT8 *abufdata = NULL; + if (chunk->allocated == 0) + { + // We allocated the data in this chunk, so get the abuf from mixer, then let it free the chunk, THEN we free the data + // I believe this should ensure the sound is not playing when we free it + abufdata = chunk->abuf; + } Mix_FreeChunk(sfx->data); + if (abufdata) + { + // I'm going to assume we used Z_Malloc to allocate this data. + Z_Free(abufdata); + } + } sfx->data = NULL; sfx->lumpnum = LUMPERROR; } From d072dd27254596c7c8925b4f6d08c151e57535f2 Mon Sep 17 00:00:00 2001 From: Sryder Date: Sun, 7 Oct 2018 00:22:23 +0100 Subject: [PATCH 280/306] I think that should be NULL, not 0 actually. --- src/sdl/mixer_sound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 15f1595ce..9fef16460 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -178,7 +178,7 @@ static Mix_Chunk *ds2chunk(void *stream) return NULL; // would and/or did wrap, can't store. break; } - sound = Z_Malloc(newsamples<<2, PU_SOUND, 0); // samples * frequency shift * bytes per sample * channels + sound = Z_Malloc(newsamples<<2, PU_SOUND, NULL); // samples * frequency shift * bytes per sample * channels s = (SINT8 *)stream; d = (INT16 *)sound; From 02597e0bf923c76cb1aed2bd15c285371bdd71ff Mon Sep 17 00:00:00 2001 From: Sryder Date: Sun, 7 Oct 2018 09:26:18 +0100 Subject: [PATCH 281/306] Fix compiler warnings. --- src/sdl/mixer_sound.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 9fef16460..ed15fcdaa 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -246,6 +246,7 @@ void *I_GetSfx(sfxinfo_t *sfx) { void *lump; Mix_Chunk *chunk; + SDL_RWops *rw; #ifdef HAVE_LIBGME Music_Emu *emu; gme_info_t *info; @@ -387,10 +388,10 @@ void *I_GetSfx(sfxinfo_t *sfx) #endif // Try to load it as a WAVE or OGG using Mixer. - SDL_RWops *rw = SDL_RWFromMem(lump, sfx->length); + rw = SDL_RWFromMem(lump, sfx->length); if (rw != NULL) { - Mix_Chunk *chunk = Mix_LoadWAV_RW(rw, 1); + chunk = Mix_LoadWAV_RW(rw, 1); SDL_RWclose(rw); return chunk; } @@ -547,6 +548,7 @@ boolean I_StartDigSong(const char *musicname, boolean looping) char *data; size_t len; lumpnum_t lumpnum = W_CheckNumForName(va("O_%s",musicname)); + SDL_RWops *rw; I_Assert(!music); #ifdef HAVE_LIBGME @@ -658,7 +660,7 @@ boolean I_StartDigSong(const char *musicname, boolean looping) } #endif - SDL_RWops *rw = SDL_RWFromMem(data, len); + rw = SDL_RWFromMem(data, len); if (rw != NULL) { music = Mix_LoadMUS_RW(rw, SDL_FALSE); From fb6c3298702e76ee8a167264cc7dc0e86936f862 Mon Sep 17 00:00:00 2001 From: Sryder Date: Sun, 7 Oct 2018 10:37:45 +0100 Subject: [PATCH 282/306] Fix the crashing bug hopefully A value of 1 in freesrc for Mix_LoadWAV_RW and Mix_LoadMus_RW calls SDL_RWclose on the RWops anyway. For Mix_LoadWAV_RW the RWops is freed right after the data is loaded (because it makes a copy of the data in memory) For Mix_LoadMUS_RW the RWops is freed when Mix_FreeMusic is called (because the data is not a copy) So setting 1 on freesrc doesn't actually free the RWops immediately on Mix_LoadMus_RW *unless* it failed to load any music. --- src/sdl/mixer_sound.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index ed15fcdaa..53a767dfb 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -392,7 +392,6 @@ void *I_GetSfx(sfxinfo_t *sfx) if (rw != NULL) { chunk = Mix_LoadWAV_RW(rw, 1); - SDL_RWclose(rw); return chunk; } @@ -663,8 +662,7 @@ boolean I_StartDigSong(const char *musicname, boolean looping) rw = SDL_RWFromMem(data, len); if (rw != NULL) { - music = Mix_LoadMUS_RW(rw, SDL_FALSE); - SDL_RWclose(rw); + music = Mix_LoadMUS_RW(rw, 1); } if (!music) { @@ -831,8 +829,7 @@ INT32 I_RegisterSong(void *data, size_t len) SDL_RWops *rw = SDL_RWFromMem(data, len); if (rw != NULL) { - music = Mix_LoadMUS_RW(rw, SDL_FALSE); - SDL_RWclose(rw); + music = Mix_LoadMUS_RW(rw, 1); } if (!music) { From b1e02467bfc009d1b08d83a12181fde87869bae0 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 7 Oct 2018 15:00:58 +0100 Subject: [PATCH 283/306] Weather is already run client-side. What if we ran it render-side, for major performance gains? This commit will answer all your questions - and more! --- src/hardware/hw_main.c | 22 ++++++++++++++++++---- src/p_mobj.c | 37 ++++++++++++++++++++----------------- src/p_mobj.h | 4 ++++ src/p_saveg.c | 6 ++---- src/p_spec.c | 34 ++++++++++------------------------ src/p_tick.c | 24 ++++++++++++------------ src/r_things.c | 23 +++++++++++++++++++---- 7 files changed, 85 insertions(+), 65 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index d7c73415a..871a6a493 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5140,8 +5140,10 @@ static void HWR_AddSprites(sector_t *sec) approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y); - if (approx_dist <= limit_dist) - HWR_ProjectSprite(thing); + if (approx_dist > limit_dist) + continue; + + HWR_ProjectSprite(thing); } } else @@ -5163,8 +5165,10 @@ static void HWR_AddSprites(sector_t *sec) approx_dist = P_AproxDistance(viewx-precipthing->x, viewy-precipthing->y); - if (approx_dist <= limit_dist) - HWR_ProjectPrecipitationSprite(precipthing); + if (approx_dist > limit_dist) + continue; + + HWR_ProjectPrecipitationSprite(precipthing); } } else @@ -5449,6 +5453,16 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) x1 = tr_x + x1 * rightcos; x2 = tr_x - x2 * rightcos; + // okay, we can't return now... this is a hack, but weather isn't networked, so it should be ok + if (!(thing->precipflags & PCF_THUNK)) + { + if (thing->precipflags & PCF_RAIN) + P_RainThinker(thing); + else + P_SnowThinker(thing); + thing->precipflags |= PCF_THUNK; + } + // // store information in a vissprite // diff --git a/src/p_mobj.c b/src/p_mobj.c index 5f85474c6..bb9483d18 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3840,7 +3840,8 @@ void P_RecalcPrecipInSector(sector_t *sector) // void P_NullPrecipThinker(precipmobj_t *mobj) { - (void)mobj; + //(void)mobj; + mobj->precipflags &= ~PCF_THUNK; } void P_SnowThinker(precipmobj_t *mobj) @@ -3860,25 +3861,26 @@ void P_RainThinker(precipmobj_t *mobj) { // cycle through states, // calling action functions at transitions - if (mobj->tics > 0 && --mobj->tics == 0) - { - // you can cycle through multiple states in a tic - if (!P_SetPrecipMobjState(mobj, mobj->state->nextstate)) - return; // freed itself - } + if (mobj->tics <= 0) + return; + + if (--mobj->tics) + return; + + if (!P_SetPrecipMobjState(mobj, mobj->state->nextstate)) + return; + + if (mobj->state != &states[S_RAINRETURN]) + return; + + mobj->z = mobj->ceilingz; + P_SetPrecipMobjState(mobj, S_RAIN1); - if (mobj->state == &states[S_RAINRETURN]) - { - mobj->z = mobj->ceilingz; - P_SetPrecipMobjState(mobj, S_RAIN1); - } return; } // adjust height - mobj->z += mobj->momz; - - if (mobj->z <= mobj->floorz) + if ((mobj->z += mobj->momz) <= mobj->floorz) { // no splashes on sky or bottomless pits if (mobj->precipflags & PCF_PIT) @@ -7926,14 +7928,15 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype static inline precipmobj_t *P_SpawnRainMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { precipmobj_t *mo = P_SpawnPrecipMobj(x,y,z,type); - mo->thinker.function.acp1 = (actionf_p1)P_RainThinker; + mo->precipflags |= PCF_RAIN; + //mo->thinker.function.acp1 = (actionf_p1)P_RainThinker; return mo; } static inline precipmobj_t *P_SpawnSnowMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { precipmobj_t *mo = P_SpawnPrecipMobj(x,y,z,type); - mo->thinker.function.acp1 = (actionf_p1)P_SnowThinker; + //mo->thinker.function.acp1 = (actionf_p1)P_SnowThinker; return mo; } diff --git a/src/p_mobj.h b/src/p_mobj.h index 79cffae89..620028d81 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -252,6 +252,10 @@ typedef enum { PCF_FOF = 4, // Above MOVING FOF (this means we need to keep floorz up to date...) PCF_MOVINGFOF = 8, + // Is rain. + PCF_RAIN = 16, + // Ran the thinker this tic. + PCF_THUNK = 32, } precipflag_t; // Map Object definition. typedef struct mobj_s diff --git a/src/p_saveg.c b/src/p_saveg.c index d1ec8e5ab..17d28302e 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1661,8 +1661,7 @@ static void P_NetArchiveThinkers(void) for (th = thinkercap.next; th != &thinkercap; th = th->next) { if (!(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed - || th->function.acp1 == (actionf_p1)P_RainThinker - || th->function.acp1 == (actionf_p1)P_SnowThinker)) + || th->function.acp1 == (actionf_p1)P_NullPrecipThinker)) numsaved++; if (th->function.acp1 == (actionf_p1)P_MobjThinker) @@ -1671,8 +1670,7 @@ static void P_NetArchiveThinkers(void) continue; } #ifdef PARANOIA - else if (th->function.acp1 == (actionf_p1)P_RainThinker - || th->function.acp1 == (actionf_p1)P_SnowThinker); + else if (th->function.acp1 == (actionf_p1)P_NullPrecipThinker); #endif else if (th->function.acp1 == (actionf_p1)T_MoveCeiling) { diff --git a/src/p_spec.c b/src/p_spec.c index c62c3b209..ff6691a99 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2039,8 +2039,7 @@ void P_SwitchWeather(INT32 weathernum) for (think = thinkercap.next; think != &thinkercap; think = think->next) { - if ((think->function.acp1 != (actionf_p1)P_SnowThinker) - && (think->function.acp1 != (actionf_p1)P_RainThinker)) + if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) continue; // not a precipmobj thinker precipmobj = (precipmobj_t *)think; @@ -2056,14 +2055,12 @@ void P_SwitchWeather(INT32 weathernum) for (think = thinkercap.next; think != &thinkercap; think = think->next) { + if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) + continue; // not a precipmobj thinker + precipmobj = (precipmobj_t *)think; + if (swap == PRECIP_RAIN) // Snow To Rain { - if (!(think->function.acp1 == (actionf_p1)P_SnowThinker - || think->function.acp1 == (actionf_p1)P_NullPrecipThinker)) - continue; // not a precipmobj thinker - - precipmobj = (precipmobj_t *)think; - precipmobj->flags = mobjinfo[MT_RAIN].flags; st = &states[mobjinfo[MT_RAIN].spawnstate]; precipmobj->state = st; @@ -2074,18 +2071,13 @@ void P_SwitchWeather(INT32 weathernum) precipmobj->precipflags &= ~PCF_INVISIBLE; - think->function.acp1 = (actionf_p1)P_RainThinker; + precipmobj->precipflags |= PCF_RAIN; + //think->function.acp1 = (actionf_p1)P_RainThinker; } else if (swap == PRECIP_SNOW) // Rain To Snow { INT32 z; - if (!(think->function.acp1 == (actionf_p1)P_RainThinker - || think->function.acp1 == (actionf_p1)P_NullPrecipThinker)) - continue; // not a precipmobj thinker - - precipmobj = (precipmobj_t *)think; - precipmobj->flags = mobjinfo[MT_SNOWFLAKE].flags; z = M_RandomByte(); @@ -2103,19 +2095,13 @@ void P_SwitchWeather(INT32 weathernum) precipmobj->frame = st->frame; precipmobj->momz = mobjinfo[MT_SNOWFLAKE].speed; - precipmobj->precipflags &= ~PCF_INVISIBLE; + precipmobj->precipflags &= ~(PCF_INVISIBLE|PCF_RAIN); - think->function.acp1 = (actionf_p1)P_SnowThinker; + //think->function.acp1 = (actionf_p1)P_SnowThinker; } else if (swap == PRECIP_BLANK || swap == PRECIP_STORM_NORAIN) // Remove precip, but keep it around for reuse. { - if (!(think->function.acp1 == (actionf_p1)P_RainThinker - || think->function.acp1 == (actionf_p1)P_SnowThinker)) - continue; - - precipmobj = (precipmobj_t *)think; - - think->function.acp1 = (actionf_p1)P_NullPrecipThinker; + //think->function.acp1 = (actionf_p1)P_NullPrecipThinker; precipmobj->precipflags |= PCF_INVISIBLE; } diff --git a/src/p_tick.c b/src/p_tick.c index f4bc59323..5ba747078 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -56,12 +56,12 @@ void Command_Numthinkers_f(void) CONS_Printf(M_GetText("numthinkers <#>: Count number of thinkers\n")); CONS_Printf( "\t1: P_MobjThinker\n" - "\t2: P_RainThinker\n" - "\t3: P_SnowThinker\n" - "\t4: P_NullPrecipThinker\n" - "\t5: T_Friction\n" - "\t6: T_Pusher\n" - "\t7: P_RemoveThinkerDelayed\n"); + /*"\t2: P_RainThinker\n" + "\t3: P_SnowThinker\n"*/ + "\t2: P_NullPrecipThinker\n" + "\t3: T_Friction\n" + "\t4: T_Pusher\n" + "\t5: P_RemoveThinkerDelayed\n"); return; } @@ -73,27 +73,27 @@ void Command_Numthinkers_f(void) action = (actionf_p1)P_MobjThinker; CONS_Printf(M_GetText("Number of %s: "), "P_MobjThinker"); break; - case 2: + /*case 2: action = (actionf_p1)P_RainThinker; CONS_Printf(M_GetText("Number of %s: "), "P_RainThinker"); break; case 3: action = (actionf_p1)P_SnowThinker; CONS_Printf(M_GetText("Number of %s: "), "P_SnowThinker"); - break; - case 4: + break;*/ + case 2: action = (actionf_p1)P_NullPrecipThinker; CONS_Printf(M_GetText("Number of %s: "), "P_NullPrecipThinker"); break; - case 5: + case 3: action = (actionf_p1)T_Friction; CONS_Printf(M_GetText("Number of %s: "), "T_Friction"); break; - case 6: + case 4: action = (actionf_p1)T_Pusher; CONS_Printf(M_GetText("Number of %s: "), "T_Pusher"); break; - case 7: + case 5: action = (actionf_p1)P_RemoveThinkerDelayed; CONS_Printf(M_GetText("Number of %s: "), "P_RemoveThinkerDelayed"); break; diff --git a/src/r_things.c b/src/r_things.c index 0b1764167..910a52b30 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1451,6 +1451,17 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) return; } + // okay, we can't return now except for vertical clipping... this is a hack, but weather isn't networked, so it should be ok + if (!(thing->precipflags & PCF_THUNK)) + { + if (thing->precipflags & PCF_RAIN) + P_RainThinker(thing); + else + P_SnowThinker(thing); + thing->precipflags |= PCF_THUNK; + } + + //SoM: 3/17/2000: Disregard sprites that are out of view.. gzt = thing->z + spritecachedinfo[lump].topoffset; gz = gzt - spritecachedinfo[lump].height; @@ -1569,8 +1580,10 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel) approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y); - if (approx_dist <= limit_dist) - R_ProjectSprite(thing); + if (approx_dist > limit_dist) + continue; + + R_ProjectSprite(thing); } } else @@ -1591,8 +1604,10 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel) approx_dist = P_AproxDistance(viewx-precipthing->x, viewy-precipthing->y); - if (approx_dist <= limit_dist) - R_ProjectPrecipitationSprite(precipthing); + if (approx_dist > limit_dist) + continue; + + R_ProjectPrecipitationSprite(precipthing); } } else From def090c9f0245c148d2313c30c4ef398578d1738 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 7 Oct 2018 14:45:03 -0400 Subject: [PATCH 284/306] Move the ifdef --- src/sdl/mixer_sound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index d1083518a..1b0974b17 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -52,11 +52,11 @@ #ifndef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 0 #endif -#endif #ifdef HAVE_ZLIB #include "zlib.h" #endif +#endif UINT8 sound_started = false; From 232a7ae7b713c5c5854d0d0205a4fbd5dea9ee47 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 7 Oct 2018 14:52:25 -0400 Subject: [PATCH 285/306] Change order of the ifdef --- src/sdl/mixer_sound.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 1b0974b17..c4d2a8b08 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -39,6 +39,7 @@ #define GME_TREBLE 5.0 #define GME_BASS 1.0 +#ifdef HAVE_ZLIB #ifndef _MSC_VER #ifndef _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE @@ -53,10 +54,9 @@ #define _FILE_OFFSET_BITS 0 #endif -#ifdef HAVE_ZLIB #include "zlib.h" -#endif -#endif +#endif // HAVE_ZLIB +#endif // HAVE_LIBGME UINT8 sound_started = false; From 027e6e8e3c91777efa302c63ab5eab23e315925d Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 7 Oct 2018 15:00:48 -0400 Subject: [PATCH 286/306] Change win_snd.c also --- src/win32/win_snd.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index bc04bd6df..58644457a 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -18,13 +18,12 @@ #define GME_TREBLE 5.0 #define GME_BASS 1.0 +#ifdef HAVE_ZLIB #ifndef _MSC_VER -#ifndef _WII #ifndef _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE #endif #endif -#endif #ifndef _LFS64_LARGEFILE #define _LFS64_LARGEFILE @@ -34,10 +33,9 @@ #define _FILE_OFFSET_BITS 0 #endif -#ifdef HAVE_ZLIB #include "zlib.h" -#endif -#endif +#endif // HAVE_ZLIB +#endif // HAVE_LIBGME static FMOD_SYSTEM *fsys; static FMOD_SOUND *music_stream; From 1324e0bfcd945651a90c339042523d4f35e89a24 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 8 Oct 2018 18:50:17 +0100 Subject: [PATCH 287/306] * Fix a memory leak regarding implementation of SOC_ (improperly copypasted code from LUA_LoadLump!!) * Optimise the repeated strlen usage into a single call, which is stored for later. --- src/lua_script.c | 12 +++++++----- src/w_wad.c | 15 ++++++++++----- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/lua_script.c b/src/lua_script.c index ce96878bf..1c1b01f6c 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -182,19 +182,21 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump) { MYFILE f; char *name; + size_t len; f.wad = wad; f.size = W_LumpLengthPwad(wad, lump); f.data = Z_Malloc(f.size, PU_LUA, NULL); W_ReadLumpPwad(wad, lump, f.data); f.curpos = f.data; - name = malloc(strlen(wadfiles[wad]->filename)+10); + len = strlen(wadfiles[wad]->filename); + name = malloc(len+10); strcpy(name, wadfiles[wad]->filename); - if (!fasticmp(&name[strlen(name) - 4], ".lua")) { + if (!fasticmp(&name[len - 4], ".lua")) { // If it's not a .lua file, copy the lump name in too. - name[strlen(wadfiles[wad]->filename)] = '|'; - M_Memcpy(name+strlen(wadfiles[wad]->filename)+1, wadfiles[wad]->lumpinfo[lump].name, 8); - name[strlen(wadfiles[wad]->filename)+9] = '\0'; + name[len] = '|'; + M_Memcpy(name+len+1, wadfiles[wad]->lumpinfo[lump].name, 8); + name[len+9] = '\0'; } LUA_LoadFile(&f, name); diff --git a/src/w_wad.c b/src/w_wad.c index 3a8285593..3f0082a16 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -194,16 +194,21 @@ static inline void W_LoadDehackedLumps(UINT16 wadnum) for (lump = 0; lump < wadfiles[wadnum]->numlumps; lump++, lump_p++) if (memcmp(lump_p->name,"SOC_",4)==0) // Check for generic SOC lump { // shameless copy+paste of code from LUA_LoadLump - char *name = malloc(strlen(wadfiles[wadnum]->filename)+10); + size_t len = strlen(wadfiles[wadnum]->filename); + char *name = malloc(len+10); + strcpy(name, wadfiles[wadnum]->filename); - if (!fasticmp(&name[strlen(name) - 4], ".soc")) { + if (!fasticmp(&name[len - 4], ".soc")) { // If it's not a .soc file, copy the lump name in too. - name[strlen(wadfiles[wadnum]->filename)] = '|'; - M_Memcpy(name+strlen(wadfiles[wadnum]->filename)+1, lump_p->name, 8); - name[strlen(wadfiles[wadnum]->filename)+9] = '\0'; + name[len] = '|'; + M_Memcpy(name+len+1, lump_p->name, 8); + name[len+9] = '\0'; } + CONS_Printf(M_GetText("Loading SOC from %s\n"), name); DEH_LoadDehackedLumpPwad(wadnum, lump); + + free(name); } else if (memcmp(lump_p->name,"MAINCFG",8)==0) // Check for MAINCFG { From 497314fdc44551a46395f41cd579d845d92b270e Mon Sep 17 00:00:00 2001 From: Sryder Date: Tue, 9 Oct 2018 19:43:18 +0100 Subject: [PATCH 288/306] Tiny fix so that joystick2 being closed can let the JoystickSubSystem close before game close. No memory leak here, just a very tiny thing I noticed. --- src/sdl/i_system.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index f92cd4b6e..7b14f1f18 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1154,6 +1154,7 @@ static void I_ShutdownJoystick2(void) D_PostEvent(&event); } + joystick2_started = 0; JoyReset(&JoyInfo2); if (!joystick_started && !joystick2_started && SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) { From 77e85394d8fe59d70b96085f64062118ea261986 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 10 Oct 2018 14:59:44 +0100 Subject: [PATCH 289/306] Change when and specifically what colormap[] is applied to in R_Draw2sMultiPatchTranslucentColumn_8 --- src/r_draw8.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/r_draw8.c b/src/r_draw8.c index 76eb58c0d..bda146546 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -261,7 +261,7 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void) val = source[frac>>FRACBITS]; if (val != TRANSPARENTPIXEL) - *dest = colormap[*(transmap + (val<<8) + (*dest))]; + *dest = *(transmap + (colormap[val]<<8) + (*dest)); dest += vid.width; @@ -281,12 +281,12 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void) { val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) - *dest = colormap[*(transmap + (val<<8) + (*dest))]; + *dest = *(transmap + (colormap[val]<<8) + (*dest)); dest += vid.width; frac += fracstep; val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) - *dest = colormap[*(transmap + (val<<8) + (*dest))]; + *dest = *(transmap + (colormap[val]<<8) + (*dest)); dest += vid.width; frac += fracstep; } @@ -294,7 +294,7 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void) { val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) - *dest = colormap[*(transmap + (val<<8) + (*dest))]; + *dest = *(transmap + (colormap[val]<<8) + (*dest)); } } } From a4419abfdc21d0d0ec69e3d73528a4c9bb68205e Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 25 Jan 2017 19:36:32 +0000 Subject: [PATCH 290/306] debugfile is only used by DEBUGFILE code, no need to declare/define it for anything else --- src/d_net.c | 2 ++ src/doomstat.h | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/d_net.c b/src/d_net.c index 643c41ac9..8de5cf088 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -49,7 +49,9 @@ doomcom_t *doomcom = NULL; /// \brief network packet data, points inside doomcom doomdata_t *netbuffer = NULL; +#ifdef DEBUGFILE FILE *debugfile = NULL; // put some net info in a file during the game +#endif #define MAXREBOUND 8 static doomdata_t reboundstore[MAXREBOUND]; diff --git a/src/doomstat.h b/src/doomstat.h index 8072a1552..341cc70a9 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -445,19 +445,17 @@ extern mapthing_t *redctfstarts[MAXPLAYERS]; // CTF #if defined (macintosh) #define DEBFILE(msg) I_OutputMsg(msg) -extern FILE *debugfile; #else #define DEBUGFILE #ifdef DEBUGFILE #define DEBFILE(msg) { if (debugfile) { fputs(msg, debugfile); fflush(debugfile); } } -extern FILE *debugfile; #else #define DEBFILE(msg) {} -extern FILE *debugfile; #endif #endif #ifdef DEBUGFILE +extern FILE *debugfile; extern INT32 debugload; #endif From 61a29bed853a737f79fb5aac2c1ceb4ddd758aeb Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 11 Feb 2017 22:41:15 +0000 Subject: [PATCH 291/306] Remove unused sscount variable (it's only set to 0 in software, and only ++'d in OpenGL, what kind of sense does that make?) --- src/hardware/hw_bsp.c | 2 -- src/hardware/hw_main.c | 1 - src/r_main.c | 5 ----- src/r_state.h | 3 --- 4 files changed, 11 deletions(-) diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c index 17eb8761c..a32609fc8 100644 --- a/src/hardware/hw_bsp.c +++ b/src/hardware/hw_bsp.c @@ -564,8 +564,6 @@ static inline void HWR_SubsecPoly(INT32 num, poly_t *poly) subsector_t *sub; seg_t *lseg; - sscount++; - sub = &subsectors[num]; count = sub->numlines; lseg = &segs[sub->firstline]; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 871a6a493..ecb70a0f9 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3264,7 +3264,6 @@ static void HWR_Subsector(size_t num) if (num < numsubsectors) { - sscount++; // subsector sub = &subsectors[num]; // sector diff --git a/src/r_main.c b/src/r_main.c index f2a0c8894..6c92983f4 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -60,7 +60,6 @@ fixed_t projectiony; // aspect ratio // just for profiling purposes size_t framecount; -size_t sscount; size_t loopcount; fixed_t viewx, viewy, viewz; @@ -964,8 +963,6 @@ void R_SkyboxFrame(player_t *player) viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); - sscount = 0; - // recalc necessary stuff for mouseaiming // slopes are already calculated for the full possible view (which is 4*viewheight). @@ -1089,8 +1086,6 @@ void R_SetupFrame(player_t *player, boolean skybox) viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); - sscount = 0; - // recalc necessary stuff for mouseaiming // slopes are already calculated for the full possible view (which is 4*viewheight). diff --git a/src/r_state.h b/src/r_state.h index 49d0457b2..ac3e1fa42 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -108,7 +108,4 @@ extern angle_t rw_normalangle; // angle to line origin extern angle_t rw_angle1; -// Segs count? -extern size_t sscount; - #endif From 07dd527e7e58e06ce621e80357bef7ae91424f76 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 11 Feb 2017 22:56:08 +0000 Subject: [PATCH 292/306] Removed unused function prototypes in d_main.h Also corrected what appears to be a typo in some comments above? --- src/d_main.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/d_main.h b/src/d_main.h index 6dc273b15..d73b19d1f 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -34,7 +34,7 @@ void D_SRB2Loop(void) FUNCNORETURN; // D_SRB2Main() // Not a globally visible function, just included for source reference, // calls all startup code, parses command line options. -// If not overrided by user input, calls N_AdvanceDemo. +// If not overrided by user input, calls D_AdvanceDemo. // void D_SRB2Main(void); @@ -51,9 +51,6 @@ const char *D_Home(void); // // BASE LEVEL // -void D_PageTicker(void); -// pagename is lumpname of a 320x200 patch to fill the screen -void D_PageDrawer(const char *pagename); void D_AdvanceDemo(void); void D_StartTitle(void); From 91b2f5e570b1b3783b54ca014a11ed07d0570ef4 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 11 Feb 2017 23:24:12 +0000 Subject: [PATCH 293/306] "t" is not needed to take out fencepost cases from viewangletox --- src/r_main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/r_main.c b/src/r_main.c index 6c92983f4..d1cd71b3f 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -491,9 +491,6 @@ static void R_InitTextureMapping(void) // Take out the fencepost cases from viewangletox. for (i = 0; i < FINEANGLES/2; i++) { - t = FixedMul(FINETANGENT(i), focallength); - t = centerx - t; - if (viewangletox[i] == -1) viewangletox[i] = 0; else if (viewangletox[i] == viewwidth+1) From 49c5a6f7e474ff6aa30a726ae7cbcf9e224fb533 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 11 Feb 2017 23:28:42 +0000 Subject: [PATCH 294/306] Remove unused "runcount" variable from p_local.h --- src/p_local.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/p_local.h b/src/p_local.h index 1fd7ada04..b82bcf0ec 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -68,7 +68,6 @@ // both the head and tail of the thinker list extern thinker_t thinkercap; -extern INT32 runcount; void P_InitThinkers(void); void P_AddThinker(thinker_t *thinker); From ef78c942f798e0d736cc84de8b912889d9232fbc Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 15 Feb 2017 21:16:56 +0000 Subject: [PATCH 295/306] Remove unused ObjectPlace_OnChange prototype (from when Objectplace was a consvar, which it is not anymore) --- src/d_netcmd.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/d_netcmd.h b/src/d_netcmd.h index d8fae72f7..023bbd094 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -212,7 +212,6 @@ void Command_ExitGame_f(void); void Command_Retry_f(void); void D_GameTypeChanged(INT32 lastgametype); // not a real _OnChange function anymore void D_MapChange(INT32 pmapnum, INT32 pgametype, boolean pultmode, boolean presetplayers, INT32 pdelay, boolean pskipprecutscene, boolean pfromlevelselect); -void ObjectPlace_OnChange(void); void ItemFinder_OnChange(void); void D_SetPassword(const char *pw); From 9c464742b7d0b10b35ef27dcdad2e72d33e4f8da Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 22 Feb 2017 21:07:29 +0000 Subject: [PATCH 296/306] Remove "playerdeadview" variable; it's not been used for its stated purpose for who knows how long now Besides rankings popping up when you die just sounds weird anyway, maybe I'm just used to SRB2 not doing it I guess --- src/d_clisrv.c | 2 -- src/d_main.c | 1 - src/f_finale.c | 6 ------ src/g_game.c | 1 - src/hu_stuff.h | 3 --- src/p_user.c | 9 --------- 6 files changed, 22 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 6e22dde23..950038237 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1568,8 +1568,6 @@ static void CL_LoadReceivedSavegame(void) automapactive = false; // load a base level - playerdeadview = false; - if (P_LoadNetGame()) { const INT32 actnum = mapheaderinfo[gamemap-1]->actnum; diff --git a/src/d_main.c b/src/d_main.c index df3398752..f807e3070 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -720,7 +720,6 @@ void D_StartTitle(void) maptol = 0; gameaction = ga_nothing; - playerdeadview = false; displayplayer = consoleplayer = 0; //demosequence = -1; gametype = GT_COOP; diff --git a/src/f_finale.c b/src/f_finale.c index a8b27bb80..fb1387c11 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -442,7 +442,6 @@ void F_StartIntro(void) G_SetGamestate(GS_INTRO); gameaction = ga_nothing; - playerdeadview = false; paused = false; CON_ToggleOff(); CON_ClearHUD(); @@ -1130,7 +1129,6 @@ void F_StartCredits(void) } gameaction = ga_nothing; - playerdeadview = false; paused = false; CON_ToggleOff(); CON_ClearHUD(); @@ -1277,7 +1275,6 @@ void F_StartGameEvaluation(void) G_SaveGame((UINT32)cursaveslot); gameaction = ga_nothing; - playerdeadview = false; paused = false; CON_ToggleOff(); CON_ClearHUD(); @@ -1388,7 +1385,6 @@ void F_StartGameEnd(void) G_SetGamestate(GS_GAMEEND); gameaction = ga_nothing; - playerdeadview = false; paused = false; CON_ToggleOff(); CON_ClearHUD(); @@ -1591,7 +1587,6 @@ void F_StartContinue(void) gameaction = ga_nothing; keypressed = false; - playerdeadview = false; paused = false; CON_ToggleOff(); CON_ClearHUD(); @@ -1760,7 +1755,6 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset G_SetGamestate(GS_CUTSCENE); gameaction = ga_nothing; - playerdeadview = false; paused = false; CON_ToggleOff(); diff --git a/src/g_game.c b/src/g_game.c index 4f1c49b42..0e8c14f6a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3616,7 +3616,6 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean mapmusflags |= MUSIC_RELOADRESET; ultimatemode = pultmode; - playerdeadview = false; automapactive = false; imcontinuing = false; diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 7b22f33f1..5356ba8ac 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -78,9 +78,6 @@ extern boolean chat_on; // set true whenever the tab rankings are being shown for any reason extern boolean hu_showscores; -// P_DeathThink sets this true to show scores while dead, in multiplayer -extern boolean playerdeadview; - // init heads up data at game startup. void HU_Init(void); diff --git a/src/p_user.c b/src/p_user.c index 7abf85347..7e206930d 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8648,8 +8648,6 @@ void P_DoPityCheck(player_t *player) // P_PlayerThink // -boolean playerdeadview; // show match/chaos/tag/capture the flag rankings while in death view - void P_PlayerThink(player_t *player) { ticcmd_t *cmd; @@ -8838,10 +8836,6 @@ void P_PlayerThink(player_t *player) if (player->playerstate == PST_DEAD) { player->mo->flags2 &= ~MF2_SHADOW; - // show the multiplayer rankings while dead - if (player == &players[displayplayer]) - playerdeadview = true; - P_DeathThink(player); return; @@ -8862,9 +8856,6 @@ void P_PlayerThink(player_t *player) player->lives = cv_startinglives.value; } - if (player == &players[displayplayer]) - playerdeadview = false; - if ((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE) { cmd->buttons &= BT_USE; // Remove all buttons except BT_USE From c1d5c711a940fc2e66cbfe53571be01f8bee9420 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 19 Apr 2017 20:00:19 +0100 Subject: [PATCH 297/306] Be gone ye old texture hack --- src/r_data.c | 32 +++++++------------------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index f2c9b1466..ee9144b72 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -472,40 +472,22 @@ void R_LoadTextures(void) } else { - UINT16 patchcount = 1; //CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height); - if (SHORT(patchlump->width) == 64 - && SHORT(patchlump->height) == 64) - { // 64x64 patch - const column_t *column; - for (k = 0; k < SHORT(patchlump->width); k++) - { // Find use of transparency. - column = (const column_t *)((const UINT8 *)patchlump + LONG(patchlump->columnofs[k])); - if (column->length != SHORT(patchlump->height)) - break; - } - if (k == SHORT(patchlump->width)) - patchcount = 2; // No transparency? 64x128 texture. - } - texture = textures[i] = Z_Calloc(sizeof(texture_t) + (sizeof(texpatch_t) * patchcount), PU_STATIC, NULL); + texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL); // Set texture properties. M_Memcpy(texture->name, W_CheckNameForNumPwad((UINT16)w, texstart + j), sizeof(texture->name)); texture->width = SHORT(patchlump->width); - texture->height = SHORT(patchlump->height)*patchcount; - texture->patchcount = patchcount; + texture->height = SHORT(patchlump->height); + texture->patchcount = 1; texture->holes = false; // Allocate information for the texture's patches. - for (k = 0; k < patchcount; k++) - { - patch = &texture->patches[k]; + patch = &texture->patches[0]; - patch->originx = 0; - patch->originy = (INT16)(k*patchlump->height); - patch->wad = (UINT16)w; - patch->lump = texstart + j; - } + patch->originx = patch->originy = 0; + patch->wad = (UINT16)w; + patch->lump = texstart + j; Z_Unlock(patchlump); From 31f3f8b8e787f41e4c22ac2d84130f0a02861912 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 18 May 2017 16:54:58 +0100 Subject: [PATCH 298/306] Moved Y_EndGame from y_inter.c/h to g_game.c/h, renamed it to G_EndGame --- src/f_finale.c | 4 ++-- src/g_game.c | 34 +++++++++++++++++++++++++++++++++- src/g_game.h | 1 + src/y_inter.c | 33 +-------------------------------- src/y_inter.h | 1 - 5 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index a8b27bb80..0a4486928 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1733,7 +1733,7 @@ static void F_AdvanceToNextScene(void) void F_EndCutScene(void) { - cutsceneover = true; // do this first, just in case Y_EndGame or something wants to turn it back false later + cutsceneover = true; // do this first, just in case G_EndGame or something wants to turn it back false later if (runningprecutscene) { if (server) @@ -1748,7 +1748,7 @@ void F_EndCutScene(void) else if (nextmap < 1100-1) G_NextLevel(); else - Y_EndGame(); + G_EndGame(); } } diff --git a/src/g_game.c b/src/g_game.c index 4f1c49b42..25730ce7d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2911,7 +2911,7 @@ void G_AfterIntermission(void) if (nextmap < 1100-1) G_NextLevel(); else - Y_EndGame(); + G_EndGame(); } } @@ -2997,6 +2997,38 @@ static void G_DoContinued(void) gameaction = ga_nothing; } +// +// G_EndGame (formerly Y_EndGame) +// Franky this function fits better in g_game.c than it does in y_inter.c +// +// ...Gee, (why) end the game? +// Because Y_FollowIntermission and F_EndCutscene would +// both do this exact same thing *in different ways* otherwise, +// which made it so that you could only unlock Ultimate mode +// if you had a cutscene after the final level and crap like that. +// This function simplifies it so only one place has to be updated +// when something new is added. +void G_EndGame(void) +{ + // Only do evaluation and credits in coop games. + if (gametype == GT_COOP) + { + if (nextmap == 1102-1) // end game with credits + { + F_StartCredits(); + return; + } + if (nextmap == 1101-1) // end game with evaluation + { + F_StartGameEvaluation(); + return; + } + } + + // 1100 or competitive multiplayer, so go back to title screen. + D_StartTitle(); +} + // // G_LoadGameSettings // diff --git a/src/g_game.h b/src/g_game.h index ada82404c..196ba2ea1 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -171,6 +171,7 @@ void G_NextLevel(void); void G_Continue(void); void G_UseContinue(void); void G_AfterIntermission(void); +void G_EndGame(void); // moved from y_inter.c/h and renamed void G_Ticker(boolean run); boolean G_Responder(event_t *ev); diff --git a/src/y_inter.c b/src/y_inter.c index e7df165bf..37c597305 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1794,37 +1794,6 @@ void Y_EndIntermission(void) usebuffer = false; } -// -// Y_EndGame -// -// Why end the game? -// Because Y_FollowIntermission and F_EndCutscene would -// both do this exact same thing *in different ways* otherwise, -// which made it so that you could only unlock Ultimate mode -// if you had a cutscene after the final level and crap like that. -// This function simplifies it so only one place has to be updated -// when something new is added. -void Y_EndGame(void) -{ - // Only do evaluation and credits in coop games. - if (gametype == GT_COOP) - { - if (nextmap == 1102-1) // end game with credits - { - F_StartCredits(); - return; - } - if (nextmap == 1101-1) // end game with evaluation - { - F_StartGameEvaluation(); - return; - } - } - - // 1100 or competitive multiplayer, so go back to title screen. - D_StartTitle(); -} - // // Y_FollowIntermission // @@ -1850,7 +1819,7 @@ static void Y_FollowIntermission(void) return; } - Y_EndGame(); + G_EndGame(); } #define UNLOAD(x) Z_ChangeTag(x, PU_CACHE); x = NULL diff --git a/src/y_inter.h b/src/y_inter.h index 9fe95fcc4..26f7dc390 100644 --- a/src/y_inter.h +++ b/src/y_inter.h @@ -15,7 +15,6 @@ void Y_IntermissionDrawer(void); void Y_Ticker(void); void Y_StartIntermission(void); void Y_EndIntermission(void); -void Y_EndGame(void); typedef enum { From 2bb7df5f49d90ac9f8c4d80ec5bbfeb11c9a064e Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 18 May 2017 17:10:44 +0100 Subject: [PATCH 299/306] G_ExitLevel tweak: Use HU_ClearCEcho() instead of HU_DoCEcho(""), the latter causes an empty line to appear in log.txt --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 25730ce7d..d145fcbef 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2615,7 +2615,7 @@ void G_ExitLevel(void) CONS_Printf(M_GetText("The round has ended.\n")); // Remove CEcho text on round end. - HU_DoCEcho(""); + HU_ClearCEcho(); } } From feceaf6d30144e19ef64e773705b637b242c7b05 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 18 May 2017 17:23:19 +0100 Subject: [PATCH 300/306] Removed all code in Y_FollowIntermission that's already handled in G_AfterIntermission Only real difference here is that CEcho messages will always be cleared when going to credits/evaluation, but that's hardly a loss tbh. --- src/g_game.c | 4 ++-- src/y_inter.c | 19 ++++--------------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index d145fcbef..b8df32f90 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2999,10 +2999,10 @@ static void G_DoContinued(void) // // G_EndGame (formerly Y_EndGame) -// Franky this function fits better in g_game.c than it does in y_inter.c +// Frankly this function fits better in g_game.c than it does in y_inter.c // // ...Gee, (why) end the game? -// Because Y_FollowIntermission and F_EndCutscene would +// Because G_AfterIntermission and F_EndCutscene would // both do this exact same thing *in different ways* otherwise, // which made it so that you could only unlock Ultimate mode // if you had a cutscene after the final level and crap like that. diff --git a/src/y_inter.c b/src/y_inter.c index 37c597305..9d41caf36 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1805,21 +1805,10 @@ static void Y_FollowIntermission(void) return; } - if (nextmap < 1100-1) - { - // normal level - G_AfterIntermission(); - return; - } - - // Start a custom cutscene if there is one. - if (mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking) - { - F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false); - return; - } - - G_EndGame(); + // This handles whether to play a post-level cutscene, end the game, + // or simply go to the next level. + // No need to duplicate the code here! + G_AfterIntermission(); } #define UNLOAD(x) Z_ChangeTag(x, PU_CACHE); x = NULL From 8ab4915b5bf83cc336e0666301b84e41807623e8 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 11 Oct 2018 21:44:25 +0100 Subject: [PATCH 301/306] Whoops these should be L not gL here (not that it makes much difference normally though) --- src/dehacked.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index f6288f487..6c39fc197 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8869,17 +8869,17 @@ static int lib_getActionName(lua_State *L) { lua_settop(L, 1); // set top of stack to 1 (removing any extra args, which there shouldn't be) // get the name for this action, if possible. - lua_getfield(gL, LUA_REGISTRYINDEX, LREG_ACTIONS); - lua_pushnil(gL); + lua_getfield(L, LUA_REGISTRYINDEX, LREG_ACTIONS); + lua_pushnil(L); // Lua stack at this point: // 1 ... -2 -1 // arg ... LREG_ACTIONS nil - while (lua_next(gL, -2)) + while (lua_next(L, -2)) { // Lua stack at this point: // 1 ... -3 -2 -1 // arg ... LREG_ACTIONS "A_ACTION" function - if (lua_rawequal(gL, -1, 1)) // is this the same as the arg? + if (lua_rawequal(L, -1, 1)) // is this the same as the arg? { // make sure the key (i.e. "A_ACTION") is a string first // (note: we don't use lua_isstring because it also returns true for numbers) @@ -8888,12 +8888,12 @@ static int lib_getActionName(lua_State *L) lua_pushvalue(L, -2); // push "A_ACTION" string to top of stack return 1; } - lua_pop(gL, 2); // pop the name and function + lua_pop(L, 2); // pop the name and function break; // probably should have succeeded but we didn't, so end the loop } - lua_pop(gL, 1); + lua_pop(L, 1); } - lua_pop(gL, 1); // pop LREG_ACTIONS + lua_pop(L, 1); // pop LREG_ACTIONS return 0; // return nothing (don't error) } From 6184f91dd3bd82164282c7379d457ffcea5e5a8c Mon Sep 17 00:00:00 2001 From: Sryder Date: Sat, 13 Oct 2018 23:01:11 +0100 Subject: [PATCH 302/306] Add an int to I_PlaySound to tell an interface which channel number SRB2 is using. I've voided this out on other sound interfaces than SDL Mixer ones because I'm both not sure whether they need it, and not sure how to make them work with it if they do. --- src/djgppdos/i_sound.c | 4 +++- src/dummy/i_sound.c | 3 ++- src/i_sound.h | 2 +- src/nds/i_sound.c | 3 ++- src/s_sound.c | 4 ++-- src/sdl/mixer_sound.c | 4 ++-- src/sdl/sdl_sound.c | 3 ++- src/sdl12/mixer_sound.c | 4 ++-- src/sdl12/sdl_sound.c | 3 ++- src/win32/win_snd.c | 3 ++- src/win32ce/win_snd.c | 4 +++- 11 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/djgppdos/i_sound.c b/src/djgppdos/i_sound.c index 88fc807f4..f1e2ad2bf 100644 --- a/src/djgppdos/i_sound.c +++ b/src/djgppdos/i_sound.c @@ -165,9 +165,11 @@ INT32 I_StartSound ( sfxenum_t id, INT32 vol, INT32 sep, INT32 pitch, - INT32 priority ) + INT32 priority + INT32 channel) { int voice; + (void)channel; if (nosound) return 0; diff --git a/src/dummy/i_sound.c b/src/dummy/i_sound.c index 51dbb610d..143da186c 100644 --- a/src/dummy/i_sound.c +++ b/src/dummy/i_sound.c @@ -23,13 +23,14 @@ void I_UpdateSound(void){}; // SFX I/O // -INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority) +INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel) { (void)id; (void)vol; (void)sep; (void)pitch; (void)priority; + (void)channel; return -1; } diff --git a/src/i_sound.h b/src/i_sound.h index 084479ee1..098c9be17 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -64,7 +64,7 @@ void I_ShutdownSound(void); \return sfx handle */ -INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority); +INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel); /** \brief Stops a sound channel. diff --git a/src/nds/i_sound.c b/src/nds/i_sound.c index 8dea4ad7d..a17c7f66a 100644 --- a/src/nds/i_sound.c +++ b/src/nds/i_sound.c @@ -21,13 +21,14 @@ void I_ShutdownSound(void){} // SFX I/O // -INT32 I_StartSound(sfxenum_t id, INT32 vol, INT32 sep, INT32 pitch, INT32 priority) +INT32 I_StartSound(sfxenum_t id, INT32 vol, INT32 sep, INT32 pitch, INT32 priority, INT32 channel) { (void)id; (void)vol; (void)sep; (void)pitch; (void)priority; + (void)channel; return -1; } diff --git a/src/s_sound.c b/src/s_sound.c index 76ee4c649..3b35b36f6 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -529,7 +529,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) // Assigns the handle to one of the channels in the // mix/output buffer. - channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority); + channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority, cnum); } dontplay: @@ -579,7 +579,7 @@ dontplay: // Assigns the handle to one of the channels in the // mix/output buffer. - channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority); + channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority, cnum); } void S_StartSound(const void *origin, sfxenum_t sfx_id) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index cfdb32303..4b4ad3e62 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -419,10 +419,10 @@ void I_FreeSfx(sfxinfo_t *sfx) sfx->lumpnum = LUMPERROR; } -INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority) +INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel) { UINT8 volume = (((UINT16)vol + 1) * (UINT16)sfx_volume) / 62; // (256 * 31) / 62 == 127 - INT32 handle = Mix_PlayChannel(-1, S_sfx[id].data, 0); + INT32 handle = Mix_PlayChannel(channel, S_sfx[id].data, 0); Mix_Volume(handle, volume); Mix_SetPanning(handle, min((UINT16)(0xff-sep)<<1, 0xff), min((UINT16)(sep)<<1, 0xff)); (void)pitch; // Mixer can't handle pitch diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index 6c70c163b..a7c8383a3 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -604,10 +604,11 @@ void I_FreeSfx(sfxinfo_t * sfx) // Pitching (that is, increased speed of playback) // is set, but currently not used by mixing. // -INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority) +INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel) { (void)priority; (void)pitch; + (void)channel; if (nosound) return 0; diff --git a/src/sdl12/mixer_sound.c b/src/sdl12/mixer_sound.c index 542a67169..daf09ab91 100644 --- a/src/sdl12/mixer_sound.c +++ b/src/sdl12/mixer_sound.c @@ -376,10 +376,10 @@ void I_FreeSfx(sfxinfo_t *sfx) sfx->data = NULL; } -INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority) +INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel) { UINT8 volume = (((UINT16)vol + 1) * (UINT16)sfx_volume) / 62; // (256 * 31) / 62 == 127 - INT32 handle = Mix_PlayChannel(-1, S_sfx[id].data, 0); + INT32 handle = Mix_PlayChannel(channel, S_sfx[id].data, 0); Mix_Volume(handle, volume); Mix_SetPanning(handle, min((UINT16)(0xff-sep)<<1, 0xff), min((UINT16)(sep)<<1, 0xff)); (void)pitch; // Mixer can't handle pitch diff --git a/src/sdl12/sdl_sound.c b/src/sdl12/sdl_sound.c index 6ba83104e..01a27153e 100644 --- a/src/sdl12/sdl_sound.c +++ b/src/sdl12/sdl_sound.c @@ -621,10 +621,11 @@ void I_FreeSfx(sfxinfo_t * sfx) // Pitching (that is, increased speed of playback) // is set, but currently not used by mixing. // -INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority) +INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel) { (void)priority; (void)pitch; + (void)channel; if (nosound) return 0; diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index 58644457a..e50a4737e 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -353,12 +353,13 @@ void I_FreeSfx(sfxinfo_t *sfx) sfx->data = NULL; } -INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority) +INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel) { FMOD_SOUND *sound; FMOD_CHANNEL *chan; INT32 i; float frequency; + (void)channel; sound = (FMOD_SOUND *)S_sfx[id].data; I_Assert(sound != NULL); diff --git a/src/win32ce/win_snd.c b/src/win32ce/win_snd.c index f9c652178..a58bbc3ce 100644 --- a/src/win32ce/win_snd.c +++ b/src/win32ce/win_snd.c @@ -538,7 +538,8 @@ INT32 I_StartSound (sfxenum_t id, INT32 vol, INT32 sep, INT32 pitch, - INT32 priority) + INT32 priority + INT32 channel) { HRESULT hr; LPDIRECTSOUNDBUFFER dsbuffer; @@ -549,6 +550,7 @@ INT32 I_StartSound (sfxenum_t id, #ifdef SURROUND LPDIRECTSOUNDBUFFER dssurround; #endif + (void)channel; if (nosound) return -1; From 3886888b3014da650aa2ae5bd843b8ef7dcea28f Mon Sep 17 00:00:00 2001 From: Sryder Date: Sun, 14 Oct 2018 10:14:07 +0100 Subject: [PATCH 303/306] Fix missing commas and missed interface --- src/android/i_sound.c | 3 ++- src/djgppdos/i_sound.c | 2 +- src/win32ce/win_snd.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/android/i_sound.c b/src/android/i_sound.c index ecf96f2f0..77f8e6a55 100644 --- a/src/android/i_sound.c +++ b/src/android/i_sound.c @@ -21,13 +21,14 @@ void I_ShutdownSound(void){} // SFX I/O // -INT32 I_StartSound(sfxenum_t id, INT32 vol, INT32 sep, INT32 pitch, INT32 priority) +INT32 I_StartSound(sfxenum_t id, INT32 vol, INT32 sep, INT32 pitch, INT32 priority, INT32 channel) { (void)id; (void)vol; (void)sep; (void)pitch; (void)priority; + (void)channel; return -1; } diff --git a/src/djgppdos/i_sound.c b/src/djgppdos/i_sound.c index f1e2ad2bf..ec6f4412f 100644 --- a/src/djgppdos/i_sound.c +++ b/src/djgppdos/i_sound.c @@ -165,7 +165,7 @@ INT32 I_StartSound ( sfxenum_t id, INT32 vol, INT32 sep, INT32 pitch, - INT32 priority + INT32 priority, INT32 channel) { int voice; diff --git a/src/win32ce/win_snd.c b/src/win32ce/win_snd.c index a58bbc3ce..14ce4add4 100644 --- a/src/win32ce/win_snd.c +++ b/src/win32ce/win_snd.c @@ -538,7 +538,7 @@ INT32 I_StartSound (sfxenum_t id, INT32 vol, INT32 sep, INT32 pitch, - INT32 priority + INT32 priority, INT32 channel) { HRESULT hr; From 7d612011949d117f568f99c6012084bb6056f67a Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 20 Oct 2018 12:54:40 +0100 Subject: [PATCH 304/306] Fix slipup from when the smashing spikeballs from HHZ were hardcoded --- src/info.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/info.c b/src/info.c index 728fb13c0..3140bd7de 100644 --- a/src/info.c +++ b/src/info.c @@ -3458,8 +3458,8 @@ state_t states[NUMSTATES] = {SPR_FMCE, 0, 20, {NULL}, 0, 0, S_SMASHSPIKE_EASE1}, // S_SMASHSPIKE_FLOAT {SPR_FMCE, 0, 4, {A_ZThrust}, 4, (1<<16)|1, S_SMASHSPIKE_EASE2}, // S_SMASHSPIKE_EASE1 - {SPR_FMCE, 0, 4, {A_ZThrust}, 0, (1<<16)|1, S_SMASHSPIKE_FALL}, // S_SMASHSPIKE_EASE1 - {SPR_FMCE, 0, 2, {A_ZThrust}, -6, (1<<16)|1, S_SMASHSPIKE_FALL}, // S_SMASHSPIKE_FALL + {SPR_FMCE, 0, 4, {A_ZThrust}, 0, (1<<16)|1, S_SMASHSPIKE_FALL}, // S_SMASHSPIKE_EASE2 + {SPR_FMCE, 0, 2, {A_ZThrust}, -6, 1, S_SMASHSPIKE_FALL}, // S_SMASHSPIKE_FALL {SPR_FMCE, 1, 2, {A_MultiShotDist}, (MT_DUST<<16)|10, -48, S_SMASHSPIKE_STOMP2}, // S_SMASHSPIKE_STOMP1 {SPR_FMCE, 2, 14, {NULL}, 0, 0, S_SMASHSPIKE_RISE1}, // S_SMASHSPIKE_STOMP2 {SPR_FMCE, 1, 2, {NULL}, 0, 0, S_SMASHSPIKE_RISE2}, // S_SMASHSPIKE_RISE1 From b7c6661c76db66d4158875c60bdf37525b080d86 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 4 Nov 2018 20:16:33 -0500 Subject: [PATCH 305/306] Add MTF_EXTRA flag to monitors, to run linedef exec by Angle (Tag + 16384) upon pop --- src/p_enemy.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/p_enemy.c b/src/p_enemy.c index 8088c20a8..15608f57f 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3324,6 +3324,11 @@ void A_MonitorPop(mobj_t *actor) newmobj->sprite = SPR_TV1P; } } + + // Run a linedef executor immediately upon popping + // You may want to delay your effects by 18 tics to sync with the reward giving + if (actor->spawnpoint && (actor->spawnpoint->options & MTF_EXTRA) && (actor->spawnpoint->angle & 16384)) + P_LinedefExecute((actor->spawnpoint->angle & 16383), actor->target, NULL); } // Function: A_GoldMonitorPop From f57ec03ad5675e627b8ebd1cdfd98aad754b8d0e Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 27 Nov 2018 21:32:03 -0500 Subject: [PATCH 306/306] fix EOL on src/p_enemy.c --- src/p_enemy.c | 23640 ++++++++++++++++++++++++------------------------ 1 file changed, 11820 insertions(+), 11820 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 15608f57f..4950306a9 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -1,11820 +1,11820 @@ -// SONIC ROBO BLAST 2 -//----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2016 by Sonic Team Junior. -// -// This program is free software distributed under the -// terms of the GNU General Public License, version 2. -// See the 'LICENSE' file for more details. -//----------------------------------------------------------------------------- -/// \file p_enemy.c -/// \brief Enemy thinking, AI -/// Action Pointer Functions that are associated with states/frames - -#include "doomdef.h" -#include "g_game.h" -#include "p_local.h" -#include "r_main.h" -#include "r_state.h" -#include "s_sound.h" -#include "m_random.h" -#include "m_misc.h" -#include "r_things.h" -#include "i_video.h" -#include "lua_hook.h" - -#ifdef HW3SOUND -#include "hardware/hw3sound.h" -#endif - -#ifdef HAVE_BLUA -boolean LUA_CallAction(const char *action, mobj_t *actor); -#endif - -player_t *stplyr; -INT32 var1; -INT32 var2; - -// -// P_NewChaseDir related LUT. -// -static dirtype_t opposite[] = -{ - DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, - DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_NODIR -}; - -static dirtype_t diags[] = -{ - DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST -}; - -//Real Prototypes to A_* -void A_Fall(mobj_t *actor); -void A_Look(mobj_t *actor); -void A_Chase(mobj_t *actor); -void A_FaceStabChase(mobj_t *actor); -void A_FaceStabRev(mobj_t *actor); -void A_FaceStabHurl(mobj_t *actor); -void A_FaceStabMiss(mobj_t *actor); -void A_StatueBurst(mobj_t *actor); -void A_JetJawRoam(mobj_t *actor); -void A_JetJawChomp(mobj_t *actor); -void A_PointyThink(mobj_t *actor); -void A_CheckBuddy(mobj_t *actor); -void A_HoodFire(mobj_t *actor); -void A_HoodThink(mobj_t *actor); -void A_HoodFall(mobj_t *actor); -void A_ArrowBonks(mobj_t *actor); -void A_SnailerThink(mobj_t *actor); -void A_SharpChase(mobj_t *actor); -void A_SharpSpin(mobj_t *actor); -void A_SharpDecel(mobj_t *actor); -void A_CrushstaceanWalk(mobj_t *actor); -void A_CrushstaceanPunch(mobj_t *actor); -void A_CrushclawAim(mobj_t *actor); -void A_CrushclawLaunch(mobj_t *actor); -void A_VultureVtol(mobj_t *actor); -void A_VultureCheck(mobj_t *actor); -void A_SkimChase(mobj_t *actor); -void A_FaceTarget(mobj_t *actor); -void A_FaceTracer(mobj_t *actor); -void A_LobShot(mobj_t *actor); -void A_FireShot(mobj_t *actor); -void A_SuperFireShot(mobj_t *actor); -void A_BossFireShot(mobj_t *actor); -void A_Boss7FireMissiles(mobj_t *actor); -void A_Boss1Laser(mobj_t *actor); -void A_FocusTarget(mobj_t *actor); -void A_Boss4Reverse(mobj_t *actor); -void A_Boss4SpeedUp(mobj_t *actor); -void A_Boss4Raise(mobj_t *actor); -void A_SkullAttack(mobj_t *actor); -void A_BossZoom(mobj_t *actor); -void A_BossScream(mobj_t *actor); -void A_Scream(mobj_t *actor); -void A_Pain(mobj_t *actor); -void A_1upThinker(mobj_t *actor); -void A_MonitorPop(mobj_t *actor); -void A_GoldMonitorPop(mobj_t *actor); -void A_GoldMonitorRestore(mobj_t *actor); -void A_GoldMonitorSparkle(mobj_t *actor); -void A_Explode(mobj_t *actor); -void A_BossDeath(mobj_t *actor); -void A_CustomPower(mobj_t *actor); -void A_GiveWeapon(mobj_t *actor); -void A_RingBox(mobj_t *actor); -void A_Invincibility(mobj_t *actor); -void A_SuperSneakers(mobj_t *actor); -void A_AwardScore(mobj_t *actor); -void A_ExtraLife(mobj_t *actor); -void A_GiveShield(mobj_t *actor); -void A_GravityBox(mobj_t *actor); -void A_ScoreRise(mobj_t *actor); -void A_BunnyHop(mobj_t *actor); -void A_BubbleSpawn(mobj_t *actor); -void A_FanBubbleSpawn(mobj_t *actor); -void A_BubbleRise(mobj_t *actor); -void A_BubbleCheck(mobj_t *actor); -void A_AttractChase(mobj_t *actor); -void A_DropMine(mobj_t *actor); -void A_FishJump(mobj_t *actor); -void A_ThrownRing(mobj_t *actor); -void A_SetSolidSteam(mobj_t *actor); -void A_UnsetSolidSteam(mobj_t *actor); -void A_SignPlayer(mobj_t *actor); -void A_OverlayThink(mobj_t *actor); -void A_JetChase(mobj_t *actor); -void A_JetbThink(mobj_t *actor); -void A_JetgShoot(mobj_t *actor); -void A_JetgThink(mobj_t *actor); -void A_ShootBullet(mobj_t *actor); -void A_MinusDigging(mobj_t *actor); -void A_MinusPopup(mobj_t *actor); -void A_MinusCheck(mobj_t *actor); -void A_ChickenCheck(mobj_t *actor); -void A_MouseThink(mobj_t *actor); -void A_DetonChase(mobj_t *actor); -void A_CapeChase(mobj_t *actor); -void A_RotateSpikeBall(mobj_t *actor); -void A_SlingAppear(mobj_t *actor); -void A_UnidusBall(mobj_t *actor); -void A_RockSpawn(mobj_t *actor); -void A_SetFuse(mobj_t *actor); -void A_CrawlaCommanderThink(mobj_t *actor); -void A_RingExplode(mobj_t *actor); -void A_OldRingExplode(mobj_t *actor); -void A_MixUp(mobj_t *actor); -void A_RecyclePowers(mobj_t *actor); -void A_Boss2TakeDamage(mobj_t *actor); -void A_Boss7Chase(mobj_t *actor); -void A_GoopSplat(mobj_t *actor); -void A_Boss2PogoSFX(mobj_t *actor); -void A_Boss2PogoTarget(mobj_t *actor); -void A_EggmanBox(mobj_t *actor); -void A_TurretFire(mobj_t *actor); -void A_SuperTurretFire(mobj_t *actor); -void A_TurretStop(mobj_t *actor); -void A_SparkFollow(mobj_t *actor); -void A_BuzzFly(mobj_t *actor); -void A_GuardChase(mobj_t *actor); -void A_EggShield(mobj_t *actor); -void A_SetReactionTime(mobj_t *actor); -void A_Boss1Spikeballs(mobj_t *actor); -void A_Boss3TakeDamage(mobj_t *actor); -void A_Boss3Path(mobj_t *actor); -void A_LinedefExecute(mobj_t *actor); -void A_PlaySeeSound(mobj_t *actor); -void A_PlayAttackSound(mobj_t *actor); -void A_PlayActiveSound(mobj_t *actor); -void A_SmokeTrailer(mobj_t *actor); -void A_SpawnObjectAbsolute(mobj_t *actor); -void A_SpawnObjectRelative(mobj_t *actor); -void A_ChangeAngleRelative(mobj_t *actor); -void A_ChangeAngleAbsolute(mobj_t *actor); -void A_PlaySound(mobj_t *actor); -void A_FindTarget(mobj_t *actor); -void A_FindTracer(mobj_t *actor); -void A_SetTics(mobj_t *actor); -void A_SetRandomTics(mobj_t *actor); -void A_ChangeColorRelative(mobj_t *actor); -void A_ChangeColorAbsolute(mobj_t *actor); -void A_MoveRelative(mobj_t *actor); -void A_MoveAbsolute(mobj_t *actor); -void A_Thrust(mobj_t *actor); -void A_ZThrust(mobj_t *actor); -void A_SetTargetsTarget(mobj_t *actor); -void A_SetObjectFlags(mobj_t *actor); -void A_SetObjectFlags2(mobj_t *actor); -void A_RandomState(mobj_t *actor); -void A_RandomStateRange(mobj_t *actor); -void A_DualAction(mobj_t *actor); -void A_RemoteAction(mobj_t *actor); -void A_ToggleFlameJet(mobj_t *actor); -void A_OrbitNights(mobj_t *actor); -void A_GhostMe(mobj_t *actor); -void A_SetObjectState(mobj_t *actor); -void A_SetObjectTypeState(mobj_t *actor); -void A_KnockBack(mobj_t *actor); -void A_PushAway(mobj_t *actor); -void A_RingDrain(mobj_t *actor); -void A_SplitShot(mobj_t *actor); -void A_MissileSplit(mobj_t *actor); -void A_MultiShot(mobj_t *actor); -void A_InstaLoop(mobj_t *actor); -void A_Custom3DRotate(mobj_t *actor); -void A_SearchForPlayers(mobj_t *actor); -void A_CheckRandom(mobj_t *actor); -void A_CheckTargetRings(mobj_t *actor); -void A_CheckRings(mobj_t *actor); -void A_CheckTotalRings(mobj_t *actor); -void A_CheckHealth(mobj_t *actor); -void A_CheckRange(mobj_t *actor); -void A_CheckHeight(mobj_t *actor); -void A_CheckTrueRange(mobj_t *actor); -void A_CheckThingCount(mobj_t *actor); -void A_CheckAmbush(mobj_t *actor); -void A_CheckCustomValue(mobj_t *actor); -void A_CheckCusValMemo(mobj_t *actor); -void A_SetCustomValue(mobj_t *actor); -void A_UseCusValMemo(mobj_t *actor); -void A_RelayCustomValue(mobj_t *actor); -void A_CusValAction(mobj_t *actor); -void A_ForceStop(mobj_t *actor); -void A_ForceWin(mobj_t *actor); -void A_SpikeRetract(mobj_t *actor); -void A_InfoState(mobj_t *actor); -void A_Repeat(mobj_t *actor); -void A_SetScale(mobj_t *actor); -void A_RemoteDamage(mobj_t *actor); -void A_HomingChase(mobj_t *actor); -void A_TrapShot(mobj_t *actor); -void A_Boss1Chase(mobj_t *actor); -void A_Boss2Chase(mobj_t *actor); -void A_Boss2Pogo(mobj_t *actor); -void A_BossJetFume(mobj_t *actor); -void A_VileTarget(mobj_t *actor); -void A_VileAttack(mobj_t *actor); -void A_VileFire(mobj_t *actor); -void A_BrakChase(mobj_t *actor); -void A_BrakFireShot(mobj_t *actor); -void A_BrakLobShot(mobj_t *actor); -void A_NapalmScatter(mobj_t *actor); -void A_SpawnFreshCopy(mobj_t *actor); -void A_FlickySpawn(mobj_t *actor); -void A_FlickyCenter(mobj_t *actor); -void A_FlickyAim(mobj_t *actor); -void A_FlickyFly(mobj_t *actor); -void A_FlickySoar(mobj_t *actor); -void A_FlickyCoast(mobj_t *actor); -void A_FlickyHop(mobj_t *actor); -void A_FlickyFlounder(mobj_t *actor); -void A_FlickyCheck(mobj_t *actor); -void A_FlickyHeightCheck(mobj_t *actor); -void A_FlickyFlutter(mobj_t *actor); -void A_FlameParticle(mobj_t *actor); -void A_FadeOverlay(mobj_t *actor); -void A_Boss5Jump(mobj_t *actor); -void A_LightBeamReset(mobj_t *actor); -void A_MineExplode(mobj_t *actor); -void A_MineRange(mobj_t *actor); -void A_ConnectToGround(mobj_t *actor); -void A_SpawnParticleRelative(mobj_t *actor); -void A_MultiShotDist(mobj_t *actor); -void A_WhoCaresIfYourSonIsABee(mobj_t *actor); -void A_ParentTriesToSleep(mobj_t *actor); -void A_CryingToMomma(mobj_t *actor); -void A_CheckFlags2(mobj_t *actor); -//for p_enemy.c - -// -// ENEMY THINKING -// Enemies are always spawned with targetplayer = -1, threshold = 0 -// Most monsters are spawned unaware of all players, but some can be made preaware. -// - -// -// P_CheckMeleeRange -// -boolean P_CheckMeleeRange(mobj_t *actor) -{ - mobj_t *pl; - fixed_t dist; - - if (!actor->target) - return false; - - pl = actor->target; - dist = P_AproxDistance(pl->x-actor->x, pl->y-actor->y); - - if (dist >= FixedMul(MELEERANGE - 20*FRACUNIT, actor->scale) + pl->radius) - return false; - - // check height now, so that damn crawlas cant attack - // you if you stand on a higher ledge. - if ((pl->z > actor->z + actor->height) || (actor->z > pl->z + pl->height)) - return false; - - if (!P_CheckSight(actor, actor->target)) - return false; - - return true; -} - -// P_CheckMeleeRange for Jettysyn Bomber. -boolean P_JetbCheckMeleeRange(mobj_t *actor) -{ - mobj_t *pl; - fixed_t dist; - - if (!actor->target) - return false; - - pl = actor->target; - dist = P_AproxDistance(pl->x-actor->x, pl->y-actor->y); - - if (dist >= (actor->radius + pl->radius)*2) - return false; - - if (actor->eflags & MFE_VERTICALFLIP) - { - if (pl->z < actor->z + actor->height + FixedMul(40<scale)) - return false; - } - else - { - if (pl->z + pl->height > actor->z - FixedMul(40<scale)) - return false; - } - - return true; -} - -// P_CheckMeleeRange for CastleBot FaceStabber. -boolean P_FaceStabCheckMeleeRange(mobj_t *actor) -{ - mobj_t *pl; - fixed_t dist; - - if (!actor->target) - return false; - - pl = actor->target; - dist = P_AproxDistance(pl->x-actor->x, pl->y-actor->y); - - if (dist >= (actor->radius + pl->radius)*4) - return false; - - if ((pl->z > actor->z + actor->height) || (actor->z > pl->z + pl->height)) - return false; - - if (!P_CheckSight(actor, actor->target)) - return false; - - return true; -} - -// P_CheckMeleeRange for Skim. -boolean P_SkimCheckMeleeRange(mobj_t *actor) -{ - mobj_t *pl; - fixed_t dist; - - if (!actor->target) - return false; - - pl = actor->target; - dist = P_AproxDistance(pl->x-actor->x, pl->y-actor->y); - - if (dist >= FixedMul(MELEERANGE - 20*FRACUNIT, actor->scale) + pl->radius) - return false; - - if (actor->eflags & MFE_VERTICALFLIP) - { - if (pl->z < actor->z + actor->height + FixedMul(24<scale)) - return false; - } - else - { - if (pl->z + pl->height > actor->z - FixedMul(24<scale)) - return false; - } - - return true; -} - -// -// P_CheckMissileRange -// -boolean P_CheckMissileRange(mobj_t *actor) -{ - fixed_t dist; - - if (!actor->target) - return false; - - if (actor->reactiontime) - return false; // do not attack yet - - if (!P_CheckSight(actor, actor->target)) - return false; - - // OPTIMIZE: get this from a global checksight - dist = P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) - FixedMul(64*FRACUNIT, actor->scale); - - if (!actor->info->meleestate) - dist -= FixedMul(128*FRACUNIT, actor->scale); // no melee attack, so fire more - - dist >>= FRACBITS; - - if (actor->type == MT_EGGMOBILE) - dist >>= 1; - - if (dist > 200) - dist = 200; - - if (actor->type == MT_EGGMOBILE && dist > 160) - dist = 160; - - if (P_RandomByte() < dist) - return false; - - return true; -} - -/** Checks for water in a sector. - * Used by Skim movements. - * - * \param x X coordinate on the map. - * \param y Y coordinate on the map. - * \return True if there's water at this location, false if not. - * \sa ::MT_SKIM - */ -static boolean P_WaterInSector(mobj_t *mobj, fixed_t x, fixed_t y) -{ - sector_t *sector; - - sector = R_PointInSubsector(x, y)->sector; - - if (sector->ffloors) - { - ffloor_t *rover; - - for (rover = sector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE)) - continue; - - if (*rover->topheight >= mobj->floorz && *rover->topheight <= mobj->z) - return true; // we found water!! - } - } - - return false; -} - -static const fixed_t xspeed[NUMDIRS] = {FRACUNIT, 46341>>(16-FRACBITS), 0, -(46341>>(16-FRACBITS)), -FRACUNIT, -(46341>>(16-FRACBITS)), 0, 46341>>(16-FRACBITS)}; -static const fixed_t yspeed[NUMDIRS] = {0, 46341>>(16-FRACBITS), FRACUNIT, 46341>>(16-FRACBITS), 0, -(46341>>(16-FRACBITS)), -FRACUNIT, -(46341>>(16-FRACBITS))}; - -/** Moves an actor in its current direction. - * - * \param actor Actor object to move. - * \return False if the move is blocked, otherwise true. - */ -boolean P_Move(mobj_t *actor, fixed_t speed) -{ - fixed_t tryx, tryy; - dirtype_t movedir = actor->movedir; - - if (movedir == DI_NODIR || !actor->health) - return false; - - I_Assert(movedir < NUMDIRS); - - tryx = actor->x + FixedMul(speed*xspeed[movedir], actor->scale); - if (twodlevel || actor->flags2 & MF2_TWOD) - tryy = actor->y; - else - tryy = actor->y + FixedMul(speed*yspeed[movedir], actor->scale); - - if (actor->type == MT_SKIM && !P_WaterInSector(actor, tryx, tryy)) // bail out if sector lacks water - return false; - - if (!P_TryMove(actor, tryx, tryy, false)) - { - if (actor->flags & MF_FLOAT && floatok) - { - // must adjust height - if (actor->z < tmfloorz) - actor->z += FixedMul(FLOATSPEED, actor->scale); - else - actor->z -= FixedMul(FLOATSPEED, actor->scale); - - if (actor->type == MT_JETJAW && actor->z + actor->height > actor->watertop) - actor->z = actor->watertop - actor->height; - - actor->flags2 |= MF2_INFLOAT; - return true; - } - - return false; - } - else - actor->flags2 &= ~MF2_INFLOAT; - - return true; -} - -/** Attempts to move an actor on in its current direction. - * If the move succeeds, the actor's move count is reset - * randomly to a value from 0 to 15. - * - * \param actor Actor to move. - * \return True if the move succeeds, false if the move is blocked. - */ -static boolean P_TryWalk(mobj_t *actor) -{ - if (!P_Move(actor, actor->info->speed)) - return false; - actor->movecount = P_RandomByte() & 15; - return true; -} - -void P_NewChaseDir(mobj_t *actor) -{ - fixed_t deltax, deltay; - dirtype_t d[3]; - dirtype_t tdir = DI_NODIR, olddir, turnaround; - - I_Assert(actor->target != NULL); - I_Assert(!P_MobjWasRemoved(actor->target)); - - olddir = actor->movedir; - - if (olddir >= NUMDIRS) - olddir = DI_NODIR; - - if (olddir != DI_NODIR) - turnaround = opposite[olddir]; - else - turnaround = olddir; - - deltax = actor->target->x - actor->x; - deltay = actor->target->y - actor->y; - - if (deltax > FixedMul(10*FRACUNIT, actor->scale)) - d[1] = DI_EAST; - else if (deltax < -FixedMul(10*FRACUNIT, actor->scale)) - d[1] = DI_WEST; - else - d[1] = DI_NODIR; - - if (twodlevel || actor->flags2 & MF2_TWOD) - d[2] = DI_NODIR; - if (deltay < -FixedMul(10*FRACUNIT, actor->scale)) - d[2] = DI_SOUTH; - else if (deltay > FixedMul(10*FRACUNIT, actor->scale)) - d[2] = DI_NORTH; - else - d[2] = DI_NODIR; - - // try direct route - if (d[1] != DI_NODIR && d[2] != DI_NODIR) - { - dirtype_t newdir = diags[((deltay < 0)<<1) + (deltax > 0)]; - - actor->movedir = newdir; - if ((newdir != turnaround) && P_TryWalk(actor)) - return; - } - - // try other directions - if (P_RandomChance(25*FRACUNIT/32) || abs(deltay) > abs(deltax)) - { - tdir = d[1]; - d[1] = d[2]; - d[2] = tdir; - } - - if (d[1] == turnaround) - d[1] = DI_NODIR; - if (d[2] == turnaround) - d[2] = DI_NODIR; - - if (d[1] != DI_NODIR) - { - actor->movedir = d[1]; - - if (P_TryWalk(actor)) - return; // either moved forward or attacked - } - - if (d[2] != DI_NODIR) - { - actor->movedir = d[2]; - - if (P_TryWalk(actor)) - return; - } - - // there is no direct path to the player, so pick another direction. - if (olddir != DI_NODIR) - { - actor->movedir =olddir; - - if (P_TryWalk(actor)) - return; - } - - // randomly determine direction of search - if (P_RandomChance(FRACUNIT/2)) - { - for (tdir = DI_EAST; tdir <= DI_SOUTHEAST; tdir++) - { - if (tdir != turnaround) - { - actor->movedir = tdir; - - if (P_TryWalk(actor)) - return; - } - } - } - else - { - for (tdir = DI_SOUTHEAST; tdir >= DI_EAST; tdir--) - { - if (tdir != turnaround) - { - actor->movedir = tdir; - - if (P_TryWalk(actor)) - return; - } - } - } - - if (turnaround != DI_NODIR) - { - actor->movedir = turnaround; - - if (P_TryWalk(actor)) - return; - } - - actor->movedir = (angle_t)DI_NODIR; // cannot move -} - -/** Looks for players to chase after, aim at, or whatever. - * - * \param actor The object looking for flesh. - * \param allaround Look all around? If false, only players in a 180-degree - * range in front will be spotted. - * \param dist If > 0, checks distance - * \return True if a player is found, otherwise false. - * \sa P_SupermanLook4Players - */ -boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed_t dist) -{ - INT32 c = 0, stop; - player_t *player; - angle_t an; - - // BP: first time init, this allow minimum lastlook changes - if (actor->lastlook < 0) - actor->lastlook = P_RandomByte(); - - actor->lastlook %= MAXPLAYERS; - - stop = (actor->lastlook - 1) & PLAYERSMASK; - - for (; ; actor->lastlook = (actor->lastlook + 1) & PLAYERSMASK) - { - // done looking - if (actor->lastlook == stop) - return false; - - if (!playeringame[actor->lastlook]) - continue; - - if (c++ == 2) - return false; - - player = &players[actor->lastlook]; - - if ((netgame || multiplayer) && player->spectator) - continue; - - if (player->pflags & PF_INVIS) - continue; // ignore notarget - - if (!player->mo || P_MobjWasRemoved(player->mo)) - continue; - - if (player->mo->health <= 0) - continue; // dead - - if (dist > 0 - && P_AproxDistance(P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y), player->mo->z - actor->z) > dist) - continue; // Too far away - - if (!allaround) - { - an = R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y) - actor->angle; - if (an > ANGLE_90 && an < ANGLE_270) - { - dist = P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y); - // if real close, react anyway - if (dist > FixedMul(MELEERANGE, actor->scale)) - continue; // behind back - } - } - - if (!P_CheckSight(actor, player->mo)) - continue; // out of sight - - if (tracer) - P_SetTarget(&actor->tracer, player->mo); - else - P_SetTarget(&actor->target, player->mo); - return true; - } - - //return false; -} - -/** Looks for a player with a ring shield. - * Used by rings. - * - * \param actor Ring looking for a shield to be attracted to. - * \return True if a player with ring shield is found, otherwise false. - * \sa A_AttractChase - */ -static boolean P_LookForShield(mobj_t *actor) -{ - INT32 c = 0, stop; - player_t *player; - - // BP: first time init, this allow minimum lastlook changes - if (actor->lastlook < 0) - actor->lastlook = P_RandomByte(); - - actor->lastlook %= MAXPLAYERS; - - stop = (actor->lastlook - 1) & PLAYERSMASK; - - for (; ; actor->lastlook = ((actor->lastlook + 1) & PLAYERSMASK)) - { - // done looking - if (actor->lastlook == stop) - return false; - - if (!playeringame[actor->lastlook]) - continue; - - if (c++ == 2) - return false; - - player = &players[actor->lastlook]; - - if (!player->mo || player->mo->health <= 0) - continue; // dead - - //When in CTF, don't pull rings that you cannot pick up. - if ((actor->type == MT_REDTEAMRING && player->ctfteam != 1) || - (actor->type == MT_BLUETEAMRING && player->ctfteam != 2)) - continue; - - if ((player->powers[pw_shield] & SH_PROTECTELECTRIC) - && (P_AproxDistance(P_AproxDistance(actor->x-player->mo->x, actor->y-player->mo->y), actor->z-player->mo->z) < FixedMul(RING_DIST, player->mo->scale))) - { - P_SetTarget(&actor->tracer, player->mo); - - if (actor->hnext) - P_SetTarget(&actor->hnext->hprev, actor->hprev); - if (actor->hprev) - P_SetTarget(&actor->hprev->hnext, actor->hnext); - - return true; - } - } - - //return false; -} - -#ifdef WEIGHTEDRECYCLER -// Compares players to see who currently has the "best" items, etc. -static int P_RecycleCompare(const void *p1, const void *p2) -{ - player_t *player1 = &players[*(const UINT8 *)p1]; - player_t *player2 = &players[*(const UINT8 *)p2]; - - // Non-shooting gametypes - if (!G_PlatformGametype()) - { - // Invincibility. - if (player1->powers[pw_invulnerability] > player2->powers[pw_invulnerability]) return -1; - else if (player2->powers[pw_invulnerability] > player1->powers[pw_invulnerability]) return 1; - - // One has a shield, the other doesn't. - if (player1->powers[pw_shield] && !player2->powers[pw_shield]) return -1; - else if (player2->powers[pw_shield] && !player1->powers[pw_shield]) return 1; - - // Sneakers. - if (player1->powers[pw_sneakers] > player2->powers[pw_sneakers]) return -1; - else if (player2->powers[pw_sneakers] > player1->powers[pw_sneakers]) return 1; - } - else // Match, Team Match, CTF, Tag, Etc. - { - UINT8 player1_em = M_CountBits((UINT32)player1->powers[pw_emeralds], 7); - UINT8 player2_em = M_CountBits((UINT32)player2->powers[pw_emeralds], 7); - - UINT8 player1_rw = M_CountBits((UINT32)player1->ringweapons, NUM_WEAPONS-1); - UINT8 player2_rw = M_CountBits((UINT32)player2->ringweapons, NUM_WEAPONS-1); - - UINT16 player1_am = player1->powers[pw_infinityring] // max 800 - + player1->powers[pw_automaticring] // max 300 - + (player1->powers[pw_bouncering] * 3) // max 100 - + (player1->powers[pw_explosionring] * 6) // max 50 - + (player1->powers[pw_scatterring] * 3) // max 100 - + (player1->powers[pw_grenadering] * 6) // max 50 - + (player1->powers[pw_railring] * 6); // max 50 - UINT16 player2_am = player2->powers[pw_infinityring] // max 800 - + player2->powers[pw_automaticring] // max 300 - + (player2->powers[pw_bouncering] * 3) // max 100 - + (player2->powers[pw_explosionring] * 6) // max 50 - + (player2->powers[pw_scatterring] * 3) // max 100 - + (player2->powers[pw_grenadering] * 6) // max 50 - + (player2->powers[pw_railring] * 6); // max 50 - - // Super trumps everything. - if (player1->powers[pw_super] && !player2->powers[pw_super]) return -1; - else if (player2->powers[pw_super] && !player1->powers[pw_super]) return 1; - - // Emerald count if neither player is Super. - if (player1_em > player2_em) return -1; - else if (player1_em < player2_em) return 1; - - // One has a shield, the other doesn't. - // (the likelihood of a shielded player being worse off than one without one is low.) - if (player1->powers[pw_shield] && !player2->powers[pw_shield]) return -1; - else if (player2->powers[pw_shield] && !player1->powers[pw_shield]) return 1; - - // Ring weapons count - if (player1_rw > player2_rw) return -1; - else if (player1_rw < player2_rw) return 1; - - // Ring ammo if they have the same number of weapons - if (player1_am > player2_am) return -1; - else if (player1_am < player2_am) return 1; - } - - // Identical for our purposes - return 0; -} -#endif - -// Handles random monitor weights via console. -static mobjtype_t P_DoRandomBoxChances(void) -{ - mobjtype_t spawnchance[256]; - INT32 numchoices = 0, i = 0; - - if (!(netgame || multiplayer)) - { - switch (P_RandomKey(10)) - { - case 0: - return MT_RING_ICON; - case 1: - return MT_SNEAKERS_ICON; - case 2: - return MT_INVULN_ICON; - case 3: - return MT_WHIRLWIND_ICON; - case 4: - return MT_ELEMENTAL_ICON; - case 5: - return MT_ATTRACT_ICON; - case 6: - return MT_FORCE_ICON; - case 7: - return MT_ARMAGEDDON_ICON; - case 8: - return MT_1UP_ICON; - case 9: - return MT_EGGMAN_ICON; - } - return MT_NULL; - } - -#define QUESTIONBOXCHANCES(type, cvar) \ -for (i = cvar.value; i; --i) spawnchance[numchoices++] = type - QUESTIONBOXCHANCES(MT_RING_ICON, cv_superring); - QUESTIONBOXCHANCES(MT_SNEAKERS_ICON, cv_supersneakers); - QUESTIONBOXCHANCES(MT_INVULN_ICON, cv_invincibility); - QUESTIONBOXCHANCES(MT_WHIRLWIND_ICON, cv_jumpshield); - QUESTIONBOXCHANCES(MT_ELEMENTAL_ICON, cv_watershield); - QUESTIONBOXCHANCES(MT_ATTRACT_ICON, cv_ringshield); - QUESTIONBOXCHANCES(MT_FORCE_ICON, cv_forceshield); - QUESTIONBOXCHANCES(MT_ARMAGEDDON_ICON, cv_bombshield); - QUESTIONBOXCHANCES(MT_1UP_ICON, cv_1up); - QUESTIONBOXCHANCES(MT_EGGMAN_ICON, cv_eggmanbox); - QUESTIONBOXCHANCES(MT_MIXUP_ICON, cv_teleporters); - QUESTIONBOXCHANCES(MT_RECYCLER_ICON, cv_recycler); -#undef QUESTIONBOXCHANCES - - if (numchoices == 0) return MT_NULL; - return spawnchance[P_RandomKey(numchoices)]; -} - -// -// ACTION ROUTINES -// - -// Function: A_Look -// -// Description: Look for a player and set your target to them. -// -// var1: -// lower 16 bits = look all around -// upper 16 bits = distance limit -// var2 = If 1, only change to seestate. If 2, only play seesound. If 0, do both. -// -void A_Look(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Look", actor)) - return; -#endif - - if (!P_LookForPlayers(actor, locvar1 & 65535, false , FixedMul((locvar1 >> 16)*FRACUNIT, actor->scale))) - return; - - // go into chase state - if (!locvar2) - { - P_SetMobjState(actor, actor->info->seestate); - A_PlaySeeSound(actor); - } - else if (locvar2 == 1) // Only go into seestate - P_SetMobjState(actor, actor->info->seestate); - else if (locvar2 == 2) // Only play seesound - A_PlaySeeSound(actor); -} - -// Function: A_Chase -// -// Description: Chase after your target. -// -// var1: -// 1 = don't check meleestate -// 2 = don't check missilestate -// 3 = don't check meleestate and missilestate -// var2 = unused -// -void A_Chase(mobj_t *actor) -{ - INT32 delta; - INT32 locvar1 = var1; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Chase", actor)) - return; -#endif - - I_Assert(actor != NULL); - I_Assert(!P_MobjWasRemoved(actor)); - - if (actor->reactiontime) - actor->reactiontime--; - - // modify target threshold - if (actor->threshold) - { - if (!actor->target || actor->target->health <= 0) - actor->threshold = 0; - else - actor->threshold--; - } - - // turn towards movement direction if not there yet - if (actor->movedir < NUMDIRS) - { - actor->angle &= (7<<29); - delta = actor->angle - (actor->movedir << 29); - - if (delta > 0) - actor->angle -= ANGLE_45; - else if (delta < 0) - actor->angle += ANGLE_45; - } - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { - // look for a new target - if (P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - P_SetMobjStateNF(actor, actor->info->spawnstate); - return; - } - - // do not attack twice in a row - if (actor->flags2 & MF2_JUSTATTACKED) - { - actor->flags2 &= ~MF2_JUSTATTACKED; - P_NewChaseDir(actor); - return; - } - - // check for melee attack - if (!(locvar1 & 1) && actor->info->meleestate && P_CheckMeleeRange(actor)) - { - if (actor->info->attacksound) - S_StartAttackSound(actor, actor->info->attacksound); - - P_SetMobjState(actor, actor->info->meleestate); - return; - } - - // check for missile attack - if (!(locvar1 & 2) && actor->info->missilestate) - { - if (actor->movecount || !P_CheckMissileRange(actor)) - goto nomissile; - - P_SetMobjState(actor, actor->info->missilestate); - actor->flags2 |= MF2_JUSTATTACKED; - return; - } - -nomissile: - // possibly choose another target - if (multiplayer && !actor->threshold && (actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) - && P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - // chase towards player - if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) - P_NewChaseDir(actor); -} - -// Function: A_FaceStabChase -// -// Description: Unused variant of A_Chase for Castlebot Facestabber. -// -// var1 = unused -// var2 = unused -// -void A_FaceStabChase(mobj_t *actor) -{ - INT32 delta; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FaceStabChase", actor)) - return; -#endif - - if (actor->reactiontime) - actor->reactiontime--; - - // modify target threshold - if (actor->threshold) - { - if (!actor->target || actor->target->health <= 0) - actor->threshold = 0; - else - actor->threshold--; - } - - // turn towards movement direction if not there yet - if (actor->movedir < NUMDIRS) - { - actor->angle &= (7<<29); - delta = actor->angle - (actor->movedir << 29); - - if (delta > 0) - actor->angle -= ANGLE_45; - else if (delta < 0) - actor->angle += ANGLE_45; - } - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { - // look for a new target - if (P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - P_SetMobjStateNF(actor, actor->info->spawnstate); - return; - } - - // do not attack twice in a row - if (actor->flags2 & MF2_JUSTATTACKED) - { - actor->flags2 &= ~MF2_JUSTATTACKED; - P_NewChaseDir(actor); - return; - } - - // check for melee attack - if (actor->info->meleestate && P_FaceStabCheckMeleeRange(actor)) - { - if (actor->info->attacksound) - S_StartAttackSound(actor, actor->info->attacksound); - - P_SetMobjState(actor, actor->info->meleestate); - return; - } - - // check for missile attack - if (actor->info->missilestate) - { - if (actor->movecount || !P_CheckMissileRange(actor)) - goto nomissile; - - P_SetMobjState(actor, actor->info->missilestate); - actor->flags2 |= MF2_JUSTATTACKED; - return; - } - -nomissile: - // possibly choose another target - if (multiplayer && !actor->threshold && (actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) - && P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - // chase towards player - if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) - P_NewChaseDir(actor); -} - -static void P_SharpDust(mobj_t *actor, mobjtype_t type, angle_t ang) -{ - mobj_t *dust; - - if (!type || !P_IsObjectOnGround(actor)) - return; - - dust = P_SpawnMobjFromMobj(actor, - -P_ReturnThrustX(actor, ang, 16<angle, actor->radius), - -P_ReturnThrustY(actor, actor->angle, actor->radius), - actor->height/3, - MT_PARTICLE); - flume->destscale = actor->scale*3; - P_SetScale(flume, flume->destscale); - P_SetTarget(&flume->target, actor); - flume->sprite = SPR_JETF; - flume->frame = FF_FULLBRIGHT; - flume->tics = 2; -} - -// Function: A_FaceStabRev -// -// Description: Facestabber rev action -// -// var1 = effective duration -// var2 = effective nextstate -// -void A_FaceStabRev(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FaceStabRev", actor)) - return; -#endif - - if (!actor->target) - { - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - - actor->extravalue1 = 0; - - if (!actor->reactiontime) - { - actor->reactiontime = locvar1; - S_StartSound(actor, actor->info->activesound); - } - else - { - if ((--actor->reactiontime) == 0) - { - S_StartSound(actor, actor->info->attacksound); - P_SetMobjState(actor, locvar2); - } - else - { - P_TryMove(actor, actor->x - P_ReturnThrustX(actor, actor->angle, 2<y - P_ReturnThrustY(actor, actor->angle, 2<target) - { - angle_t visang = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); - // Calculate new direction. - angle_t dirang = actor->angle; - angle_t diffang = visang - dirang; - - if (locvar1) // Allow homing? - { - if (diffang > ANGLE_180) - { - angle_t workang = locvar1*(InvAngle(diffang)>>5); - diffang += InvAngle(workang); - } - else - diffang += (locvar1*(diffang>>5)); - } - diffang += ANGLE_45; - - // Check the sight cone. - if (diffang < ANGLE_90) - { - actor->angle = dirang; - if (++actor->extravalue2 < 4) - actor->extravalue2 = 4; - else if (actor->extravalue2 > 26) - actor->extravalue2 = 26; - - if (P_TryMove(actor, - actor->x + P_ReturnThrustX(actor, dirang, actor->extravalue2<y + P_ReturnThrustY(actor, dirang, actor->extravalue2<extravalue1); - fixed_t basesize = FRACUNIT/MAXVAL; - mobj_t *hwork = actor; - INT32 dist = 113; - fixed_t xo = P_ReturnThrustX(actor, actor->angle, dist*basesize); - fixed_t yo = P_ReturnThrustY(actor, actor->angle, dist*basesize); - - while (step > 0) - { - if (!hwork->hnext) - P_SetTarget(&hwork->hnext, P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_FACESTABBERSPEAR)); - hwork = hwork->hnext; - hwork->angle = actor->angle + ANGLE_90; - hwork->destscale = FixedSqrt(step*basesize); - P_SetScale(hwork, hwork->destscale); - hwork->fuse = 2; - P_TeleportMove(hwork, actor->x + xo*(15-step), actor->y + yo*(15-step), actor->z + (actor->height - hwork->height)/2 + (P_MobjFlip(actor)*(8<extravalue1 >= MAXVAL) - actor->extravalue1 -= NUMGRADS; - - if ((step % 5) == 0) - P_SharpDust(actor, MT_SPINDUST, actor->angle); - - P_FaceStabFlume(actor); - return; -#undef MAXVAL -#undef NUMGRADS -#undef NUMSTEPS - } - } - } - - P_SetMobjState(actor, locvar2); - actor->reactiontime = actor->info->reactiontime; -} - -// Function: A_FaceStabMiss -// -// Description: Facestabber miss action -// -// var1 = unused -// var2 = effective nextstate -// -void A_FaceStabMiss(mobj_t *actor) -{ - //INT32 locvar1 = var1; - INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FaceStabMiss", actor)) - return; -#endif - - if (++actor->extravalue1 >= 3) - { - actor->extravalue2 -= 2; - actor->extravalue1 = 0; - S_StartSound(actor, sfx_s3k47); - P_SharpDust(actor, MT_SPINDUST, actor->angle); - } - - if (actor->extravalue2 <= 0 || !P_TryMove(actor, - actor->x + P_ReturnThrustX(actor, actor->angle, actor->extravalue2<y + P_ReturnThrustY(actor, actor->angle, actor->extravalue2<extravalue2 = 0; - P_SetMobjState(actor, locvar2); - } -} - -// Function: A_StatueBurst -// -// Description: For suspicious statues only... -// -// var1 = object to create -// var2 = effective nextstate for created object -// -void A_StatueBurst(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - mobjtype_t chunktype = (mobjtype_t)actor->info->raisestate; - mobj_t *new; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_StatueBurst", actor)) - return; -#endif - - if (!locvar1 || !(new = P_SpawnMobjFromMobj(actor, 0, 0, 0, locvar1))) - return; - - new->angle = actor->angle; - new->target = actor->target; - if (locvar2) - P_SetMobjState(new, (statenum_t)locvar2); - S_StartSound(new, new->info->attacksound); - S_StopSound(actor); - S_StartSound(actor, sfx_s3k96); - - { - fixed_t a, b; - fixed_t c = (actor->height>>2) - FixedMul(actor->scale, mobjinfo[chunktype].height>>1); - fixed_t v = 4<radius>>1); - mobj_t *spawned; - UINT8 i; - for (i = 0; i < 8; i++) - { - a = ((i & 1) ? r : (-r)); - b = ((i & 2) ? r : (-r)); - if (i == 4) - { - c += (actor->height>>1); - v = 8<fuse = 3*TICRATE; - } - } -} - -// Function: A_JetJawRoam -// -// Description: Roaming routine for JetJaw -// -// var1 = unused -// var2 = unused -// -void A_JetJawRoam(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_JetJawRoam", actor)) - return; -#endif - if (actor->reactiontime) - { - actor->reactiontime--; - P_InstaThrust(actor, actor->angle, FixedMul(actor->info->speed*FRACUNIT/4, actor->scale)); - } - else - { - actor->reactiontime = actor->info->reactiontime; - actor->angle += ANGLE_180; - } - - if (P_LookForPlayers(actor, false, false, actor->radius * 16)) - P_SetMobjState(actor, actor->info->seestate); -} - -// Function: A_JetJawChomp -// -// Description: Chase and chomp at the target, as long as it is in view -// -// var1 = unused -// var2 = unused -// -void A_JetJawChomp(mobj_t *actor) -{ - INT32 delta; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_JetJawChomp", actor)) - return; -#endif - - // turn towards movement direction if not there yet - if (actor->movedir < NUMDIRS) - { - actor->angle &= (7<<29); - delta = actor->angle - (actor->movedir << 29); - - if (delta > 0) - actor->angle -= ANGLE_45; - else if (delta < 0) - actor->angle += ANGLE_45; - } - - // Stop chomping if target's dead or you can't see it - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE) - || actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) - { - P_SetMobjStateNF(actor, actor->info->spawnstate); - return; - } - - // chase towards player - if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) - P_NewChaseDir(actor); -} - -// Function: A_PointyThink -// -// Description: Thinker function for Pointy -// -// var1 = unused -// var2 = unused -// -void A_PointyThink(mobj_t *actor) -{ - INT32 i; - player_t *player = NULL; - mobj_t *ball; - TVector v; - TVector *res; - angle_t fa; - fixed_t radius = FixedMul(actor->info->radius*actor->info->reactiontime, actor->scale); - boolean firsttime = true; - INT32 sign; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_PointyThink", actor)) - return; -#endif - actor->momx = actor->momy = actor->momz = 0; - - // Find nearest player - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - if (!players[i].mo->health) - continue; - - if (!P_CheckSight(actor, players[i].mo)) - continue; - - if (firsttime) - { - firsttime = false; - player = &players[i]; - } - else - { - if (P_AproxDistance(players[i].mo->x - actor->x, players[i].mo->y - actor->y) < - P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y)) - player = &players[i]; - } - } - - if (!player) - return; - - // Okay, we found the closest player. Let's move based on his movement. - P_SetTarget(&actor->target, player->mo); - A_FaceTarget(actor); - - if (P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y) < P_AproxDistance(player->mo->x + player->mo->momx - actor->x, player->mo->y + player->mo->momy - actor->y)) - sign = -1; // Player is moving away - else - sign = 1; // Player is moving closer - - if (player->mo->momx || player->mo->momy) - { - P_InstaThrust(actor, R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y), FixedMul(actor->info->speed*sign, actor->scale)); - - // Rotate our spike balls - actor->lastlook += actor->info->damage; - actor->lastlook %= FINEANGLES/4; - } - - if (!actor->tracer) // For some reason we do not have spike balls... - return; - - // Position spike balls relative to the value of 'lastlook'. - ball = actor->tracer; - - i = 0; - while (ball) - { - fa = actor->lastlook+i; - v[0] = FixedMul(FINECOSINE(fa),radius); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),radius); - v[3] = FRACUNIT; - - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(actor->lastlook+i))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(actor->angle+ANGLE_180)); - M_Memcpy(&v, res, sizeof (v)); - - P_UnsetThingPosition(ball); - ball->x = actor->x + v[0]; - ball->y = actor->y + v[1]; - ball->z = actor->z + (actor->height>>1) + v[2]; - P_SetThingPosition(ball); - - ball = ball->tracer; - i += ANGLE_90 >> ANGLETOFINESHIFT; - } -} - -// Function: A_CheckBuddy -// -// Description: Checks if target/tracer exists/has health. If not, the object removes itself. -// -// var1: -// 0 = target -// 1 = tracer -// var2 = unused -// -void A_CheckBuddy(mobj_t *actor) -{ - INT32 locvar1 = var1; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CheckBuddy", actor)) - return; -#endif - if (locvar1 && (!actor->tracer || actor->tracer->health <= 0)) - P_RemoveMobj(actor); - else if (!locvar1 && (!actor->target || actor->target->health <= 0)) - P_RemoveMobj(actor); -} - -// Helper function for the Robo Hood. -// Don't ask me how it works. Nev3r made it with dark majyks. -static void P_ParabolicMove(mobj_t *actor, fixed_t x, fixed_t y, fixed_t z, fixed_t speed) -{ - fixed_t dh; - - x -= actor->x; - y -= actor->y; - z -= actor->z; - - dh = P_AproxDistance(x, y); - - actor->momx = FixedMul(FixedDiv(x, dh), speed); - actor->momy = FixedMul(FixedDiv(y, dh), speed); - - if (!gravity) - return; - - dh = FixedDiv(FixedMul(dh, gravity), speed); - actor->momz = (dh>>1) + FixedDiv(z, dh<<1); -} - -// Function: A_HoodFire -// -// Description: Firing Robo-Hood -// -// var1 = object type to fire -// var2 = unused -// -void A_HoodFire(mobj_t *actor) -{ - mobj_t *arrow; - INT32 locvar1 = var1; - //INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_HoodFire", actor)) - return; -#endif - - // Check target first. - if (!actor->target) - { - actor->reactiontime = actor->info->reactiontime; - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - - A_FaceTarget(actor); - - if (!(arrow = P_SpawnMissile(actor, actor->target, (mobjtype_t)locvar1))) - return; - - // Set a parabolic trajectory for the arrow. - P_ParabolicMove(arrow, actor->target->x, actor->target->y, actor->target->z, arrow->info->speed); -} - -// Function: A_HoodThink -// -// Description: Thinker for Robo-Hood -// -// var1 = unused -// var2 = unused -// -void A_HoodThink(mobj_t *actor) -{ - fixed_t dx, dy, dz, dm; - boolean checksight; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_HoodThink", actor)) - return; -#endif - - // Check target first. - if (!actor->target) - { - actor->reactiontime = actor->info->reactiontime; - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - - dx = (actor->target->x - actor->x), dy = (actor->target->y - actor->y), dz = (actor->target->z - actor->z); - dm = P_AproxDistance(dx, dy); - // Target dangerously close to robohood, retreat then. - if ((dm < 256<info->raisestate); - return; - } - - // If target on sight, look at it. - if ((checksight = P_CheckSight(actor, actor->target))) - { - angle_t dang = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); - if (actor->angle >= ANGLE_180) - { - actor->angle = InvAngle(actor->angle)>>1; - actor->angle = InvAngle(actor->angle); - } - else - actor->angle >>= 1; - - if (dang >= ANGLE_180) - { - dang = InvAngle(dang)>>1; - dang = InvAngle(dang); - } - else - dang >>= 1; - - actor->angle += dang; - } - - // Check whether to do anything. - if ((--actor->reactiontime) <= 0) - { - actor->reactiontime = actor->info->reactiontime; - - // If way too far, don't shoot. - if ((dm < (3072<info->missilestate); - return; - } - } -} - -// Function: A_HoodFall -// -// Description: Falling Robo-Hood -// -// var1 = unused -// var2 = unused -// -void A_HoodFall(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_HoodFall", actor)) - return; -#endif - - if (!P_IsObjectOnGround(actor)) - return; - - actor->momx = actor->momy = 0; - actor->reactiontime = actor->info->reactiontime; - P_SetMobjState(actor, actor->info->seestate); -} - -// Function: A_ArrowBonks -// -// Description: Arrow momentum setting on collision -// -// var1 = unused -// var2 = unused -// -void A_ArrowBonks(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ArrowBonks", actor)) - return; -#endif - - if (((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz) - || (!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)) - actor->angle += ANGLE_180; - - P_SetObjectMomZ(actor, 8*actor->scale, false); - P_InstaThrust(actor, actor->angle, -6*actor->scale); - - actor->flags = (actor->flags|MF_NOCLIPHEIGHT) & ~MF_NOGRAVITY; - actor->z += P_MobjFlip(actor); -} - -// Function: A_SnailerThink -// -// Description: Thinker function for Snailer -// -// var1 = unused -// var2 = unused -// -void A_SnailerThink(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SnailerThink", actor)) - return; -#endif - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { - // look for a new target - if (!P_LookForPlayers(actor, true, false, 0)) - return; - } - - // We now have a target. Oh bliss, rapture, and contentment! - - if (actor->target->z + actor->target->height > actor->z - FixedMul(32*FRACUNIT, actor->scale) - && actor->target->z < actor->z + actor->height + FixedMul(32*FRACUNIT, actor->scale) - && !(leveltime % (TICRATE*2))) - { - angle_t an; - fixed_t z; - - // Actor shouldn't face target, so we'll do things a bit differently here - - an = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) - actor->angle; - - z = actor->z + actor->height/2; - - if (an > ANGLE_45 && an < ANGLE_315) // fire as close as you can to the target, even if too sharp an angle from your front - { - fixed_t dist; - fixed_t dx, dy; - - dist = P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y); - - if (an > ANGLE_45 && an <= ANGLE_90) // fire at 45 degrees to the left - { - dx = actor->x + P_ReturnThrustX(actor, actor->angle + ANGLE_45, dist); - dy = actor->y + P_ReturnThrustY(actor, actor->angle + ANGLE_45, dist); - } - else if (an >= ANGLE_270 && an < ANGLE_315) // fire at 45 degrees to the right - { - dx = actor->x + P_ReturnThrustX(actor, actor->angle - ANGLE_45, dist); - dy = actor->y + P_ReturnThrustY(actor, actor->angle - ANGLE_45, dist); - } - else // fire straight ahead - { - dx = actor->x + P_ReturnThrustX(actor, actor->angle, dist); - dy = actor->y + P_ReturnThrustY(actor, actor->angle, dist); - } - - P_SpawnPointMissile(actor, dx, dy, actor->target->z, MT_ROCKET, actor->x, actor->y, z); - } - else - P_SpawnXYZMissile(actor, actor->target, MT_ROCKET, actor->x, actor->y, z); - } - - if ((!(actor->eflags & MFE_VERTICALFLIP) && actor->target->z > actor->z) - || (actor->eflags & MFE_VERTICALFLIP && (actor->target->z + actor->target->height) > (actor->z + actor->height))) - actor->momz += FixedMul(actor->info->speed, actor->scale); - else if ((!(actor->eflags & MFE_VERTICALFLIP) && actor->target->z < actor->z) - || (actor->eflags & MFE_VERTICALFLIP && (actor->target->z + actor->target->height) < (actor->z + actor->height))) - actor->momz -= FixedMul(actor->info->speed, actor->scale); - - actor->momz /= 2; -} - -// Function: A_SharpChase -// -// Description: Thinker/Chase routine for Spincushions -// -// var1 = unused -// var2 = unused -// -void A_SharpChase(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SharpChase", actor)) - return; -#endif - - if (actor->reactiontime) - { - INT32 delta; - - actor->reactiontime--; - - // turn towards movement direction if not there yet - if (actor->movedir < NUMDIRS) - { - actor->angle &= (7<<29); - delta = actor->angle - (actor->movedir << 29); - - if (delta > 0) - actor->angle -= ANGLE_45; - else if (delta < 0) - actor->angle += ANGLE_45; - } - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { - // look for a new target - if (P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - - // chase towards player - if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) - P_NewChaseDir(actor); - } - else - { - actor->threshold = actor->info->painchance; - P_SetMobjState(actor, actor->info->missilestate); - S_StartSound(actor, actor->info->attacksound); - } -} - -// Function: A_SharpSpin -// -// Description: Spin chase routine for Spincushions -// -// var1 = object # to spawn as dust (if not provided not done) -// var2 = if nonzero, do the old-style spinning using this as the angle difference -// -void A_SharpSpin(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - angle_t oldang = actor->angle; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SharpSpin", actor)) - return; -#endif - - if (actor->threshold && actor->target) - { - angle_t ang = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); - P_Thrust(actor, ang, actor->info->speed*actor->scale); - if (locvar2) - actor->angle += locvar2; // ANGLE_22h; - else - actor->angle = ang; - actor->threshold--; - if (leveltime & 1) - S_StartSound(actor, actor->info->painsound); - } - else - { - actor->reactiontime = actor->info->reactiontime; - P_SetMobjState(actor, actor->info->meleestate); - } - - P_SharpDust(actor, locvar1, oldang); -} - -// Function: A_SharpDecel -// -// Description: Slow down the Spincushion -// -// var1 = unused -// var2 = unused -// -void A_SharpDecel(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SharpDecel", actor)) - return; -#endif - - if (actor->momx > 2 || actor->momy > 2) - { - actor->momx >>= 1; - actor->momy >>= 1; - } - else - P_SetMobjState(actor, actor->info->xdeathstate); -} - -// Function: A_CrushstaceanWalk -// -// Description: Crushstacean movement -// -// var1 = speed (actor info's speed if 0) -// var2 = state to switch to when blocked (spawnstate if 0) -// -void A_CrushstaceanWalk(mobj_t *actor) -{ - INT32 locvar1 = (var1 ? var1 : (INT32)actor->info->speed); - INT32 locvar2 = (var2 ? var2 : (INT32)actor->info->spawnstate); - angle_t ang = actor->angle + ((actor->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270); -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CrushstaceanWalk", actor)) - return; -#endif - - actor->reactiontime--; - - if (!P_TryMove(actor, - actor->x + P_ReturnThrustX(actor, ang, locvar1*actor->scale), - actor->y + P_ReturnThrustY(actor, ang, locvar1*actor->scale), - false) - || (actor->reactiontime-- <= 0)) - { - actor->flags2 ^= MF2_AMBUSH; - P_SetMobjState(actor, locvar2); - actor->reactiontime = actor->info->reactiontime; - } -} - -// Function: A_CrushstaceanPunch -// -// Description: Crushstacean attack -// -// var1 = unused -// var2 = state to go to if unsuccessful (spawnstate if 0) -// -void A_CrushstaceanPunch(mobj_t *actor) -{ - //INT32 locvar1 = var1; - INT32 locvar2 = (var2 ? var2 : (INT32)actor->info->spawnstate); -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CrushstaceanPunch", actor)) - return; -#endif - - if (!actor->tracer) - return; - - if (!actor->target) - { - P_SetMobjState(actor, locvar2); - return; - } - - actor->tracer->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); - P_SetMobjState(actor->tracer, actor->tracer->info->missilestate); - actor->tracer->extravalue1 = actor->tracer->extravalue2 = 0; - S_StartSound(actor, actor->info->attacksound); -} - -// Function: A_CrushclawAim -// -// Description: Crushstacean claw aiming -// -// var1 = sideways offset -// var2 = vertical offset -// -void A_CrushclawAim(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - mobj_t *crab = actor->tracer; - angle_t ang; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CrushclawAim", actor)) - return; -#endif - - if (!crab) - { - P_RemoveMobj(actor); - return; // there is only one step and it is crab - } - - if (crab->target || P_LookForPlayers(crab, true, false, 600*crab->scale)) - ang = R_PointToAngle2(crab->x, crab->y, crab->target->x, crab->target->y); - else - ang = crab->angle + ((crab->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270); - ang -= actor->angle; - -#define anglimit ANGLE_22h -#define angfactor 5 - if (ang < ANGLE_180) - { - if (ang > anglimit) - ang = anglimit; - ang /= angfactor; - } - else - { - ang = InvAngle(ang); - if (ang > anglimit) - ang = anglimit; - ang = InvAngle(ang/angfactor); - } - actor->angle += ang; -#undef anglimit -#undef angfactor - - P_TeleportMove(actor, - crab->x + P_ReturnThrustX(actor, actor->angle, locvar1*crab->scale), - crab->y + P_ReturnThrustY(actor, actor->angle, locvar1*crab->scale), - crab->z + locvar2*crab->scale); - - if (!crab->target || !crab->info->missilestate || (statenum_t)(crab->state-states) == crab->info->missilestate) - return; - - if (((ang + ANG1) < ANG2) || P_AproxDistance(crab->x - crab->target->x, crab->y - crab->target->y) < 333*crab->scale) - P_SetMobjState(crab, crab->info->missilestate); -} - -// Function: A_CrushclawLaunch -// -// Description: Crushstacean claw launching -// -// var1: -// 0 - forwards -// anything else - backwards -// var2 = state to change to when done -// -void A_CrushclawLaunch(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - mobj_t *crab = actor->tracer; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CrushclawLaunch", actor)) - return; -#endif - - if (!crab) - { - mobj_t *chainnext; - while (actor) - { - chainnext = actor->target; - P_RemoveMobj(actor); - actor = chainnext; - } - return; // there is only one step and it is crab - } - - if (!actor->extravalue1) - { - S_StartSound(actor, actor->info->activesound); - actor->extravalue1 = ((locvar1) ? -1 : 32); - } - else if (actor->extravalue1 != 1) - actor->extravalue1 -= 1; - -#define CSEGS 5 - if (!actor->target) - { - mobj_t *prevchain = actor; - UINT8 i = 0; - for (i = 0; (i < CSEGS); i++) - { - mobj_t *newchain = P_SpawnMobjFromMobj(actor, 0, 0, 0, actor->info->raisestate); - prevchain->target = newchain; - prevchain = newchain; - } - actor->target->angle = R_PointToAngle2(actor->target->x, actor->target->y, crab->target->x, crab->target->y); - } - - if ((!locvar1) && crab->target) - { -#define anglimit ANGLE_22h -#define angfactor 7 - angle_t ang = R_PointToAngle2(actor->target->x, actor->target->y, crab->target->x, crab->target->y) - actor->target->angle; - if (ang < ANGLE_180) - { - if (ang > anglimit) - ang = anglimit; - ang /= angfactor; - } - else - { - ang = InvAngle(ang); - if (ang > anglimit) - ang = anglimit; - ang /= angfactor; - ang = InvAngle(ang); - } - actor->target->angle += ang; - actor->angle = actor->target->angle; - } - - actor->extravalue2 += actor->extravalue1; - - if (!P_TryMove(actor, - actor->target->x + P_ReturnThrustX(actor, actor->target->angle, actor->extravalue2*actor->scale), - actor->target->y + P_ReturnThrustY(actor, actor->target->angle, actor->extravalue2*actor->scale), - true) - && !locvar1) - { - actor->extravalue1 = 0; - actor->extravalue2 = FixedHypot(actor->x - actor->target->x, actor->y - actor->target->y)>>FRACBITS; - P_SetMobjState(actor, locvar2); - S_StopSound(actor); - S_StartSound(actor, sfx_s3k49); - } - else - { - actor->z = actor->target->z; - if ((!locvar1 && (actor->extravalue2 > 256)) || (locvar1 && (actor->extravalue2 < 16))) - { - if (locvar1) // In case of retracting, resume crab and remove the chain. - { - mobj_t *chain = actor->target, *chainnext; - while (chain) - { - chainnext = chain->target; - P_RemoveMobj(chain); - chain = chainnext; - } - actor->extravalue2 = 0; - actor->angle = R_PointToAngle2(crab->x, crab->y, actor->x, actor->y); - P_SetTarget(&actor->target, NULL); - P_SetTarget(&crab->target, NULL); - P_SetMobjState(crab, crab->state->nextstate); - } - actor->extravalue1 = 0; - P_SetMobjState(actor, locvar2); - S_StopSound(actor); - if (!locvar1) - S_StartSound(actor, sfx_s3k64); - } - } - - if (!actor->target) - return; - - { - mobj_t *chain = actor->target->target; - fixed_t dx = (actor->x - actor->target->x)/CSEGS, dy = (actor->y - actor->target->y)/CSEGS, dz = (actor->z - actor->target->z)/CSEGS; - fixed_t idx = dx, idy = dy, idz = dz; - while (chain) - { - P_TeleportMove(chain, actor->target->x + idx, actor->target->y + idy, actor->target->z + idz); - chain->watertop = chain->z; - idx += dx; - idy += dy; - idz += dz; - chain = chain->target; - } - } -#undef CSEGS -} - -// Function: A_VultureVtol -// -// Description: Vulture rising up to match target's height -// -// var1 = unused -// var2 = unused -// -void A_VultureVtol(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_VultureVtol", actor)) - return; -#endif - - if (!actor->target) - return; - - actor->flags |= MF_NOGRAVITY; - actor->flags |= MF_FLOAT; - - A_FaceTarget(actor); - - S_StopSound(actor); - - if (actor->z < actor->target->z+(actor->target->height/4) && actor->z + actor->height < actor->ceilingz) - actor->momz = FixedMul(2*FRACUNIT, actor->scale); - else if (actor->z > (actor->target->z+(actor->target->height/4)*3) && actor->z > actor->floorz) - actor->momz = FixedMul(-2*FRACUNIT, actor->scale); - else - { - // Attack! - actor->momz = 0; - P_SetMobjState(actor, actor->info->missilestate); - S_StartSound(actor, actor->info->activesound); - } -} - -// Function: A_VultureCheck -// -// Description: If the vulture is stopped, look for a new target -// -// var1 = unused -// var2 = unused -// -void A_VultureCheck(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_VultureCheck", actor)) - return; -#endif - - if (actor->momx || actor->momy) - return; - - actor->flags &= ~MF_NOGRAVITY; // Fall down - - if (actor->z <= actor->floorz) - { - actor->angle -= ANGLE_180; // turn around - P_SetMobjState(actor, actor->info->spawnstate); - } -} - -// Function: A_SkimChase -// -// Description: Thinker/Chase routine for Skims -// -// var1 = unused -// var2 = unused -// -void A_SkimChase(mobj_t *actor) -{ - INT32 delta; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SkimChase", actor)) - return; -#endif - if (actor->reactiontime) - actor->reactiontime--; - - // modify target threshold - if (actor->threshold) - { - if (!actor->target || actor->target->health <= 0) - actor->threshold = 0; - else - actor->threshold--; - } - - // turn towards movement direction if not there yet - if (actor->movedir < NUMDIRS) - { - actor->angle &= (7<<29); - delta = actor->angle - (actor->movedir << 29); - - if (delta > 0) - actor->angle -= ANGLE_45; - else if (delta < 0) - actor->angle += ANGLE_45; - } - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { - // look for a new target - P_LookForPlayers(actor, true, false, 0); - - // the spawnstate for skims already calls this function so just return either way - // without changing state - return; - } - - // do not attack twice in a row - if (actor->flags2 & MF2_JUSTATTACKED) - { - actor->flags2 &= ~MF2_JUSTATTACKED; - P_NewChaseDir(actor); - return; - } - - // check for melee attack - if (actor->info->meleestate && P_SkimCheckMeleeRange(actor)) - { - if (actor->info->attacksound) - S_StartAttackSound(actor, actor->info->attacksound); - - P_SetMobjState(actor, actor->info->meleestate); - return; - } - - // check for missile attack - if (actor->info->missilestate) - { - if (actor->movecount || !P_CheckMissileRange(actor)) - goto nomissile; - - P_SetMobjState(actor, actor->info->missilestate); - actor->flags2 |= MF2_JUSTATTACKED; - return; - } - -nomissile: - // possibly choose another target - if (multiplayer && !actor->threshold && (actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) - && P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - // chase towards player - if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) - P_NewChaseDir(actor); -} - -// Function: A_FaceTarget -// -// Description: Immediately turn to face towards your target. -// -// var1 = unused -// var2 = unused -// -void A_FaceTarget(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FaceTarget", actor)) - return; -#endif - if (!actor->target) - return; - - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); -} - -// Function: A_FaceTracer -// -// Description: Immediately turn to face towards your tracer. -// -// var1 = unused -// var2 = unused -// -void A_FaceTracer(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FaceTracer", actor)) - return; -#endif - if (!actor->tracer) - return; - - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); -} - -// Function: A_LobShot -// -// Description: Lob an object at your target. -// -// var1 = object # to lob -// var2: -// var2 >> 16 = height offset -// var2 & 65535 = airtime -// -void A_LobShot(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2 >> 16; - mobj_t *shot, *hitspot; - angle_t an; - fixed_t z; - fixed_t dist; - fixed_t vertical, horizontal; - fixed_t airtime = var2 & 65535; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_LobShot", actor)) - return; -#endif - if (!actor->target) - return; - - A_FaceTarget(actor); - - if (actor->eflags & MFE_VERTICALFLIP) - { - z = actor->z + actor->height - FixedMul(locvar2*FRACUNIT, actor->scale); - if (actor->type == MT_BLACKEGGMAN) - z -= FixedMul(mobjinfo[locvar1].height, actor->scale/2); - else - z -= FixedMul(mobjinfo[locvar1].height, actor->scale); - } - else - z = actor->z + FixedMul(locvar2*FRACUNIT, actor->scale); - - shot = P_SpawnMobj(actor->x, actor->y, z, locvar1); - - if (actor->type == MT_BLACKEGGMAN) - { - shot->destscale = actor->scale/2; - P_SetScale(shot, actor->scale/2); - } - else - { - shot->destscale = actor->scale; - P_SetScale(shot, actor->scale); - } - - // Keep track of where it's going to land - hitspot = P_SpawnMobj(actor->target->x&(64*FRACUNIT-1), actor->target->y&(64*FRACUNIT-1), actor->target->subsector->sector->floorheight, MT_NULL); - hitspot->tics = airtime; - P_SetTarget(&shot->tracer, hitspot); - - P_SetTarget(&shot->target, actor); // where it came from - - shot->angle = an = actor->angle; - an >>= ANGLETOFINESHIFT; - - dist = P_AproxDistance(actor->target->x - shot->x, actor->target->y - shot->y); - - horizontal = dist / airtime; - vertical = FixedMul((gravity*airtime)/2, shot->scale); - - shot->momx = FixedMul(horizontal, FINECOSINE(an)); - shot->momy = FixedMul(horizontal, FINESINE(an)); - shot->momz = vertical; - -/* Try to adjust when destination is not the same height - if (actor->z != actor->target->z) - { - fixed_t launchhyp; - fixed_t diff; - fixed_t orig; - - diff = actor->z - actor->target->z; - { - launchhyp = P_AproxDistance(horizontal, vertical); - - orig = FixedMul(FixedDiv(vertical, horizontal), diff); - - CONS_Debug(DBG_GAMELOGIC, "orig: %d\n", (orig)>>FRACBITS); - - horizontal = dist / airtime; - vertical = (gravity*airtime)/2; - } - dist -= orig; - shot->momx = FixedMul(horizontal, FINECOSINE(an)); - shot->momy = FixedMul(horizontal, FINESINE(an)); - shot->momz = vertical; -*/ - - if (shot->info->seesound) - S_StartSound(shot, shot->info->seesound); - - if (!(actor->flags & MF_BOSS)) - { - if (ultimatemode) - actor->reactiontime = actor->info->reactiontime*TICRATE; - else - actor->reactiontime = actor->info->reactiontime*TICRATE*2; - } -} - -// Function: A_FireShot -// -// Description: Shoot an object at your target. -// -// var1 = object # to shoot -// var2 = height offset -// -void A_FireShot(mobj_t *actor) -{ - fixed_t z; - INT32 locvar1 = var1; - INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FireShot", actor)) - return; -#endif - if (!actor->target) - return; - - A_FaceTarget(actor); - - if (actor->eflags & MFE_VERTICALFLIP) - z = actor->z + actor->height - FixedMul(48*FRACUNIT + locvar2*FRACUNIT, actor->scale); - else - z = actor->z + FixedMul(48*FRACUNIT + locvar2*FRACUNIT, actor->scale); - - P_SpawnXYZMissile(actor, actor->target, locvar1, actor->x, actor->y, z); - - if (!(actor->flags & MF_BOSS)) - { - if (ultimatemode) - actor->reactiontime = actor->info->reactiontime*TICRATE; - else - actor->reactiontime = actor->info->reactiontime*TICRATE*2; - } -} - -// Function: A_SuperFireShot -// -// Description: Shoot an object at your target that will even stall Super Sonic. -// -// var1 = object # to shoot -// var2 = height offset -// -void A_SuperFireShot(mobj_t *actor) -{ - fixed_t z; - mobj_t *mo; - INT32 locvar1 = var1; - INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SuperFireShot", actor)) - return; -#endif - if (!actor->target) - return; - - A_FaceTarget(actor); - - if (actor->eflags & MFE_VERTICALFLIP) - z = actor->z + actor->height - FixedMul(48*FRACUNIT + locvar2*FRACUNIT, actor->scale); - else - z = actor->z + FixedMul(48*FRACUNIT + locvar2*FRACUNIT, actor->scale); - - mo = P_SpawnXYZMissile(actor, actor->target, locvar1, actor->x, actor->y, z); - - if (mo) - mo->flags2 |= MF2_SUPERFIRE; - - if (!(actor->flags & MF_BOSS)) - { - if (ultimatemode) - actor->reactiontime = actor->info->reactiontime*TICRATE; - else - actor->reactiontime = actor->info->reactiontime*TICRATE*2; - } -} - -// Function: A_BossFireShot -// -// Description: Shoot an object at your target ala Bosses: -// -// var1 = object # to shoot -// var2: -// 0 - Boss 1 Left side -// 1 - Boss 1 Right side -// 2 - Boss 3 Left side upper -// 3 - Boss 3 Left side lower -// 4 - Boss 3 Right side upper -// 5 - Boss 3 Right side lower -// -void A_BossFireShot(mobj_t *actor) -{ - fixed_t x, y, z; - INT32 locvar1 = var1; - INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_BossFireShot", actor)) - return; -#endif - if (!actor->target) - return; - - A_FaceTarget(actor); - - switch (locvar2) - { - case 0: - x = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); - y = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); - if (actor->eflags & MFE_VERTICALFLIP) - z = actor->z + actor->height - FixedMul(48*FRACUNIT, actor->scale); - else - z = actor->z + FixedMul(48*FRACUNIT, actor->scale); - break; - case 1: - x = actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); - y = actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); - if (actor->eflags & MFE_VERTICALFLIP) - z = actor->z + actor->height - FixedMul(48*FRACUNIT, actor->scale); - else - z = actor->z + FixedMul(48*FRACUNIT, actor->scale); - break; - case 2: - x = actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(56*FRACUNIT, actor->scale)); - y = actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(56*FRACUNIT, actor->scale)); - if (actor->eflags & MFE_VERTICALFLIP) - z = actor->z + actor->height - FixedMul(42*FRACUNIT, actor->scale); - else - z = actor->z + FixedMul(42*FRACUNIT, actor->scale); - break; - case 3: - x = actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(58*FRACUNIT, actor->scale)); - y = actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(58*FRACUNIT, actor->scale)); - if (actor->eflags & MFE_VERTICALFLIP) - z = actor->z + actor->height - FixedMul(30*FRACUNIT, actor->scale); - else - z = actor->z + FixedMul(30*FRACUNIT, actor->scale); - break; - case 4: - x = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(56*FRACUNIT, actor->scale)); - y = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(56*FRACUNIT, actor->scale)); - if (actor->eflags & MFE_VERTICALFLIP) - z = actor->z + actor->height - FixedMul(42*FRACUNIT, actor->scale); - else - z = actor->z + FixedMul(42*FRACUNIT, actor->scale); - break; - case 5: - x = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(58*FRACUNIT, actor->scale)); - y = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(58*FRACUNIT, actor->scale)); - if (actor->eflags & MFE_VERTICALFLIP) - z = actor->z + actor->height - FixedMul(30*FRACUNIT, actor->scale); - else - z = actor->z + FixedMul(30*FRACUNIT, actor->scale); - break; - default: - x = actor->x; - y = actor->y; - z = actor->z + actor->height/2; - break; - } - - P_SpawnXYZMissile(actor, actor->target, locvar1, x, y, z); -} - -// Function: A_Boss7FireMissiles -// -// Description: Shoot 4 missiles of a specific object type at your target ala Black Eggman -// -// var1 = object # to shoot -// var2 = firing sound -// -void A_Boss7FireMissiles(mobj_t *actor) -{ - mobj_t dummymo; - INT32 locvar1 = var1; - INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Boss7FireMissiles", actor)) - return; -#endif - - if (!actor->target) - { - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - - A_FaceTarget(actor); - - S_StartSound(NULL, locvar2); - - // set dummymo's coordinates - dummymo.x = actor->target->x; - dummymo.y = actor->target->y; - dummymo.z = actor->target->z + FixedMul(16*FRACUNIT, actor->scale); // raised height - - P_SpawnXYZMissile(actor, &dummymo, locvar1, - actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedDiv(actor->radius, 3*FRACUNIT/2)+FixedMul(4*FRACUNIT, actor->scale)), - actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedDiv(actor->radius, 3*FRACUNIT/2)+FixedMul(4*FRACUNIT, actor->scale)), - actor->z + FixedDiv(actor->height, 3*FRACUNIT/2)); - - P_SpawnXYZMissile(actor, &dummymo, locvar1, - actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedDiv(actor->radius, 3*FRACUNIT/2)+FixedMul(4*FRACUNIT, actor->scale)), - actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedDiv(actor->radius, 3*FRACUNIT/2)+FixedMul(4*FRACUNIT, actor->scale)), - actor->z + FixedDiv(actor->height, 3*FRACUNIT/2)); - - P_SpawnXYZMissile(actor, &dummymo, locvar1, - actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedDiv(actor->radius, 3*FRACUNIT/2)+FixedMul(4*FRACUNIT, actor->scale)), - actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedDiv(actor->radius, 3*FRACUNIT/2)+FixedMul(4*FRACUNIT, actor->scale)), - actor->z + actor->height/2); - - P_SpawnXYZMissile(actor, &dummymo, locvar1, - actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedDiv(actor->radius, 3*FRACUNIT/2)+FixedMul(4*FRACUNIT, actor->scale)), - actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedDiv(actor->radius, 3*FRACUNIT/2)+FixedMul(4*FRACUNIT, actor->scale)), - actor->z + actor->height/2); -} - -// Function: A_Boss1Laser -// -// Description: Shoot an object at your target ala Bosses: -// -// var1 = object # to shoot -// var2: -// 0 - Boss 1 Left side -// 1 - Boss 1 Right side -// -void A_Boss1Laser(mobj_t *actor) -{ - fixed_t x, y, z, floorz, speed; - INT32 locvar1 = var1; - INT32 locvar2 = var2; - INT32 i; - angle_t angle; - mobj_t *point; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Boss1Laser", actor)) - return; -#endif - if (!actor->target) - return; - - switch (locvar2) - { - case 0: - x = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); - y = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); - if (actor->eflags & MFE_VERTICALFLIP) - z = actor->z + actor->height - FixedMul(56*FRACUNIT, actor->scale) - mobjinfo[locvar1].height; - else - z = actor->z + FixedMul(56*FRACUNIT, actor->scale); - break; - case 1: - x = actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); - y = actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); - if (actor->eflags & MFE_VERTICALFLIP) - z = actor->z + actor->height - FixedMul(56*FRACUNIT, actor->scale) - mobjinfo[locvar1].height; - else - z = actor->z + FixedMul(56*FRACUNIT, actor->scale); - break; - default: - x = actor->x; - y = actor->y; - z = actor->z + actor->height/2; - break; - } - - if (!(actor->flags2 & MF2_FIRING)) - { - actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y); - if (mobjinfo[locvar1].seesound) - S_StartSound(actor, mobjinfo[locvar1].seesound); - if (!(actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH)) - { - point = P_SpawnMobj(x + P_ReturnThrustX(actor, actor->angle, actor->radius), y + P_ReturnThrustY(actor, actor->angle, actor->radius), actor->z - actor->height / 2, MT_EGGMOBILE_TARGET); - point->angle = actor->angle; - point->fuse = actor->tics+1; - P_SetTarget(&point->target, actor->target); - P_SetTarget(&actor->target, point); - } - } - /* -- the following was relevant when the MT_EGGMOBILE_TARGET was allowed to move left and right from its path - else if (actor->target && !(actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH)) - actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y);*/ - - if (actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH) - angle = FixedAngle(FixedDiv(actor->tics*160*FRACUNIT, actor->state->tics*FRACUNIT) + 10*FRACUNIT); - else - angle = R_PointToAngle2(z + (mobjinfo[locvar1].height>>1), 0, actor->target->z, R_PointToDist2(x, y, actor->target->x, actor->target->y)); - point = P_SpawnMobj(x, y, z, locvar1); - P_SetTarget(&point->target, actor); - point->angle = actor->angle; - speed = point->radius*2; - point->momz = FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT), speed); - point->momx = FixedMul(FINESINE(angle>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(point->angle>>ANGLETOFINESHIFT), speed)); - point->momy = FixedMul(FINESINE(angle>>ANGLETOFINESHIFT), FixedMul(FINESINE(point->angle>>ANGLETOFINESHIFT), speed)); - - for (i = 0; i < 256; i++) - { - mobj_t *mo = P_SpawnMobj(point->x, point->y, point->z, point->type); - mo->angle = point->angle; - P_UnsetThingPosition(mo); - mo->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY; - P_SetThingPosition(mo); - - x = point->x, y = point->y, z = point->z; - if (P_RailThinker(point)) - break; - } - - floorz = P_FloorzAtPos(x, y, z, mobjinfo[MT_EGGMOBILE_FIRE].height); - if (z - floorz < mobjinfo[MT_EGGMOBILE_FIRE].height>>1) - { - point = P_SpawnMobj(x, y, floorz+1, MT_EGGMOBILE_FIRE); - point->target = actor; - point->destscale = 3*FRACUNIT; - point->scalespeed = FRACUNIT>>2; - point->fuse = TICRATE; - } - - if (actor->tics > 1) - actor->flags2 |= MF2_FIRING; - else - actor->flags2 &= ~MF2_FIRING; -} - -// Function: A_FocusTarget -// -// Description: Home in on your target. -// -// var1: -// 0 - accelerative focus with friction -// 1 - steady focus with fixed movement speed -// anything else - don't move -// var2: -// 0 - don't trace target, just move forwards -// & 1 - change horizontal angle -// & 2 - change vertical angle -// -void A_FocusTarget(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FocusTarget", actor)) - return; -#endif - - if (actor->target) - { - fixed_t speed = FixedMul(actor->info->speed, actor->scale); - fixed_t dist = (locvar2 ? R_PointToDist2(actor->x, actor->y, actor->target->x, actor->target->y) : speed+1); - angle_t hangle = ((locvar2 & 1) ? R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) : actor->angle); - angle_t vangle = ((locvar2 & 2) ? R_PointToAngle2(actor->z , 0, actor->target->z + (actor->target->height>>1), dist) : ANGLE_90); - switch(locvar1) - { - case 0: - { - actor->momx -= actor->momx>>4, actor->momy -= actor->momy>>4, actor->momz -= actor->momz>>4; - actor->momz += FixedMul(FINECOSINE(vangle>>ANGLETOFINESHIFT), speed); - actor->momx += FixedMul(FINESINE(vangle>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(hangle>>ANGLETOFINESHIFT), speed)); - actor->momy += FixedMul(FINESINE(vangle>>ANGLETOFINESHIFT), FixedMul(FINESINE(hangle>>ANGLETOFINESHIFT), speed)); - } - break; - case 1: - if (dist > speed) - { - actor->momz = FixedMul(FINECOSINE(vangle>>ANGLETOFINESHIFT), speed); - actor->momx = FixedMul(FINESINE(vangle>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(hangle>>ANGLETOFINESHIFT), speed)); - actor->momy = FixedMul(FINESINE(vangle>>ANGLETOFINESHIFT), FixedMul(FINESINE(hangle>>ANGLETOFINESHIFT), speed)); - } - else - { - actor->momx = 0, actor->momy = 0, actor->momz = 0; - actor->z = actor->target->z + (actor->target->height>>1); - P_TryMove(actor, actor->target->x, actor->target->y, true); - } - break; - default: - break; - } - } -} - -// Function: A_Boss4Reverse -// -// Description: Reverse arms direction. -// -// var1 = sfx to play -// var2 = unused -// -void A_Boss4Reverse(mobj_t *actor) -{ - sfxenum_t locvar1 = (sfxenum_t)var1; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Boss4Reverse", actor)) - return; -#endif - S_StartSound(NULL, locvar1); - actor->reactiontime = 0; - if (actor->movedir == 1) - actor->movedir = 2; - else - actor->movedir = 1; -} - -// Function: A_Boss4SpeedUp -// -// Description: Speed up arms -// -// var1 = sfx to play -// var2 = unused -// -void A_Boss4SpeedUp(mobj_t *actor) -{ - sfxenum_t locvar1 = (sfxenum_t)var1; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Boss4SpeedUp", actor)) - return; -#endif - S_StartSound(NULL, locvar1); - actor->reactiontime = 2; -} - -// Function: A_Boss4Raise -// -// Description: Raise helmet -// -// var1 = sfx to play -// var2 = unused -// -void A_Boss4Raise(mobj_t *actor) -{ - sfxenum_t locvar1 = (sfxenum_t)var1; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Boss4Raise", actor)) - return; -#endif - S_StartSound(NULL, locvar1); - actor->reactiontime = 1; -} - -// Function: A_SkullAttack -// -// Description: Fly at the player like a missile. -// -// var1: -// 0 - Fly at the player -// 1 - Fly away from the player -// 2 - Strafe in relation to the player -// var2: -// 0 - Fly horizontally and vertically -// 1 - Fly horizontal-only (momz = 0) -// -#define SKULLSPEED (20*FRACUNIT) - -void A_SkullAttack(mobj_t *actor) -{ - mobj_t *dest; - angle_t an; - INT32 dist; - INT32 speed; - INT32 locvar1 = var1; - INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SkullAttack", actor)) - return; -#endif - if (!actor->target) - return; - - speed = FixedMul(SKULLSPEED, actor->scale); - - dest = actor->target; - actor->flags2 |= MF2_SKULLFLY; - if (actor->info->activesound) - S_StartSound(actor, actor->info->activesound); - A_FaceTarget(actor); - - if (locvar1 == 1) - actor->angle += ANGLE_180; - else if (locvar1 == 2) - actor->angle += (P_RandomChance(FRACUNIT/2)) ? ANGLE_90 : -ANGLE_90; - - an = actor->angle >> ANGLETOFINESHIFT; - - actor->momx = FixedMul(speed, FINECOSINE(an)); - actor->momy = FixedMul(speed, FINESINE(an)); - dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); - dist = dist / speed; - - if (dist < 1) - dist = 1; - - actor->momz = (dest->z + (dest->height>>1) - actor->z) / dist; - - if (locvar1 == 1) - actor->momz = -actor->momz; - if (locvar2 == 1) - actor->momz = 0; -} - -// Function: A_BossZoom -// -// Description: Like A_SkullAttack, but used by Boss 1. -// -// var1 = unused -// var2 = unused -// -void A_BossZoom(mobj_t *actor) -{ - mobj_t *dest; - angle_t an; - INT32 dist; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_BossZoom", actor)) - return; -#endif - if (!actor->target) - return; - - dest = actor->target; - actor->flags2 |= MF2_SKULLFLY; - if (actor->info->attacksound) - S_StartAttackSound(actor, actor->info->attacksound); - A_FaceTarget(actor); - an = actor->angle >> ANGLETOFINESHIFT; - actor->momx = FixedMul(FixedMul(actor->info->speed*5*FRACUNIT, actor->scale), FINECOSINE(an)); - actor->momy = FixedMul(FixedMul(actor->info->speed*5*FRACUNIT, actor->scale), FINESINE(an)); - dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); - dist = dist / FixedMul(actor->info->speed*5*FRACUNIT, actor->scale); - - if (dist < 1) - dist = 1; - actor->momz = (dest->z + (dest->height>>1) - actor->z) / dist; -} - -// Function: A_BossScream -// -// Description: Spawns explosions and plays appropriate sounds around the defeated boss. -// -// var1: -// 0 - Use movecount to spawn explosions evenly -// 1 - Use P_Random to spawn explosions at complete random -// var2 = Object to spawn. Default is MT_BOSSEXPLODE. -// -void A_BossScream(mobj_t *actor) -{ - mobj_t *mo; - fixed_t x, y, z; - angle_t fa; - INT32 locvar1 = var1; - INT32 locvar2 = var2; - mobjtype_t explodetype; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_BossScream", actor)) - return; -#endif - switch (locvar1) - { - default: - case 0: - actor->movecount += 4*16; - actor->movecount %= 360; - fa = (FixedAngle(actor->movecount*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; - break; - case 1: - fa = (FixedAngle(P_RandomKey(360)*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; - break; - } - x = actor->x + FixedMul(FINECOSINE(fa),actor->radius); - y = actor->y + FixedMul(FINESINE(fa),actor->radius); - - // Determine what mobj to spawn. If undefined or invalid, use MT_BOSSEXPLODE as default. - if (locvar2 <= 0 || locvar2 >= NUMMOBJTYPES) - explodetype = MT_BOSSEXPLODE; - else - explodetype = (mobjtype_t)locvar2; - - if (actor->eflags & MFE_VERTICALFLIP) - z = actor->z + actor->height - mobjinfo[explodetype].height - FixedMul((P_RandomByte()<<(FRACBITS-2)) - 8*FRACUNIT, actor->scale); - else - z = actor->z + FixedMul((P_RandomByte()<<(FRACBITS-2)) - 8*FRACUNIT, actor->scale); - - mo = P_SpawnMobj(x, y, z, explodetype); - if (actor->eflags & MFE_VERTICALFLIP) - mo->flags2 |= MF2_OBJECTFLIP; - mo->destscale = actor->scale; - P_SetScale(mo, mo->destscale); - if (actor->info->deathsound) - S_StartSound(mo, actor->info->deathsound); -} - -// Function: A_Scream -// -// Description: Starts the death sound of the object. -// -// var1 = unused -// var2 = unused -// -void A_Scream(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Scream", actor)) - return; -#endif - if (actor->tracer && (actor->tracer->type == MT_SHELL || actor->tracer->type == MT_FIREBALL)) - S_StartScreamSound(actor, sfx_mario2); - else if (actor->info->deathsound) - S_StartScreamSound(actor, actor->info->deathsound); -} - -// Function: A_Pain -// -// Description: Starts the pain sound of the object. -// -// var1 = unused -// var2 = unused -// -void A_Pain(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Pain", actor)) - return; -#endif - if (actor->info->painsound) - S_StartSound(actor, actor->info->painsound); - - actor->flags2 &= ~MF2_FIRING; - actor->flags2 &= ~MF2_SUPERFIRE; -} - -// Function: A_Fall -// -// Description: Changes a dying object's flags to reflect its having fallen to the ground. -// -// var1 = unused -// var2 = unused -// -void A_Fall(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Fall", actor)) - return; -#endif - // actor is on ground, it can be walked over - actor->flags &= ~MF_SOLID; - - // fall through the floor - actor->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; - - // So change this if corpse objects - // are meant to be obstacles. -} - -#define LIVESBOXDISPLAYPLAYER // Use displayplayer instead of closest player - -// Function: A_1upThinker -// -// Description: Used by the 1up box to show the player's face. -// -// var1 = unused -// var2 = unused -// -void A_1upThinker(mobj_t *actor) -{ - INT32 i; - fixed_t dist = INT32_MAX; - fixed_t temp; - INT32 closestplayer = -1; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_1upThinker", actor)) - return; -#endif - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].bot || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - if ((netgame || multiplayer) && players[i].playerstate != PST_LIVE) - continue; - - temp = P_AproxDistance(players[i].mo->x-actor->x, players[i].mo->y-actor->y); - - if (temp < dist) - { - closestplayer = i; - dist = temp; - } - } - - if (closestplayer == -1 || skins[players[closestplayer].skin].sprites[SPR2_LIFE].numframes == 0) - { // Closest player not found (no players in game?? may be empty dedicated server!), or does not have correct sprite. - if (actor->tracer) { - P_RemoveMobj(actor->tracer); - actor->tracer = NULL; - } - return; - } - - // We're using the overlay, so use the overlay 1up box (no text) - actor->sprite = SPR_TV1P; - - if (!actor->tracer) - { - P_SetTarget(&actor->tracer, P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY)); - P_SetTarget(&actor->tracer->target, actor); - actor->tracer->skin = &skins[players[closestplayer].skin]; // required here to prevent spr2 default showing stand for a single frame - P_SetMobjState(actor->tracer, actor->info->seestate); - - // The overlay is going to be one tic early turning off and on - // because it's going to get its thinker run the frame we spawned it. - // So make it take one tic longer if it just spawned. - ++actor->tracer->tics; - } - - actor->tracer->color = players[closestplayer].mo->color; - actor->tracer->skin = &skins[players[closestplayer].skin]; -} - -// Function: A_MonitorPop -// -// Description: Used by monitors when they explode. -// -// var1 = unused -// var2 = unused -// -void A_MonitorPop(mobj_t *actor) -{ - mobjtype_t item = 0; - mobj_t *newmobj; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_MonitorPop", actor)) - return; -#endif - - // Spawn the "pop" explosion. - if (actor->info->deathsound) - S_StartSound(actor, actor->info->deathsound); - P_SpawnMobjFromMobj(actor, 0, 0, actor->height/4, MT_EXPLODE); - - // We're dead now. De-solidify. - actor->health = 0; - P_UnsetThingPosition(actor); - actor->flags &= ~MF_SOLID; - actor->flags |= MF_NOCLIP; - P_SetThingPosition(actor); - - if (actor->info->damage == MT_UNKNOWN) - { - // MT_UNKNOWN is random. Because it's unknown to us... get it? - item = P_DoRandomBoxChances(); - - if (item == MT_NULL) - { - CONS_Alert(CONS_WARNING, M_GetText("All monitors turned off.\n")); - return; - } - } - else - item = actor->info->damage; - - if (item == 0) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup item not defined in 'damage' field for A_MonitorPop\n"); - return; - } - - newmobj = P_SpawnMobjFromMobj(actor, 0, 0, 13*FRACUNIT, item); - P_SetTarget(&newmobj->target, actor->target); // Transfer target - - if (item == MT_1UP_ICON) - { - if (actor->tracer) // Remove the old lives icon. - P_RemoveMobj(actor->tracer); - - if (!newmobj->target - || !newmobj->target->player - || !newmobj->target->skin - || ((skin_t *)newmobj->target->skin)->sprites[SPR2_LIFE].numframes == 0) - {} // No lives icon for this player, use the default. - else - { // Spawn the lives icon. - mobj_t *livesico = P_SpawnMobjFromMobj(newmobj, 0, 0, 0, MT_OVERLAY); - P_SetTarget(&livesico->target, newmobj); - P_SetTarget(&newmobj->tracer, livesico); - - livesico->color = newmobj->target->player->mo->color; - livesico->skin = &skins[newmobj->target->player->skin]; - P_SetMobjState(livesico, newmobj->info->seestate); - - // We're using the overlay, so use the overlay 1up sprite (no text) - newmobj->sprite = SPR_TV1P; - } - } - - // Run a linedef executor immediately upon popping - // You may want to delay your effects by 18 tics to sync with the reward giving - if (actor->spawnpoint && (actor->spawnpoint->options & MTF_EXTRA) && (actor->spawnpoint->angle & 16384)) - P_LinedefExecute((actor->spawnpoint->angle & 16383), actor->target, NULL); -} - -// Function: A_GoldMonitorPop -// -// Description: Used by repeating monitors when they turn off. They don't really pop, but, you know... -// -// var1 = unused -// var2 = unused -// -void A_GoldMonitorPop(mobj_t *actor) -{ - mobjtype_t item = 0; - mobj_t *newmobj; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_GoldMonitorPop", actor)) - return; -#endif - - // Don't spawn the "pop" explosion, because the monitor isn't broken. - if (actor->info->deathsound) - S_StartSound(actor, actor->info->deathsound); - //P_SpawnMobjFromMobj(actor, 0, 0, actor.height/4, MT_EXPLODE); - - // Remove our flags for a bit. - // Players can now stand on top of us. - P_UnsetThingPosition(actor); - actor->flags &= ~(MF_MONITOR|MF_SHOOTABLE); - P_SetThingPosition(actor); - - // Don't count this box in statistics. Sorry. - if (actor->target && actor->target->player) - --actor->target->player->numboxes; - actor->fuse = 0; // Don't let the monitor code screw us up. - - if (actor->info->damage == MT_UNKNOWN) - { - // MT_UNKNOWN is random. Because it's unknown to us... get it? - item = P_DoRandomBoxChances(); - - if (item == MT_NULL) - { - CONS_Alert(CONS_WARNING, M_GetText("All monitors turned off.\n")); - return; - } - } - else - item = actor->info->damage; - - if (item == 0) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup item not defined in 'damage' field for A_GoldMonitorPop\n"); - return; - } - - // Note: the icon spawns 1 fracunit higher - newmobj = P_SpawnMobjFromMobj(actor, 0, 0, 14*FRACUNIT, item); - P_SetTarget(&newmobj->target, actor->target); // Transfer target - - if (item == MT_1UP_ICON) - { - if (actor->tracer) // Remove the old lives icon. - P_RemoveMobj(actor->tracer); - - if (!newmobj->target - || !newmobj->target->player - || !newmobj->target->skin - || ((skin_t *)newmobj->target->skin)->sprites[SPR2_LIFE].numframes == 0) - {} // No lives icon for this player, use the default. - else - { // Spawn the lives icon. - mobj_t *livesico = P_SpawnMobjFromMobj(newmobj, 0, 0, 0, MT_OVERLAY); - P_SetTarget(&livesico->target, newmobj); - P_SetTarget(&newmobj->tracer, livesico); - - livesico->color = newmobj->target->player->mo->color; - livesico->skin = &skins[newmobj->target->player->skin]; - P_SetMobjState(livesico, newmobj->info->seestate); - - // We're using the overlay, so use the overlay 1up sprite (no text) - newmobj->sprite = SPR_TV1P; - } - } -} - -// Function: A_GoldMonitorRestore -// -// Description: A repeating monitor is coming back to life. Reset monitor flags, etc. -// -// var1 = unused -// var2 = unused -// -void A_GoldMonitorRestore(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_GoldMonitorRestore", actor)) - return; -#endif - - actor->flags |= MF_MONITOR|MF_SHOOTABLE; - actor->health = 1; // Just in case. -} - -// Function: A_GoldMonitorSparkle -// -// Description: Spawns the little sparkly effect around big monitors. Looks pretty, doesn't it? -// -// var1 = unused -// var2 = unused -// -void A_GoldMonitorSparkle(mobj_t *actor) -{ - fixed_t i, ngangle, xofs, yofs; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_GoldMonitorSparkle", actor)) - return; -#endif - - ngangle = FixedAngle(((leveltime * 21) % 360) << FRACBITS); - xofs = FINESINE((ngangle>>ANGLETOFINESHIFT) & FINEMASK) * (actor->radius>>FRACBITS); - yofs = FINECOSINE((ngangle>>ANGLETOFINESHIFT) & FINEMASK) * (actor->radius>>FRACBITS); - - for (i = FRACUNIT*2; i <= FRACUNIT*3; i += FRACUNIT/2) - P_SetObjectMomZ(P_SpawnMobjFromMobj(actor, xofs, yofs, 0, MT_BOXSPARKLE), i, false); -} - -// Function: A_Explode -// -// Description: Explodes an object, doing damage to any objects nearby. The target is used as the cause of the explosion. Damage value is used as explosion range. -// -// var1 = damagetype -// var2 = unused -// -void A_Explode(mobj_t *actor) -{ - INT32 locvar1 = var1; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Explode", actor)) - return; -#endif - P_RadiusAttack(actor, actor->target, actor->info->damage, locvar1); -} - -// Function: A_BossDeath -// -// Description: Possibly trigger special effects when boss dies. -// -// var1 = unused -// var2 = unused -// -void A_BossDeath(mobj_t *mo) -{ - thinker_t *th; - mobj_t *mo2; - line_t junk; - INT32 i; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_BossDeath", mo)) - return; -#endif - - P_LinedefExecute(LE_BOSSDEAD, mo, NULL); - mo->health = 0; - - // Boss is dead (but not necessarily fleeing...) - // Lua may use this to ignore bosses after they start fleeing - mo->flags2 |= MF2_BOSSDEAD; - - // make sure there is a player alive for victory - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && ((players[i].mo && players[i].mo->health) - || ((netgame || multiplayer) && (players[i].lives || players[i].continues)))) - break; - - if (i == MAXPLAYERS) - return; // no one left alive, so do not end game - - // scan the remaining thinkers to see - // if all bosses are dead - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - if (mo2 != mo && (mo2->flags & MF_BOSS) && mo2->health > 0) - goto bossjustdie; // other boss not dead - just go straight to dying! - } - - // victory! - P_LinedefExecute(LE_ALLBOSSESDEAD, mo, NULL); - if (mo->flags2 & MF2_BOSSNOTRAP) - { - for (i = 0; i < MAXPLAYERS; i++) - P_DoPlayerExit(&players[i]); - } - else - { - // Bring the egg trap up to the surface - junk.tag = 680; - EV_DoElevator(&junk, elevateHighest, false); - junk.tag = 681; - EV_DoElevator(&junk, elevateUp, false); - junk.tag = 682; - EV_DoElevator(&junk, elevateHighest, false); - } - -bossjustdie: -#ifdef HAVE_BLUA - if (LUAh_BossDeath(mo)) - return; - else if (P_MobjWasRemoved(mo)) - return; -#endif - if (mo->type == MT_BLACKEGGMAN || mo->type == MT_CYBRAKDEMON) - { - mo->flags |= MF_NOCLIP; - mo->flags &= ~MF_SPECIAL; - - S_StartSound(NULL, sfx_befall); - } - else if (mo->type == MT_KOOPA) - { - junk.tag = 650; - EV_DoCeiling(&junk, raiseToHighest); - return; - } - else // eggmobiles - { - // Stop exploding and prepare to run. - P_SetMobjState(mo, mo->info->xdeathstate); - if (P_MobjWasRemoved(mo)) - return; - - P_SetTarget(&mo->target, NULL); - - // Flee! Flee! Find a point to escape to! If none, just shoot upward! - // scan the thinkers to find the runaway point - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type == MT_BOSSFLYPOINT) - { - // If this one's closer then the last one, go for it. - if (!mo->target || - P_AproxDistance(P_AproxDistance(mo->x - mo2->x, mo->y - mo2->y), mo->z - mo2->z) < - P_AproxDistance(P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y), mo->z - mo->target->z)) - P_SetTarget(&mo->target, mo2); - // Otherwise... Don't! - } - } - - mo->flags |= MF_NOGRAVITY|MF_NOCLIP; - mo->flags |= MF_NOCLIPHEIGHT; - - if (mo->target) - { - mo->angle = R_PointToAngle2(mo->x, mo->y, mo->target->x, mo->target->y); - mo->flags2 |= MF2_BOSSFLEE; - mo->momz = FixedMul(FixedDiv(mo->target->z - mo->z, P_AproxDistance(mo->x-mo->target->x,mo->y-mo->target->y)), FixedMul(2*FRACUNIT, mo->scale)); - } - else - mo->momz = FixedMul(2*FRACUNIT, mo->scale); - } - - if (mo->type == MT_EGGMOBILE2) - { - mo2 = P_SpawnMobj(mo->x + P_ReturnThrustX(mo, mo->angle - ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), - mo->y + P_ReturnThrustY(mo, mo->angle - ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), - mo->z + mo->height/2 + ((mo->eflags & MFE_VERTICALFLIP)? FixedMul(8*FRACUNIT, mo->scale)-mobjinfo[MT_BOSSTANK1].height : -FixedMul(8*FRACUNIT, mo->scale)), MT_BOSSTANK1); // Right tank - mo2->angle = mo->angle; - mo2->destscale = mo->scale; - P_SetScale(mo2, mo2->destscale); - if (mo->eflags & MFE_VERTICALFLIP) - { - mo2->eflags |= MFE_VERTICALFLIP; - mo2->flags2 |= MF2_OBJECTFLIP; - } - P_InstaThrust(mo2, mo2->angle - ANGLE_90, FixedMul(4*FRACUNIT, mo2->scale)); - P_SetObjectMomZ(mo2, 4*FRACUNIT, false); - - mo2 = P_SpawnMobj(mo->x + P_ReturnThrustX(mo, mo->angle + ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), - mo->y + P_ReturnThrustY(mo, mo->angle + ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), - mo->z + mo->height/2 + ((mo->eflags & MFE_VERTICALFLIP)? FixedMul(8*FRACUNIT, mo->scale)-mobjinfo[MT_BOSSTANK2].height : -FixedMul(8*FRACUNIT, mo->scale)), MT_BOSSTANK2); // Left tank - mo2->angle = mo->angle; - mo2->destscale = mo->scale; - P_SetScale(mo2, mo2->destscale); - if (mo->eflags & MFE_VERTICALFLIP) - { - mo2->eflags |= MFE_VERTICALFLIP; - mo2->flags2 |= MF2_OBJECTFLIP; - } - P_InstaThrust(mo2, mo2->angle + ANGLE_90, FixedMul(4*FRACUNIT, mo2->scale)); - P_SetObjectMomZ(mo2, 4*FRACUNIT, false); - - mo2 = P_SpawnMobj(mo->x, mo->y, - mo->z + ((mo->eflags & MFE_VERTICALFLIP)? mobjinfo[MT_BOSSSPIGOT].height-FixedMul(32*FRACUNIT,mo->scale): mo->height + FixedMul(32*FRACUNIT, mo->scale)), MT_BOSSSPIGOT); - mo2->angle = mo->angle; - mo2->destscale = mo->scale; - P_SetScale(mo2, mo2->destscale); - if (mo->eflags & MFE_VERTICALFLIP) - { - mo2->eflags |= MFE_VERTICALFLIP; - mo2->flags2 |= MF2_OBJECTFLIP; - } - P_SetObjectMomZ(mo2, 4*FRACUNIT, false); - return; - } -} - -// Function: A_CustomPower -// -// Description: Provides a custom powerup. Target (must be a player) is awarded the powerup. Reactiontime of the object is used as an index to the powers array. -// -// var1 = Power index # -// var2 = Power duration in tics -// -void A_CustomPower(mobj_t *actor) -{ - player_t *player; - INT32 locvar1 = var1; - INT32 locvar2 = var2; - boolean spawnshield = false; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CustomPower", actor)) - return; -#endif - if (!actor->target || !actor->target->player) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); - return; - } - - if (locvar1 >= NUMPOWERS) - { - CONS_Debug(DBG_GAMELOGIC, "Power #%d out of range!\n", locvar1); - return; - } - - player = actor->target->player; - - if (locvar1 == pw_shield && player->powers[pw_shield] != locvar2) - spawnshield = true; - - player->powers[locvar1] = (UINT16)locvar2; - if (actor->info->seesound) - S_StartSound(player->mo, actor->info->seesound); - - if (spawnshield) //workaround for a bug - P_SpawnShieldOrb(player); -} - -// Function: A_GiveWeapon -// -// Description: Gives the player the specified weapon panels. -// -// var1 = Weapon index # -// var2 = unused -// -void A_GiveWeapon(mobj_t *actor) -{ - player_t *player; - INT32 locvar1 = var1; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_GiveWeapon", actor)) - return; -#endif - if (!actor->target || !actor->target->player) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); - return; - } - - if (locvar1 >= 1<<(NUM_WEAPONS-1)) - { - CONS_Debug(DBG_GAMELOGIC, "Weapon #%d out of range!\n", locvar1); - return; - } - - player = actor->target->player; - - player->ringweapons |= locvar1; - if (actor->info->seesound) - S_StartSound(player->mo, actor->info->seesound); -} - -// Function: A_RingBox -// -// Description: Awards the player 10 rings. -// -// var1 = unused -// var2 = unused -// -void A_RingBox(mobj_t *actor) -{ - player_t *player; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_RingBox", actor)) - return; -#endif - if (!actor->target || !actor->target->player) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); - return; - } - - player = actor->target->player; - - P_GivePlayerRings(player, actor->info->reactiontime); - if (actor->info->seesound) - S_StartSound(player->mo, actor->info->seesound); -} - -// Function: A_Invincibility -// -// Description: Awards the player invincibility. -// -// var1 = unused -// var2 = unused -// -void A_Invincibility(mobj_t *actor) -{ - player_t *player; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Invincibility", actor)) - return; -#endif - if (!actor->target || !actor->target->player) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); - return; - } - - player = actor->target->player; - player->powers[pw_invulnerability] = invulntics + 1; - - if (P_IsLocalPlayer(player) && !player->powers[pw_super]) - { - S_StopMusic(); - if (mariomode) - G_GhostAddColor(GHC_INVINCIBLE); - strlcpy(S_sfx[sfx_None].caption, "Invincibility", 14); - S_StartCaption(sfx_None, -1, player->powers[pw_invulnerability]); - S_ChangeMusicInternal((mariomode) ? "_minv" : "_inv", false); - } -} - -// Function: A_SuperSneakers -// -// Description: Awards the player super sneakers. -// -// var1 = unused -// var2 = unused -// -void A_SuperSneakers(mobj_t *actor) -{ - player_t *player; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SuperSneakers", actor)) - return; -#endif - if (!actor->target || !actor->target->player) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); - return; - } - - player = actor->target->player; - - actor->target->player->powers[pw_sneakers] = sneakertics + 1; - - if (P_IsLocalPlayer(player) && !player->powers[pw_super]) - { - if (S_SpeedMusic(0.0f) && (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)) - S_SpeedMusic(1.4f); - else - { - S_StopMusic(); - S_ChangeMusicInternal("_shoes", false); - } - strlcpy(S_sfx[sfx_None].caption, "Speed shoes", 12); - S_StartCaption(sfx_None, -1, player->powers[pw_sneakers]); - } -} - -// Function: A_AwardScore -// -// Description: Adds a set amount of points to the player's score. -// -// var1 = unused -// var2 = unused -// -void A_AwardScore(mobj_t *actor) -{ - player_t *player; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_AwardScore", actor)) - return; -#endif - if (!actor->target || !actor->target->player) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); - return; - } - - player = actor->target->player; - - P_AddPlayerScore(player, actor->info->reactiontime); - if (actor->info->seesound) - S_StartSound(player->mo, actor->info->seesound); -} - -// Function: A_ExtraLife -// -// Description: Awards the player an extra life. -// -// var1 = unused -// var2 = unused -// -void A_ExtraLife(mobj_t *actor) -{ - player_t *player; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ExtraLife", actor)) - return; -#endif - if (!actor->target || !actor->target->player) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); - return; - } - - player = actor->target->player; - - if (actor->type == MT_1UP_ICON && actor->tracer) - { - // We're using the overlay, so use the overlay 1up sprite (no text) - actor->sprite = SPR_TV1P; - } - - if (ultimatemode) //I don't THINK so! - { - S_StartSound(player->mo, sfx_lose); - return; - } - - P_GiveCoopLives(player, 1, true); -} - -// Function: A_GiveShield -// -// Description: Awards the player a specified shield. -// -// var1 = Shield type (make with SH_ constants) -// var2 = unused -// -void A_GiveShield(mobj_t *actor) -{ - player_t *player; - UINT16 locvar1 = var1; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_GiveShield", actor)) - return; -#endif - if (!actor->target || !actor->target->player) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); - return; - } - - player = actor->target->player; - - P_SwitchShield(player, locvar1); - S_StartSound(player->mo, actor->info->seesound); -} - -// Function: A_GravityBox -// -// Description: Awards the player gravity boots. -// -// var1 = unused -// var2 = unused -// -void A_GravityBox(mobj_t *actor) -{ - player_t *player; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_GravityBox", actor)) - return; -#endif - if (!actor->target || !actor->target->player) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); - return; - } - - player = actor->target->player; - - S_StartSound(player, actor->info->activesound); - - player->powers[pw_gravityboots] = (UINT16)(actor->info->reactiontime + 1); -} - -// Function: A_ScoreRise -// -// Description: Makes the little score logos rise. Speed value sets speed. -// -// var1 = unused -// var2 = unused -// -void A_ScoreRise(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ScoreRise", actor)) - return; -#endif - // make logo rise! - P_SetObjectMomZ(actor, actor->info->speed, false); -} - -// Function: A_BunnyHop -// -// Description: Makes object hop like a bunny. -// -// var1 = jump strength -// var2 = horizontal movement -// -void A_BunnyHop(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_BunnyHop", actor)) - return; -#endif - if (((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz) - || (!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)) - { - P_SetObjectMomZ(actor, locvar1*FRACUNIT, false); - P_InstaThrust(actor, actor->angle, FixedMul(locvar2*FRACUNIT, actor->scale)); // Launch the hopping action! PHOOM!! - } -} - -// Function: A_BubbleSpawn -// -// Description: Spawns a randomly sized bubble from the object's location. Only works underwater. -// -// var1 = Distance to look for players. If no player is in this distance, bubbles aren't spawned. (Ambush overrides) -// var2 = unused -// -void A_BubbleSpawn(mobj_t *actor) -{ - INT32 i, locvar1 = var1; - UINT8 prandom; - mobj_t *bubble = NULL; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_BubbleSpawn", actor)) - return; -#endif - if (!(actor->eflags & MFE_UNDERWATER)) - { - // Don't draw or spawn bubbles above water - actor->flags2 |= MF2_DONTDRAW; - return; - } - actor->flags2 &= ~MF2_DONTDRAW; - - if (!(actor->flags2 & MF2_AMBUSH)) - { - // Quick! Look through players! - // Don't spawn bubbles unless a player is relatively close by (var1). - for (i = 0; i < MAXPLAYERS; ++i) - if (playeringame[i] && players[i].mo - && P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (locvar1<x, actor->y, actor->z + (actor->height / 2), MT_EXTRALARGEBUBBLE); - else if (prandom > 128) - bubble = P_SpawnMobj(actor->x, actor->y, actor->z + (actor->height / 2), MT_SMALLBUBBLE); - else if (prandom < 128 && prandom > 96) - bubble = P_SpawnMobj(actor->x, actor->y, actor->z + (actor->height / 2), MT_MEDIUMBUBBLE); - - if (bubble) - { - bubble->destscale = actor->scale; - P_SetScale(bubble, actor->scale); - } -} - -// Function: A_FanBubbleSpawn -// -// Description: Spawns bubbles from fans, if they're underwater. -// -// var1 = Distance to look for players. If no player is in this distance, bubbles aren't spawned. (Ambush overrides) -// var2 = unused -// -void A_FanBubbleSpawn(mobj_t *actor) -{ - INT32 i, locvar1 = var1; - UINT8 prandom; - mobj_t *bubble = NULL; - fixed_t hz = actor->z + (4*actor->height)/5; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FanBubbleSpawn", actor)) - return; -#endif - if (!(actor->eflags & MFE_UNDERWATER)) - return; - - if (!(actor->flags2 & MF2_AMBUSH)) - { - // Quick! Look through players! - // Don't spawn bubbles unless a player is relatively close by (var2). - for (i = 0; i < MAXPLAYERS; ++i) - if (playeringame[i] && players[i].mo - && P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (locvar1<x, actor->y, hz, MT_SMALLBUBBLE); - else if ((prandom & 0xF0) == 0xF0) - bubble = P_SpawnMobj(actor->x, actor->y, hz, MT_MEDIUMBUBBLE); - - if (bubble) - { - bubble->destscale = actor->scale; - P_SetScale(bubble, actor->scale); - } -} - -// Function: A_BubbleRise -// -// Description: Raises a bubble -// -// var1: -// 0 = Bend around the water abit, looking more realistic -// 1 = Rise straight up -// var2 = rising speed -// -void A_BubbleRise(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_BubbleRise", actor)) - return; -#endif - if (actor->type == MT_EXTRALARGEBUBBLE) - P_SetObjectMomZ(actor, FixedDiv(6*FRACUNIT,5*FRACUNIT), false); // make bubbles rise! - else - { - P_SetObjectMomZ(actor, locvar2, true); // make bubbles rise! - - // Move around slightly to make it look like it's bending around the water - if (!locvar1) - { - UINT8 prandom = P_RandomByte(); - if (!(prandom & 0x7)) // *****000 - { - P_InstaThrust(actor, prandom & 0x70 ? actor->angle + ANGLE_90 : actor->angle, - FixedMul(prandom & 0xF0 ? FRACUNIT/2 : -FRACUNIT/2, actor->scale)); - } - else if (!(prandom & 0x38)) // **000*** - { - P_InstaThrust(actor, prandom & 0x70 ? actor->angle - ANGLE_90 : actor->angle - ANGLE_180, - FixedMul(prandom & 0xF0 ? FRACUNIT/2 : -FRACUNIT/2, actor->scale)); - } - } - } -} - -// Function: A_BubbleCheck -// -// Description: Checks if a bubble should be drawn or not. Bubbles are not drawn above water. -// -// var1 = unused -// var2 = unused -// -void A_BubbleCheck(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_BubbleCheck", actor)) - return; -#endif - if (actor->eflags & MFE_UNDERWATER) - actor->flags2 &= ~MF2_DONTDRAW; // underwater so draw - else - actor->flags2 |= MF2_DONTDRAW; // above water so don't draw -} - -// Function: A_AttractChase -// -// Description: Makes a ring chase after a player with a ring shield and also causes spilled rings to flicker. -// -// var1 = unused -// var2 = unused -// -void A_AttractChase(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_AttractChase", actor)) - return; -#endif - if (actor->flags2 & MF2_NIGHTSPULL || !actor->health) - return; - - // spilled rings flicker before disappearing - if (leveltime & 1 && actor->type == (mobjtype_t)actor->info->reactiontime && actor->fuse && actor->fuse < 2*TICRATE) - actor->flags2 |= MF2_DONTDRAW; - else - actor->flags2 &= ~MF2_DONTDRAW; - - // Turn flingrings back into regular rings if attracted. - if (actor->tracer && actor->tracer->player - && !(actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC) && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime) - { - mobj_t *newring; - newring = P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->reactiontime); - newring->momx = actor->momx; - newring->momy = actor->momy; - newring->momz = actor->momz; - P_RemoveMobj(actor); - return; - } - - P_LookForShield(actor); // Go find 'em, boy! - - if (!actor->tracer - || !actor->tracer->player - || !actor->tracer->health - || !P_CheckSight(actor, actor->tracer)) // You have to be able to SEE it...sorta - { - // Lost attracted rings don't through walls anymore. - actor->flags &= ~MF_NOCLIP; - P_SetTarget(&actor->tracer, NULL); - return; - } - - // If a FlingRing gets attracted by a shield, change it into a normal ring. - if (actor->type == (mobjtype_t)actor->info->reactiontime) - { - P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->painchance); - P_RemoveMobj(actor); - return; - } - - // Keep stuff from going down inside floors and junk - actor->flags &= ~MF_NOCLIPHEIGHT; - - // Let attracted rings move through walls and such. - actor->flags |= MF_NOCLIP; - - P_Attract(actor, actor->tracer, false); -} - -// Function: A_DropMine -// -// Description: Drops a mine. Raisestate specifies the object # to use for the mine. -// -// var1 = height offset -// var2: -// lower 16 bits = proximity check distance (0 disables) -// upper 16 bits = 0 to check proximity with target, 1 for tracer -// -void A_DropMine(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - fixed_t z; - mobj_t *mine; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_DropMine", actor)) - return; -#endif - - if (locvar2 & 65535) - { - fixed_t dist; - mobj_t *target; - - if (locvar2 >> 16) - target = actor->tracer; - else - target = actor->target; - - if (!target) - return; - - dist = P_AproxDistance(actor->x-target->x, actor->y-target->y)>>FRACBITS; - - if (dist > FixedMul((locvar2 & 65535), actor->scale)) - return; - } - - if (actor->eflags & MFE_VERTICALFLIP) - z = actor->z + actor->height - mobjinfo[actor->info->raisestate].height - FixedMul((locvar1*FRACUNIT) - 12*FRACUNIT, actor->scale); - else - z = actor->z + FixedMul((locvar1*FRACUNIT) - 12*FRACUNIT, actor->scale); - - // Use raisestate instead of MT_MINE - mine = P_SpawnMobj(actor->x, actor->y, z, (mobjtype_t)actor->info->raisestate); - if (actor->eflags & MFE_VERTICALFLIP) - mine->eflags |= MFE_VERTICALFLIP; - mine->momz = actor->momz + actor->pmomz; - - S_StartSound(actor, actor->info->attacksound); -} - -// Function: A_FishJump -// -// Description: Makes the stupid harmless fish in Greenflower Zone jump. -// -// var1 = Jump strength (in FRACBITS), if specified. Otherwise, uses the angle value. -// var2 = unused -// -void A_FishJump(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FishJump", actor)) - return; -#endif - - if (locvar2) - { - fixed_t rad = actor->radius>>FRACBITS; - P_SpawnMobjFromMobj(actor, P_RandomRange(rad, -rad)<z <= actor->floorz) || (actor->z <= actor->watertop - FixedMul((64 << FRACBITS), actor->scale))) - { - fixed_t jumpval; - - if (locvar1) - jumpval = var1; - else - jumpval = FixedMul(AngleFixed(actor->angle)/4, actor->scale); - - if (!jumpval) jumpval = FixedMul(44*(FRACUNIT/4), actor->scale); - actor->momz = jumpval; - P_SetMobjStateNF(actor, actor->info->seestate); - } - - if (actor->momz < 0 - && (actor->state < &states[actor->info->meleestate] || actor->state > &states[actor->info->xdeathstate])) - P_SetMobjStateNF(actor, actor->info->meleestate); -} - -// Function:A_ThrownRing -// -// Description: Thinker for thrown rings/sparkle trail -// -// var1 = unused -// var2 = unused -// -void A_ThrownRing(mobj_t *actor) -{ - INT32 c = 0; - INT32 stop; - player_t *player; - fixed_t dist; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ThrownRing", actor)) - return; -#endif - - if (leveltime % (TICRATE/7) == 0) - { - mobj_t *ring = NULL; - - if (actor->flags2 & MF2_EXPLOSION) - { - if (actor->momx != 0 || actor->momy != 0) - ring = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMOKE); - // Else spawn nothing because it's totally stationary and constantly smoking would be weird -SH - } - else if (actor->flags2 & MF2_AUTOMATIC) - ring = P_SpawnGhostMobj(actor); - else if (!(actor->flags2 & MF2_RAILRING)) - ring = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SPARK); - - if (ring) - { - /* - P_SetTarget(&ring->target, actor); - ring->color = actor->color; //copy color - */ - ring->destscale = actor->scale; - P_SetScale(ring, actor->scale); - } - } - - // A_GrenadeRing beeping lives once moooooore -SH - if (actor->type == MT_THROWNGRENADE && actor->fuse % TICRATE == 0) - S_StartSound(actor, actor->info->attacksound); - - // decrement bounce ring time - if (actor->flags2 & MF2_BOUNCERING) - { - if (actor->fuse) - actor->fuse--; - else { - P_RemoveMobj(actor); - return; - } - } - - // spilled rings (and thrown bounce) flicker before disappearing - if (leveltime & 1 && actor->fuse > 0 && actor->fuse < 2*TICRATE - && actor->type != MT_THROWNGRENADE) - actor->flags2 |= MF2_DONTDRAW; - else - actor->flags2 &= ~MF2_DONTDRAW; - - if (actor->tracer && actor->tracer->health <= 0) - P_SetTarget(&actor->tracer, NULL); - - // Updated homing ring special capability - // If you have a ring shield, all rings thrown - // at you become homing (except rail)! - if (actor->tracer) - { - // A non-homing ring getting attracted by a - // magnetic player. If he gets too far away, make - // sure to stop the attraction! - if ((!actor->tracer->health) || (actor->tracer->player && (actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC) - && P_AproxDistance(P_AproxDistance(actor->tracer->x-actor->x, - actor->tracer->y-actor->y), actor->tracer->z-actor->z) > FixedMul(RING_DIST/4, actor->tracer->scale))) - { - P_SetTarget(&actor->tracer, NULL); - } - - if (actor->tracer && (actor->tracer->health) - && (actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC))// Already found someone to follow. - { - const INT32 temp = actor->threshold; - actor->threshold = 32000; - P_HomingAttack(actor, actor->tracer); - actor->threshold = temp; - return; - } - } - - // first time init, this allow minimum lastlook changes - if (actor->lastlook < 0) - actor->lastlook = P_RandomByte(); - - actor->lastlook %= MAXPLAYERS; - - stop = (actor->lastlook - 1) & PLAYERSMASK; - - for (; ; actor->lastlook = (actor->lastlook + 1) & PLAYERSMASK) - { - // done looking - if (actor->lastlook == stop) - return; - - if (!playeringame[actor->lastlook]) - continue; - - if (c++ == 2) - return; - - player = &players[actor->lastlook]; - - if (!player->mo) - continue; - - if (player->mo->health <= 0) - continue; // dead - - if ((netgame || multiplayer) && player->spectator) - continue; // spectator - - if (actor->target && actor->target->player) - { - if (player->mo == actor->target) - continue; - - // Don't home in on teammates. - if (gametype == GT_CTF - && actor->target->player->ctfteam == player->ctfteam) - continue; - } - - dist = P_AproxDistance(P_AproxDistance(player->mo->x-actor->x, - player->mo->y-actor->y), player->mo->z-actor->z); - - // check distance - if (actor->flags2 & MF2_RAILRING) - { - if (dist > FixedMul(RING_DIST/2, player->mo->scale)) - continue; - } - else if (dist > FixedMul(RING_DIST, player->mo->scale)) - continue; - - // do this after distance check because it's more computationally expensive - if (!P_CheckSight(actor, player->mo)) - continue; // out of sight - - if ((player->powers[pw_shield] & SH_PROTECTELECTRIC) - && dist < FixedMul(RING_DIST/4, player->mo->scale)) - P_SetTarget(&actor->tracer, player->mo); - return; - } - - return; -} - -// Function: A_SetSolidSteam -// -// Description: Makes steam solid so it collides with the player to boost them. -// -// var1 = unused -// var2 = unused -// -void A_SetSolidSteam(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SetSolidSteam", actor)) - return; -#endif - actor->flags &= ~MF_NOCLIP; - actor->flags |= MF_SOLID; - if (!(actor->flags2 & MF2_AMBUSH)) - { - if (P_RandomChance(FRACUNIT/8)) - { - if (actor->info->deathsound) - S_StartSound(actor, actor->info->deathsound); // Hiss! - } - else - { - if (actor->info->painsound) - S_StartSound(actor, actor->info->painsound); - } - } - - P_SetObjectMomZ (actor, 1, true); -} - -// Function: A_UnsetSolidSteam -// -// Description: Makes an object non-solid and also noclip. Used by the steam. -// -// var1 = unused -// var2 = unused -// -void A_UnsetSolidSteam(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_UnsetSolidSteam", actor)) - return; -#endif - actor->flags &= ~MF_SOLID; - actor->flags |= MF_NOCLIP; -} - -// Function: A_SignPlayer -// -// Description: Changes the state of a level end sign to reflect the player that hit it. -// -// var1 = unused -// var2 = unused -// -void A_SignPlayer(mobj_t *actor) -{ - mobj_t *ov; - skin_t *skin; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SignPlayer", actor)) - return; -#endif - if (!actor->target) - return; - - if (!actor->target->player) - return; - - skin = &skins[actor->target->player->skin]; - - if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor? - { - actor->color = skin->prefoppositecolor; - /* - If you're here from the comment above Color_Opposite, - the following line is the one which is dependent on the - array being symmetrical. It gets the opposite of the - opposite of your desired colour just so it can get the - brightness frame for the End Sign. It's not a great - design choice, but it's constant time array access and - the idea that the colours should be OPPOSITES is kind - of in the name. If you have a better idea, feel free - to let me know. ~toast 2016/07/20 - */ - actor->frame += (15 - Color_Opposite[(Color_Opposite[(skin->prefoppositecolor - 1)*2] - 1)*2 + 1]); - } - else if (actor->target->player->skincolor) // Set the sign to be an appropriate background color for this player's skincolor. - { - actor->color = Color_Opposite[(actor->target->player->skincolor - 1)*2]; - actor->frame += (15 - Color_Opposite[(actor->target->player->skincolor - 1)*2 + 1]); - } - - if (skin->sprites[SPR2_SIGN].numframes) - { - // spawn an overlay of the player's face. - ov = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY); - P_SetTarget(&ov->target, actor); - ov->color = actor->target->player->skincolor; - ov->skin = skin; - P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN - } -} - -// Function: A_OverlayThink -// -// Description: Moves the overlay to the position of its target. -// -// var1 = unused -// var2 = invert, z offset -// -void A_OverlayThink(mobj_t *actor) -{ - fixed_t destx, desty; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_OverlayThink", actor)) - return; -#endif - if (!actor->target) - return; - - if (!splitscreen && rendermode != render_soft) - { - angle_t viewingangle; - - if (players[displayplayer].awayviewtics) - viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, players[displayplayer].awayviewmobj->x, players[displayplayer].awayviewmobj->y); - else if (!camera.chase && players[displayplayer].mo) - viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, players[displayplayer].mo->x, players[displayplayer].mo->y); - else - viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, camera.x, camera.y); - - destx = actor->target->x + P_ReturnThrustX(actor->target, viewingangle, FixedMul(FRACUNIT, actor->scale)); - desty = actor->target->y + P_ReturnThrustY(actor->target, viewingangle, FixedMul(FRACUNIT, actor->scale)); - } - else - { - destx = actor->target->x; - desty = actor->target->y; - } - P_UnsetThingPosition(actor); - actor->x = destx; - actor->y = desty; - P_SetThingPosition(actor); - if (actor->eflags & MFE_VERTICALFLIP) - actor->z = actor->target->z + actor->target->height - mobjinfo[actor->type].height - ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT; - else - actor->z = actor->target->z + ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT; - actor->angle = actor->target->angle; - actor->eflags = actor->target->eflags; - - actor->momx = actor->target->momx; - actor->momy = actor->target->momy; - actor->momz = actor->target->momz; // assume target has correct momz! Do not use P_SetObjectMomZ! -} - -// Function: A_JetChase -// -// Description: A_Chase for Jettysyns -// -// var1 = unused -// var2 = unused -// -void A_JetChase(mobj_t *actor) -{ - fixed_t thefloor; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_JetChase", actor)) - return; -#endif - - if (actor->flags2 & MF2_AMBUSH) - return; - - if (actor->z >= actor->waterbottom && actor->watertop > actor->floorz - && actor->z > actor->watertop - FixedMul(256*FRACUNIT, actor->scale)) - thefloor = actor->watertop; - else - thefloor = actor->floorz; - - if (actor->reactiontime) - actor->reactiontime--; - - if (P_RandomChance(FRACUNIT/32)) - { - actor->momx = actor->momx / 2; - actor->momy = actor->momy / 2; - actor->momz = actor->momz / 2; - } - - // Bounce if too close to floor or ceiling - - // ideal for Jetty-Syns above you on 3d floors - if (actor->momz && ((actor->z - FixedMul((32<scale)) < thefloor) && !((thefloor + FixedMul(32*FRACUNIT, actor->scale) + actor->height) > actor->ceilingz)) - actor->momz = -actor->momz/2; - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { - // look for a new target - if (P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - actor->momx = actor->momy = actor->momz = 0; - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - - // modify target threshold - if (actor->threshold) - { - if (!actor->target || actor->target->health <= 0) - actor->threshold = 0; - else - actor->threshold--; - } - - // turn towards movement direction if not there yet - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); - - if ((multiplayer || netgame) && !actor->threshold && (actor->target->health <= 0 || !P_CheckSight(actor, actor->target))) - if (P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - // If the player is over 3072 fracunits away, then look for another player - if (P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), - actor->target->z - actor->z) > FixedMul(3072*FRACUNIT, actor->scale) && P_LookForPlayers(actor, true, false, FixedMul(3072*FRACUNIT, actor->scale))) - { - return; // got a new target - } - - // chase towards player - if (ultimatemode) - P_Thrust(actor, actor->angle, FixedMul(actor->info->speed/2, actor->scale)); - else - P_Thrust(actor, actor->angle, FixedMul(actor->info->speed/4, actor->scale)); - - // must adjust height - if (ultimatemode) - { - if (actor->z < (actor->target->z + actor->target->height + FixedMul((64<scale))) - actor->momz += FixedMul(FRACUNIT/2, actor->scale); - else - actor->momz -= FixedMul(FRACUNIT/2, actor->scale); - } - else - { - if (actor->z < (actor->target->z + actor->target->height + FixedMul((32<scale))) - actor->momz += FixedMul(FRACUNIT/2, actor->scale); - else - actor->momz -= FixedMul(FRACUNIT/2, actor->scale); - } -} - -// Function: A_JetbThink -// -// Description: Thinker for Jetty-Syn bombers -// -// var1 = unused -// var2 = unused -// -void A_JetbThink(mobj_t *actor) -{ - sector_t *nextsector; - fixed_t thefloor; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_JetbThink", actor)) - return; -#endif - - if (actor->z >= actor->waterbottom && actor->watertop > actor->floorz - && actor->z > actor->watertop - FixedMul(256*FRACUNIT, actor->scale)) - thefloor = actor->watertop; - else - thefloor = actor->floorz; - - if (actor->target) - { - A_JetChase(actor); - // check for melee attack - if (actor->info->raisestate - && (actor->z > (actor->floorz + FixedMul((32<scale))) - && P_JetbCheckMeleeRange(actor) && !actor->reactiontime - && (actor->target->z >= actor->floorz)) - { - mobj_t *bomb; - if (actor->info->attacksound) - S_StartAttackSound(actor, actor->info->attacksound); - - // use raisestate instead of MT_MINE - bomb = P_SpawnMobj(actor->x, actor->y, actor->z - FixedMul((32<scale), (mobjtype_t)actor->info->raisestate); - - P_SetTarget(&bomb->target, actor); - bomb->destscale = actor->scale; - P_SetScale(bomb, actor->scale); - actor->reactiontime = TICRATE; // one second - S_StartSound(actor, actor->info->attacksound); - } - } - else if (((actor->z - FixedMul((32<scale)) < thefloor) && !((thefloor + FixedMul((32<scale) + actor->height) > actor->ceilingz)) - actor->z = thefloor+FixedMul((32<scale); - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { - // look for a new target - if (P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - - nextsector = R_PointInSubsector(actor->x + actor->momx, actor->y + actor->momy)->sector; - - // Move downwards or upwards to go through a passageway. - if (nextsector->ceilingheight < actor->z + actor->height) - actor->momz -= FixedMul(5*FRACUNIT, actor->scale); - else if (nextsector->floorheight > actor->z) - actor->momz += FixedMul(5*FRACUNIT, actor->scale); -} - -// Function: A_JetgShoot -// -// Description: Firing function for Jetty-Syn gunners. -// -// var1 = unused -// var2 = unused -// -void A_JetgShoot(mobj_t *actor) -{ - fixed_t dist; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_JetgShoot", actor)) - return; -#endif - - if (!actor->target) - return; - - if (actor->reactiontime) - return; - - dist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); - - if (dist > FixedMul(actor->info->painchance*FRACUNIT, actor->scale)) - return; - - if (dist < FixedMul(64*FRACUNIT, actor->scale)) - return; - - A_FaceTarget(actor); - P_SpawnMissile(actor, actor->target, (mobjtype_t)actor->info->raisestate); - - if (ultimatemode) - actor->reactiontime = actor->info->reactiontime*TICRATE; - else - actor->reactiontime = actor->info->reactiontime*TICRATE*2; - - if (actor->info->attacksound) - S_StartSound(actor, actor->info->attacksound); -} - -// Function: A_ShootBullet -// -// Description: Shoots a bullet. Raisestate defines object # to use as projectile. -// -// var1 = unused -// var2 = unused -// -void A_ShootBullet(mobj_t *actor) -{ - fixed_t dist; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ShootBullet", actor)) - return; -#endif - - if (!actor->target) - return; - - dist = P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), actor->target->z - actor->z); - - if (dist > FixedMul(actor->info->painchance*FRACUNIT, actor->scale)) - return; - - A_FaceTarget(actor); - P_SpawnMissile(actor, actor->target, (mobjtype_t)actor->info->raisestate); - - if (actor->info->attacksound) - S_StartSound(actor, actor->info->attacksound); -} - -// Function: A_MinusDigging -// -// Description: Minus digging in the ground. -// -// var1 = unused -// var2 = unused -// -void A_MinusDigging(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_MinusDigging", actor)) - return; -#endif - actor->flags &= ~MF_SPECIAL; - actor->flags &= ~MF_SHOOTABLE; - - if (!actor->target) - { - A_Look(actor); - return; - } - - if (actor->reactiontime) - { - actor->reactiontime--; - return; - } - - // Dirt trail - P_SpawnGhostMobj(actor); - - actor->flags |= MF_NOCLIPTHING; - var1 = 3; - A_Chase(actor); - actor->flags &= ~MF_NOCLIPTHING; - - // Play digging sound - if (!(leveltime & 15)) - S_StartSound(actor, actor->info->activesound); - - // If we're close enough to our target, pop out of the ground - if (P_AproxDistance(actor->target->x-actor->x, actor->target->y-actor->y) < actor->radius - && abs(actor->target->z - actor->z) < 2*actor->height) - P_SetMobjState(actor, actor->info->missilestate); - - // Snap to ground - if (actor->eflags & MFE_VERTICALFLIP) - actor->z = actor->ceilingz - actor->height; - else - actor->z = actor->floorz; -} - -// Function: A_MinusPopup -// -// Description: Minus popping out of the ground. -// -// var1 = unused -// var2 = unused -// -void A_MinusPopup(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_MinusPopup", actor)) - return; -#endif - P_SetObjectMomZ(actor, 10*FRACUNIT, false); - - actor->flags |= MF_SPECIAL; - actor->flags |= MF_SHOOTABLE; - - // Sound for busting out of the ground. - S_StartSound(actor, actor->info->attacksound); -} - -// Function: A_MinusCheck -// -// Description: If the minus hits the floor, dig back into the ground. -// -// var1 = unused -// var2 = unused -// -void A_MinusCheck(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_MinusCheck", actor)) - return; -#endif - if ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) - || ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz)) - { - actor->flags &= ~MF_SPECIAL; - actor->flags &= ~MF_SHOOTABLE; - actor->reactiontime = TICRATE; - P_SetMobjState(actor, actor->info->seestate); - return; - } - - // 'Falling' animation - if (P_MobjFlip(actor)*actor->momz < 0 && actor->state < &states[actor->info->meleestate]) - P_SetMobjState(actor, actor->info->meleestate); -} - -// Function: A_ChickenCheck -// -// Description: Resets the chicken once it hits the floor again. -// -// var1 = unused -// var2 = unused -// -void A_ChickenCheck(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ChickenCheck", actor)) - return; -#endif - if ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) - || (actor->eflags & MFE_VERTICALFLIP && actor->z + actor->height >= actor->ceilingz)) - { - if (!(actor->momx || actor->momy || actor->momz) - && actor->state > &states[actor->info->seestate]) - { - A_Chase(actor); - P_SetMobjState(actor, actor->info->seestate); - } - - actor->momx >>= 2; - actor->momy >>= 2; - } -} - -// Function: A_JetgThink -// -// Description: Thinker for Jetty-Syn Gunners -// -// var1 = unused -// var2 = unused -// -void A_JetgThink(mobj_t *actor) -{ - sector_t *nextsector; - - fixed_t thefloor; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_JetgThink", actor)) - return; -#endif - - if (actor->z >= actor->waterbottom && actor->watertop > actor->floorz - && actor->z > actor->watertop - FixedMul(256*FRACUNIT, actor->scale)) - thefloor = actor->watertop; - else - thefloor = actor->floorz; - - if (actor->target) - { - if (P_RandomChance(FRACUNIT/8) && !actor->reactiontime) - P_SetMobjState(actor, actor->info->missilestate); - else - A_JetChase (actor); - } - else if (actor->z - FixedMul((32<scale) < thefloor && !(thefloor + FixedMul((32<scale) - + actor->height > actor->ceilingz)) - { - actor->z = thefloor + FixedMul((32<scale); - } - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { - // look for a new target - if (P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - - nextsector = R_PointInSubsector(actor->x + actor->momx, actor->y + actor->momy)->sector; - - // Move downwards or upwards to go through a passageway. - if (nextsector->ceilingheight < actor->z + actor->height) - actor->momz -= FixedMul(5*FRACUNIT, actor->scale); - else if (nextsector->floorheight > actor->z) - actor->momz += FixedMul(5*FRACUNIT, actor->scale); -} - -// Function: A_MouseThink -// -// Description: Thinker for scurrying mice. -// -// var1 = unused -// var2 = unused -// -void A_MouseThink(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_MouseThink", actor)) - return; -#endif - - if (actor->reactiontime) - actor->reactiontime--; - - if (((!(actor->eflags & MFE_VERTICALFLIP) && actor->z == actor->floorz) - || (actor->eflags & MFE_VERTICALFLIP && actor->z + actor->height == actor->ceilingz)) - && !actor->reactiontime) - { - if (twodlevel || actor->flags2 & MF2_TWOD) - { - if (P_RandomChance(FRACUNIT/2)) - actor->angle += ANGLE_180; - } - else if (P_RandomChance(FRACUNIT/2)) - actor->angle += ANGLE_90; - else - actor->angle -= ANGLE_90; - - P_InstaThrust(actor, actor->angle, FixedMul(actor->info->speed, actor->scale)); - actor->reactiontime = TICRATE/5; - } -} - -// Function: A_DetonChase -// -// Description: Chases a Deton after a player. -// -// var1 = unused -// var2 = unused -// -void A_DetonChase(mobj_t *actor) -{ - angle_t exact; - fixed_t xydist, dist; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_DetonChase", actor)) - return; -#endif - - // modify tracer threshold - if (!actor->tracer || actor->tracer->health <= 0) - actor->threshold = 0; - else - actor->threshold = 1; - - if (!actor->tracer || !(actor->tracer->flags & MF_SHOOTABLE)) - { - // look for a new target - if (P_LookForPlayers(actor, true, true, 0)) - return; // got a new target - - actor->momx = actor->momy = actor->momz = 0; - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - - if (multiplayer && !actor->threshold && P_LookForPlayers(actor, true, true, 0)) - return; // got a new target - - // Face movement direction if not doing so - exact = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); - actor->angle = exact; - /*if (exact != actor->angle) - { - if (exact - actor->angle > ANGLE_180) - { - actor->angle -= actor->info->raisestate; - if (exact - actor->angle < ANGLE_180) - actor->angle = exact; - } - else - { - actor->angle += actor->info->raisestate; - if (exact - actor->angle > ANGLE_180) - actor->angle = exact; - } - }*/ - // movedir is up/down angle: how much it has to go up as it goes over to the player - xydist = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y); - exact = R_PointToAngle2(0, 0, xydist, actor->tracer->z - actor->z); - actor->movedir = exact; - /*if (exact != actor->movedir) - { - if (exact - actor->movedir > ANGLE_180) - { - actor->movedir -= actor->info->raisestate; - if (exact - actor->movedir < ANGLE_180) - actor->movedir = exact; - } - else - { - actor->movedir += actor->info->raisestate; - if (exact - actor->movedir > ANGLE_180) - actor->movedir = exact; - } - }*/ - - // check for melee attack - if (actor->tracer) - { - if (P_AproxDistance(actor->tracer->x-actor->x, actor->tracer->y-actor->y) < actor->radius+actor->tracer->radius) - { - if (!((actor->tracer->z > actor->z + actor->height) || (actor->z > actor->tracer->z + actor->tracer->height))) - { - P_ExplodeMissile(actor); - return; - } - } - } - - // chase towards player - if ((dist = P_AproxDistance(xydist, actor->tracer->z-actor->z)) - > FixedMul((actor->info->painchance << FRACBITS), actor->scale)) - { - P_SetTarget(&actor->tracer, NULL); // Too far away - return; - } - - if (actor->reactiontime == 0) - { - actor->reactiontime = actor->info->reactiontime; - return; - } - - if (actor->reactiontime > 1) - { - actor->reactiontime--; - return; - } - - if (actor->reactiontime > 0) - { - actor->reactiontime = -42; - - if (actor->info->seesound) - S_StartScreamSound(actor, actor->info->seesound); - } - - if (actor->reactiontime == -42) - { - fixed_t xyspeed; - - actor->reactiontime = -42; - - exact = actor->movedir>>ANGLETOFINESHIFT; - xyspeed = FixedMul(FixedMul(actor->tracer->player->normalspeed,3*FRACUNIT/4), FINECOSINE(exact)); - actor->momz = FixedMul(FixedMul(actor->tracer->player->normalspeed,3*FRACUNIT/4), FINESINE(exact)); - - exact = actor->angle>>ANGLETOFINESHIFT; - actor->momx = FixedMul(xyspeed, FINECOSINE(exact)); - actor->momy = FixedMul(xyspeed, FINESINE(exact)); - - // Variable re-use - xyspeed = (P_AproxDistance(actor->tracer->x - actor->x, P_AproxDistance(actor->tracer->y - actor->y, actor->tracer->z - actor->z))>>(FRACBITS+6)); - - if (xyspeed < 1) - xyspeed = 1; - - if (leveltime % xyspeed == 0) - S_StartSound(actor, sfx_deton); - } -} - -// Function: A_CapeChase -// -// Description: Set an object's location to its target or tracer. -// -// var1: -// 0 = Use target -// 1 = Use tracer -// upper 16 bits = Z offset -// var2: -// upper 16 bits = forward/backward offset -// lower 16 bits = sideways offset -// -void A_CapeChase(mobj_t *actor) -{ - mobj_t *chaser; - fixed_t foffsetx, foffsety, boffsetx, boffsety; - INT32 locvar1 = var1; - INT32 locvar2 = var2; - angle_t angle; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CapeChase", actor)) - return; -#endif - - CONS_Debug(DBG_GAMELOGIC, "A_CapeChase called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); - - if (locvar1 & 65535) - chaser = actor->tracer; - else - chaser = actor->target; - - if (!chaser || (chaser->health <= 0)) - { - if (chaser) - CONS_Debug(DBG_GAMELOGIC, "Hmm, the guy I'm chasing (object type %d) has no health.. so I'll die too!\n", chaser->type); - - P_RemoveMobj(actor); - return; - } - - angle = (chaser->player ? chaser->player->drawangle : chaser->angle); - - foffsetx = P_ReturnThrustX(chaser, angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale)); - foffsety = P_ReturnThrustY(chaser, angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale)); - - boffsetx = P_ReturnThrustX(chaser, angle-ANGLE_90, FixedMul((locvar2 & 65535)*FRACUNIT, actor->scale)); - boffsety = P_ReturnThrustY(chaser, angle-ANGLE_90, FixedMul((locvar2 & 65535)*FRACUNIT, actor->scale)); - - P_UnsetThingPosition(actor); - actor->x = chaser->x + foffsetx + boffsetx; - actor->y = chaser->y + foffsety + boffsety; - if (chaser->eflags & MFE_VERTICALFLIP) - { - actor->eflags |= MFE_VERTICALFLIP; - actor->flags2 |= MF2_OBJECTFLIP; - actor->z = chaser->z + chaser->height - actor->height - FixedMul((locvar1 >> 16)*FRACUNIT, actor->scale); - } - else - { - actor->eflags &= ~MFE_VERTICALFLIP; - actor->flags2 &= ~MF2_OBJECTFLIP; - actor->z = chaser->z + FixedMul((locvar1 >> 16)*FRACUNIT, actor->scale); - } - actor->angle = angle; - P_SetThingPosition(actor); -} - -// Function: A_RotateSpikeBall -// -// Description: Rotates a spike ball around its target/tracer. -// -// var1: -// 0 = Use target -// 1 = Use tracer -// var2 = unused -// -void A_RotateSpikeBall(mobj_t *actor) -{ - INT32 locvar1 = var1; - const fixed_t radius = FixedMul(12*actor->info->speed, actor->scale); -#ifdef HAVE_BLUA - if (LUA_CallAction("A_RotateSpikeBall", actor)) - return; -#endif - - if (!((!locvar1 && (actor->target)) || (locvar1 && (actor->tracer))))// This should NEVER happen. - { - CONS_Debug(DBG_GAMELOGIC, "A_RotateSpikeBall: Spikeball has no target\n"); - P_RemoveMobj(actor); - return; - } - - if (!actor->info->speed) - { - CONS_Debug(DBG_GAMELOGIC, "A_RotateSpikeBall: Object has no speed.\n"); - return; - } - - actor->angle += FixedAngle(actor->info->speed); - P_UnsetThingPosition(actor); - { - const angle_t fa = actor->angle>>ANGLETOFINESHIFT; - if (!locvar1) - { - actor->x = actor->target->x + FixedMul(FINECOSINE(fa),radius); - actor->y = actor->target->y + FixedMul(FINESINE(fa),radius); - actor->z = actor->target->z + actor->target->height/2; - } - else - { - actor->x = actor->tracer->x + FixedMul(FINECOSINE(fa),radius); - actor->y = actor->tracer->y + FixedMul(FINESINE(fa),radius); - actor->z = actor->tracer->z + actor->tracer->height/2; - } - P_SetThingPosition(actor); - } -} - -// Function: A_UnidusBall -// -// Description: Rotates a spike ball around its target. -// -// var1: -// 0 = Don't throw -// 1 = Throw -// 2 = Throw when target leaves MF2_SKULLFLY. -// var2 = unused -// -void A_UnidusBall(mobj_t *actor) -{ - INT32 locvar1 = var1; - boolean canthrow = false; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_UnidusBall", actor)) - return; -#endif - - actor->angle += ANGLE_11hh; - - if (actor->movecount) - { - if (P_AproxDistance(actor->momx, actor->momy) < FixedMul(actor->info->damage/2, actor->scale)) - P_ExplodeMissile(actor); - return; - } - - if (!actor->target || !actor->target->health) - { - CONS_Debug(DBG_GAMELOGIC, "A_UnidusBall: Removing unthrown spikeball from nonexistant Unidus\n"); - P_RemoveMobj(actor); - return; - } - - P_UnsetThingPosition(actor); - { - const angle_t angle = actor->movedir + FixedAngle(actor->info->speed*(leveltime%360)); - const UINT16 fa = angle>>ANGLETOFINESHIFT; - - actor->x = actor->target->x + FixedMul(FINECOSINE(fa),actor->threshold); - actor->y = actor->target->y + FixedMul( FINESINE(fa),actor->threshold); - actor->z = actor->target->z + actor->target->height/2 - actor->height/2; - - if (locvar1 == 1 && actor->target->target) - { - const angle_t tang = R_PointToAngle2(actor->target->x, actor->target->y, actor->target->target->x, actor->target->target->y); - const angle_t mina = tang-ANGLE_11hh; - canthrow = (angle-mina < FixedAngle(actor->info->speed*3)); - } - } - P_SetThingPosition(actor); - - if (locvar1 == 1 && canthrow) - { - if (P_AproxDistance(actor->target->target->x - actor->target->x, actor->target->target->y - actor->target->y) > FixedMul(MISSILERANGE>>1, actor->scale) - || !P_CheckSight(actor, actor->target->target)) - return; - - actor->movecount = actor->info->damage>>FRACBITS; - actor->flags &= ~(MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING); - P_InstaThrust(actor, R_PointToAngle2(actor->x, actor->y, actor->target->target->x, actor->target->target->y), FixedMul(actor->info->damage, actor->scale)); - } - else if (locvar1 == 2) - { - boolean skull = (actor->target->flags2 & MF2_SKULLFLY) == MF2_SKULLFLY; - if (actor->target->state == &states[actor->target->info->painstate]) - { - P_KillMobj(actor, NULL, NULL, 0); - return; - } - switch(actor->extravalue2) - { - case 0: // at least one frame where not dashing - if (!skull) ++actor->extravalue2; - else break; - /* FALLTHRU */ - case 1: // at least one frame where ARE dashing - if (skull) ++actor->extravalue2; - else break; - /* FALLTHRU */ - case 2: // not dashing again? - if (skull) break; - // launch. - { - mobj_t *target = actor->target; - if (actor->target->target) - target = actor->target->target; - actor->movecount = actor->info->damage>>FRACBITS; - actor->flags &= ~(MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING); - P_InstaThrust(actor, R_PointToAngle2(actor->x, actor->y, target->x, target->y), FixedMul(actor->info->damage, actor->scale)); - } - default: // from our compiler appeasement program (CAP). - break; - } - } -} - -// Function: A_RockSpawn -// -// Spawns rocks at a specified interval -// -// var1 = unused -// var2 = unused -void A_RockSpawn(mobj_t *actor) -{ - mobj_t *mo; - mobjtype_t type; - INT32 i = P_FindSpecialLineFromTag(12, (INT16)actor->threshold, -1); - line_t *line; - fixed_t dist; - fixed_t randomoomph; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_RockSpawn", actor)) - return; -#endif - - if (i == -1) - { - CONS_Debug(DBG_GAMELOGIC, "A_RockSpawn: Unable to find parameter line 12 (tag %d)!\n", actor->threshold); - return; - } - - line = &lines[i]; - - if (!(sides[line->sidenum[0]].textureoffset >> FRACBITS)) - { - CONS_Debug(DBG_GAMELOGIC, "A_RockSpawn: No X-offset detected! (tag %d)!\n", actor->threshold); - return; - } - - dist = P_AproxDistance(line->dx, line->dy)/16; - - if (dist < 1) - dist = 1; - - type = MT_ROCKCRUMBLE1 + (sides[line->sidenum[0]].rowoffset >> FRACBITS); - - if (line->flags & ML_NOCLIMB) - randomoomph = P_RandomByte() * (FRACUNIT/32); - else - randomoomph = 0; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FALLINGROCK); - P_SetMobjState(mo, mobjinfo[type].spawnstate); - mo->angle = R_PointToAngle2(line->v2->x, line->v2->y, line->v1->x, line->v1->y); - - P_InstaThrust(mo, mo->angle, dist + randomoomph); - mo->momz = dist + randomoomph; - - var1 = sides[line->sidenum[0]].textureoffset >> FRACBITS; - A_SetTics(actor); -} - -// -// Function: A_SlingAppear -// -// Appears a sling. -// -// var1 = unused -// var2 = unused -// -void A_SlingAppear(mobj_t *actor) -{ - UINT8 mlength = 4; - mobj_t *spawnee, *hprev; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SlingAppear", actor)) - return; -#endif - - P_UnsetThingPosition(actor); - actor->flags &= ~(MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT); - P_SetThingPosition(actor); - actor->lastlook = 128; - actor->movecount = actor->lastlook; - actor->threshold = 0; - actor->movefactor = actor->threshold; - actor->friction = 128; - - hprev = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMALLGRABCHAIN); - P_SetTarget(&hprev->tracer, actor); - P_SetTarget(&hprev->hprev, actor); - P_SetTarget(&actor->hnext, hprev); - hprev->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT; - hprev->movecount = mlength; - - mlength--; - - while (mlength > 0) - { - spawnee = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMALLMACECHAIN); - P_SetTarget(&spawnee->tracer, actor); - P_SetTarget(&spawnee->hprev, hprev); - P_SetTarget(&hprev->hnext, spawnee); - hprev = spawnee; - - spawnee->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT; - spawnee->movecount = mlength; - - mlength--; - } -} - -// Function: A_SetFuse -// -// Description: Sets the actor's fuse timer if not set already. May also change state when fuse reaches the last tic, otherwise by default the actor will die or disappear. (Replaces A_SnowBall) -// -// var1 = fuse timer duration (in tics). -// var2: -// lower 16 bits = if > 0, state to change to when fuse = 1 -// upper 16 bits: 0 = (default) don't set fuse unless 0, 1 = force change, 2 = force no change -// -void A_SetFuse(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SetFuse", actor)) - return; -#endif - - if ((!actor->fuse || (locvar2 >> 16)) && (locvar2 >> 16) != 2) // set the actor's fuse value - actor->fuse = locvar1; - - if (actor->fuse == 1 && (locvar2 & 65535)) // change state on the very last tic (fuse is handled before actions in P_MobjThinker) - { - actor->fuse = 0; // don't die/disappear the next tic! - P_SetMobjState(actor, locvar2 & 65535); - } -} - -// Function: A_CrawlaCommanderThink -// -// Description: Thinker for Crawla Commander. -// -// var1 = shoot bullets? -// var2 = "pogo mode" speed -// -void A_CrawlaCommanderThink(mobj_t *actor) -{ - fixed_t dist; - sector_t *nextsector; - fixed_t thefloor; - INT32 locvar1 = var1; - INT32 locvar2 = var2; - boolean hovermode = (actor->health > 1 || actor->fuse); -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CrawlaCommanderThink", actor)) - return; -#endif - - if (actor->z >= actor->waterbottom && actor->watertop > actor->floorz - && actor->z > actor->watertop - FixedMul(256*FRACUNIT, actor->scale)) - thefloor = actor->watertop; - else - thefloor = actor->floorz; - - if (!actor->fuse && actor->flags2 & MF2_FRET) - { - if (actor->info->painsound) - S_StartSound(actor, actor->info->painsound); - - actor->fuse = TICRATE/2; - actor->momz = 0; - - P_InstaThrust(actor, actor->angle-ANGLE_180, FixedMul(5*FRACUNIT, actor->scale)); - } - - if (actor->reactiontime > 0) - actor->reactiontime--; - - if (actor->fuse < 2) - { - actor->fuse = 0; - actor->flags2 &= ~MF2_FRET; - } - - // Hover mode - if (hovermode) - { - if (actor->z < thefloor + FixedMul(16*FRACUNIT, actor->scale)) - actor->momz += FixedMul(FRACUNIT, actor->scale); - else if (actor->z < thefloor + FixedMul(32*FRACUNIT, actor->scale)) - actor->momz += FixedMul(FRACUNIT/2, actor->scale); - else - actor->momz += FixedMul(16, actor->scale); - } - - if (!actor->target) - { - // look for a new target - if (P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - if (actor->state != &states[actor->info->spawnstate]) - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - - dist = P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y); - - if (actor->target->player && (!hovermode || actor->reactiontime <= 2*TICRATE)) - { - if (dist < FixedMul(64<<(FRACBITS+(hovermode ? 1 : 0)), actor->scale) - && ((actor->target->player->pflags & PF_JUMPED) || (actor->target->player->pflags & PF_SPINNING))) - { - // Auugh! She's trying to kill you! Strafe! STRAAAAFFEEE!! - P_InstaThrust(actor, actor->angle - ANGLE_180, FixedMul(20*FRACUNIT, actor->scale)); - return; - } - } - - if (locvar1) - { - if (actor->health < 2 && P_RandomChance(FRACUNIT/128)) - P_SpawnMissile(actor, actor->target, locvar1); - } - - // Face the player - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); - - if (actor->threshold && dist > FixedMul(256*FRACUNIT, actor->scale)) - actor->momx = actor->momy = 0; - - if (actor->reactiontime && actor->reactiontime <= 2*TICRATE && dist > actor->target->radius - FixedMul(FRACUNIT, actor->scale)) - { - actor->threshold = 0; - - // Roam around, somewhat in the player's direction. - actor->angle += (P_RandomByte()<<10); - actor->angle -= (P_RandomByte()<<10); - - if (hovermode) - { - fixed_t mom; - P_Thrust(actor, actor->angle, 2*actor->scale); - mom = P_AproxDistance(actor->momx, actor->momy); - if (mom > 20*actor->scale) - { - mom += 20*actor->scale; - mom >>= 1; - P_InstaThrust(actor, R_PointToAngle2(0, 0, actor->momx, actor->momy), mom); - } - } - } - else if (!actor->reactiontime) - { - if (hovermode && !(actor->flags2 & MF2_FRET)) // Hover Mode - { - if (dist < FixedMul(512*FRACUNIT, actor->scale)) - { - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); - P_InstaThrust(actor, actor->angle, FixedMul(40*FRACUNIT, actor->scale)); - actor->threshold = 1; - if (actor->info->attacksound) - S_StartSound(actor, actor->info->attacksound); - } - } - actor->reactiontime = 3*TICRATE + (P_RandomByte()>>2); - } - - if (actor->health == 1) - P_Thrust(actor, actor->angle, 1); - - // Pogo Mode - if (!hovermode && actor->z <= actor->floorz) - { - if (actor->info->activesound) - S_StartSound(actor, actor->info->activesound); - - if (dist < FixedMul(256*FRACUNIT, actor->scale)) - { - actor->momz = FixedMul(locvar2, actor->scale); - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); - P_InstaThrust(actor, actor->angle, FixedMul(locvar2/8, actor->scale)); - // pogo on player - } - else - { - UINT8 prandom = P_RandomByte(); - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom); - P_InstaThrust(actor, actor->angle, FixedDiv(FixedMul(locvar2, actor->scale), 3*FRACUNIT/2)); - actor->momz = FixedMul(locvar2, actor->scale); // Bounce up in air - } - } - - nextsector = R_PointInSubsector(actor->x + actor->momx, actor->y + actor->momy)->sector; - - // Move downwards or upwards to go through a passageway. - if (nextsector->floorheight > actor->z && nextsector->floorheight - actor->z < FixedMul(128*FRACUNIT, actor->scale)) - actor->momz += (nextsector->floorheight - actor->z) / 4; -} - -// Function: A_RingExplode -// -// Description: An explosion ring exploding -// -// var1 = unused -// var2 = unused -// -void A_RingExplode(mobj_t *actor) -{ - mobj_t *mo2; - thinker_t *th; - angle_t d; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_RingExplode", actor)) - return; -#endif - - for (d = 0; d < 16; d++) - P_SpawnParaloop(actor->x, actor->y, actor->z + actor->height, FixedMul(actor->info->painchance, actor->scale), 16, MT_NIGHTSPARKLE, S_NULL, d*(ANGLE_22h), true); - - S_StartSound(actor, sfx_prloop); - - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2 == actor) // Don't explode yourself! Endless loop! - continue; - - if (P_AproxDistance(P_AproxDistance(mo2->x - actor->x, mo2->y - actor->y), mo2->z - actor->z) > FixedMul(actor->info->painchance, actor->scale)) - continue; - - if (mo2->flags & MF_SHOOTABLE) - { - actor->flags2 |= MF2_DEBRIS; - P_DamageMobj(mo2, actor, actor->target, 1, 0); - continue; - } - } - return; -} - -// Function: A_OldRingExplode -// -// Description: An explosion ring exploding, 1.09.4 style -// -// var1 = object # to explode as debris -// var2 = unused -// -void A_OldRingExplode(mobj_t *actor) { - UINT8 i; - mobj_t *mo; - const fixed_t ns = FixedMul(20 * FRACUNIT, actor->scale); - INT32 locvar1 = var1; - //INT32 locvar2 = var2; - boolean changecolor = (actor->target && actor->target->player); -#ifdef HAVE_BLUA - if (LUA_CallAction("A_OldRingExplode", actor)) - return; -#endif - - for (i = 0; i < 32; i++) - { - const angle_t fa = (i*FINEANGLES/16) & FINEMASK; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, locvar1); - P_SetTarget(&mo->target, actor->target); // Transfer target so player gets the points - - mo->momx = FixedMul(FINECOSINE(fa),ns); - mo->momy = FixedMul(FINESINE(fa),ns); - - if (i > 15) - { - if (i & 1) - mo->momz = ns; - else - mo->momz = -ns; - } - - mo->flags2 |= MF2_DEBRIS; - mo->fuse = TICRATE/5; - - if (changecolor) - { - if (gametype != GT_CTF) - mo->color = actor->target->color; //copy color - else if (actor->target->player->ctfteam == 2) - mo->color = skincolor_bluering; - } - } - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, locvar1); - - P_SetTarget(&mo->target, actor->target); - mo->momz = ns; - mo->flags2 |= MF2_DEBRIS; - mo->fuse = TICRATE/5; - - if (changecolor) - { - if (gametype != GT_CTF) - mo->color = actor->target->color; //copy color - else if (actor->target->player->ctfteam == 2) - mo->color = skincolor_bluering; - } - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, locvar1); - - P_SetTarget(&mo->target, actor->target); - mo->momz = -ns; - mo->flags2 |= MF2_DEBRIS; - mo->fuse = TICRATE/5; - - if (changecolor) - { - if (gametype != GT_CTF) - mo->color = actor->target->color; //copy color - else if (actor->target->player->ctfteam == 2) - mo->color = skincolor_bluering; - } -} - -// Function: A_MixUp -// -// Description: Mix up all of the player positions. -// -// var1 = unused -// var2 = unused -// -void A_MixUp(mobj_t *actor) -{ - boolean teleported[MAXPLAYERS]; - INT32 i, numplayers = 0, prandom = 0; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_MixUp", actor)) - return; -#else - (void)actor; -#endif - - if (!multiplayer) - return; - - // No mix-up monitors in hide and seek or time only race. - // The random factor is okay for other game modes, but in these, it is cripplingly unfair. - if (gametype == GT_HIDEANDSEEK || gametype == GT_RACE) - { - S_StartSound(actor, sfx_lose); - return; - } - - numplayers = 0; - memset(teleported, 0, sizeof (teleported)); - - // Count the number of players in the game - // and grab their xyz coords - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE - && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE) - { - if ((netgame || multiplayer) && players[i].spectator) // Ignore spectators - continue; - - numplayers++; - } - - if (numplayers <= 1) // Not enough players to mix up. - { - S_StartSound(actor, sfx_lose); - return; - } - else if (numplayers == 2) // Special case -- simple swap - { - fixed_t x, y, z; - angle_t angle; - INT32 one = -1, two = 0; // default value 0 to make the compiler shut up - - // Zoom tube stuff - mobj_t *tempthing = NULL; //tracer - UINT16 carry1,carry2; //carry - INT32 transspeed; //player speed - - // Starpost stuff - INT16 starpostx, starposty, starpostz; - INT32 starpostnum; - tic_t starposttime; - angle_t starpostangle; - - INT32 mflags2; - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE - && !players[i].exiting && !players[i].powers[pw_super]) - { - if ((netgame || multiplayer) && players[i].spectator) // Ignore spectators - continue; - - if (one == -1) - one = i; - else - { - two = i; - break; - } - } - - //get this done first! - tempthing = players[one].mo->tracer; - P_SetTarget(&players[one].mo->tracer, players[two].mo->tracer); - P_SetTarget(&players[two].mo->tracer, tempthing); - - //zoom tubes use player->speed to determine direction and speed - transspeed = players[one].speed; - players[one].speed = players[two].speed; - players[two].speed = transspeed; - - //set flags variables now but DON'T set them. - carry1 = (players[one].powers[pw_carry] == CR_PLAYER ? CR_NONE : players[one].powers[pw_carry]); - carry2 = (players[two].powers[pw_carry] == CR_PLAYER ? CR_NONE : players[two].powers[pw_carry]); - - x = players[one].mo->x; - y = players[one].mo->y; - z = players[one].mo->z; - angle = players[one].mo->angle; - - starpostx = players[one].starpostx; - starposty = players[one].starposty; - starpostz = players[one].starpostz; - starpostangle = players[one].starpostangle; - starpostnum = players[one].starpostnum; - starposttime = players[one].starposttime; - - mflags2 = players[one].mo->flags2; - - P_MixUp(players[one].mo, players[two].mo->x, players[two].mo->y, players[two].mo->z, players[two].mo->angle, - players[two].starpostx, players[two].starposty, players[two].starpostz, - players[two].starpostnum, players[two].starposttime, players[two].starpostangle, - players[two].mo->flags2); - - P_MixUp(players[two].mo, x, y, z, angle, starpostx, starposty, starpostz, - starpostnum, starposttime, starpostangle, - mflags2); - - //carry set after mixup. Stupid P_ResetPlayer() takes away some of the stuff we look for... - //but not all of it! So we need to make sure they aren't set wrong or anything. - players[one].powers[pw_carry] = carry2; - players[two].powers[pw_carry] = carry1; - - teleported[one] = true; - teleported[two] = true; - } - else - { - fixed_t position[MAXPLAYERS][3]; - angle_t anglepos[MAXPLAYERS]; - INT32 pindex[MAXPLAYERS], counter = 0, teleportfrom = 0; - - // Zoom tube stuff - mobj_t *transtracer[MAXPLAYERS]; //tracer - //pflags_t transflag[MAXPLAYERS]; //cyan pink white pink cyan - UINT16 transcarry[MAXPLAYERS]; //player carry - INT32 transspeed[MAXPLAYERS]; //player speed - - // Star post stuff - INT16 spposition[MAXPLAYERS][3]; - INT32 starpostnum[MAXPLAYERS]; - tic_t starposttime[MAXPLAYERS]; - angle_t starpostangle[MAXPLAYERS]; - - INT32 flags2[MAXPLAYERS]; - - for (i = 0; i < MAXPLAYERS; i++) - { - position[i][0] = position[i][1] = position[i][2] = anglepos[i] = pindex[i] = -1; - teleported[i] = false; - } - - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && players[i].playerstate == PST_LIVE - && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE) - { - if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators - continue; - - position[counter][0] = players[i].mo->x; - position[counter][1] = players[i].mo->y; - position[counter][2] = players[i].mo->z; - pindex[counter] = i; - anglepos[counter] = players[i].mo->angle; - players[i].mo->momx = players[i].mo->momy = players[i].mo->momz = - players[i].rmomx = players[i].rmomy = 1; - players[i].cmomx = players[i].cmomy = 0; - - transcarry[counter] = (players[i].powers[pw_carry] == CR_PLAYER ? CR_NONE : players[i].powers[pw_carry]); - transspeed[counter] = players[i].speed; - transtracer[counter] = players[i].mo->tracer; - - spposition[counter][0] = players[i].starpostx; - spposition[counter][1] = players[i].starposty; - spposition[counter][2] = players[i].starpostz; - starpostnum[counter] = players[i].starpostnum; - starposttime[counter] = players[i].starposttime; - starpostangle[counter] = players[i].starpostangle; - - flags2[counter] = players[i].mo->flags2; - - counter++; - } - } - - counter = 0; - - // Mix them up! - for (;;) - { - if (counter > 255) // fail-safe to avoid endless loop - break; - prandom = P_RandomByte(); - prandom %= numplayers; // I love modular arithmetic, don't you? - if (prandom) // Make sure it's not a useless mix - break; - counter++; - } - - counter = 0; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && players[i].playerstate == PST_LIVE - && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE) - { - if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators - continue; - - teleportfrom = (counter + prandom) % numplayers; - - //speed and tracer come before... - players[i].speed = transspeed[teleportfrom]; - P_SetTarget(&players[i].mo->tracer, transtracer[teleportfrom]); - - P_MixUp(players[i].mo, position[teleportfrom][0], position[teleportfrom][1], position[teleportfrom][2], anglepos[teleportfrom], - spposition[teleportfrom][0], spposition[teleportfrom][1], spposition[teleportfrom][2], - starpostnum[teleportfrom], starposttime[teleportfrom], starpostangle[teleportfrom], - flags2[teleportfrom]); - - //...carry after. same reasoning. - players[i].powers[pw_carry] = transcarry[teleportfrom]; - - teleported[i] = true; - counter++; - } - } - } - - for (i = 0; i < MAXPLAYERS; i++) - { - if (teleported[i]) - { - if (playeringame[i] && players[i].playerstate == PST_LIVE - && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE) - { - if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators - continue; - - P_SetThingPosition(players[i].mo); - -#ifdef ESLOPE - players[i].mo->floorz = P_GetFloorZ(players[i].mo, players[i].mo->subsector->sector, players[i].mo->x, players[i].mo->y, NULL); - players[i].mo->ceilingz = P_GetCeilingZ(players[i].mo, players[i].mo->subsector->sector, players[i].mo->x, players[i].mo->y, NULL); -#else - players[i].mo->floorz = players[i].mo->subsector->sector->floorheight; - players[i].mo->ceilingz = players[i].mo->subsector->sector->ceilingheight; -#endif - - P_CheckPosition(players[i].mo, players[i].mo->x, players[i].mo->y); - } - } - } - - // Play the 'bowrwoosh!' sound - S_StartSound(NULL, sfx_mixup); -} - -// Function: A_RecyclePowers -// -// Description: Take all player's powers, and swap 'em. -// -// var1 = unused -// var2 = unused -// -void A_RecyclePowers(mobj_t *actor) -{ - INT32 i, j, k, numplayers = 0; - -#ifdef WEIGHTEDRECYCLER - UINT8 beneficiary = 255; -#endif - UINT8 playerslist[MAXPLAYERS]; - UINT8 postscramble[MAXPLAYERS]; - - UINT16 powers[MAXPLAYERS][NUMPOWERS]; - INT32 weapons[MAXPLAYERS]; - INT32 weaponheld[MAXPLAYERS]; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_RecyclePowers", actor)) - return; -#endif - -#if !defined(WEIGHTEDRECYCLER) && !defined(HAVE_BLUA) - // actor is used in all scenarios but this one, funny enough - (void)actor; -#endif - - if (!multiplayer) - { - S_StartSound(actor, sfx_lose); - return; - } - - numplayers = 0; - - // Count the number of players in the game - for (i = 0, j = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE - && !players[i].exiting && !((netgame || multiplayer) && players[i].spectator)) - { -#ifndef WEIGHTEDRECYCLER - if (players[i].powers[pw_super]) - continue; // Ignore super players -#endif - - numplayers++; - postscramble[j] = playerslist[j] = (UINT8)i; - -#ifdef WEIGHTEDRECYCLER - // The guy who started the recycle gets the best result - if (actor && actor->target && actor->target->player && &players[i] == actor->target->player) - beneficiary = (UINT8)i; -#endif - - // Save powers - for (k = 0; k < NUMPOWERS; k++) - powers[i][k] = players[i].powers[k]; - //1.1: ring weapons too - weapons[i] = players[i].ringweapons; - weaponheld[i] = players[i].currentweapon; - - j++; - } - } - - if (numplayers <= 1) - { - S_StartSound(actor, sfx_lose); - return; //nobody to touch! - } - - //shuffle the post scramble list, whee! - // hardcoded 0-1 to 1-0 for two players - if (numplayers == 2) - { - postscramble[0] = playerslist[1]; - postscramble[1] = playerslist[0]; - } - else - for (j = 0; j < numplayers; j++) - { - UINT8 tempint; - - i = j + ((P_RandomByte() + leveltime) % (numplayers - j)); - tempint = postscramble[j]; - postscramble[j] = postscramble[i]; - postscramble[i] = tempint; - } - -#ifdef WEIGHTEDRECYCLER - //the joys of qsort... - if (beneficiary != 255) { - qsort(playerslist, numplayers, sizeof(UINT8), P_RecycleCompare); - - // now, make sure the benificiary is in the best slot - // swap out whatever poor sap was going to get the best items - for (i = 0; i < numplayers; i++) - { - if (postscramble[i] == beneficiary) - { - postscramble[i] = postscramble[0]; - postscramble[0] = beneficiary; - break; - } - } - } -#endif - - // now assign! - for (i = 0; i < numplayers; i++) - { - UINT8 send_pl = playerslist[i]; - UINT8 recv_pl = postscramble[i]; - - // debugF - CONS_Debug(DBG_GAMELOGIC, "sending player %hu's items to %hu\n", (UINT16)send_pl, (UINT16)recv_pl); - - for (j = 0; j < NUMPOWERS; j++) - { - if (j == pw_flashing || j == pw_underwater || j == pw_spacetime || j == pw_carry - || j == pw_tailsfly || j == pw_extralife || j == pw_nocontrol || j == pw_super) - continue; - players[recv_pl].powers[j] = powers[send_pl][j]; - } - - //1.1: weapon rings too - players[recv_pl].ringweapons = weapons[send_pl]; - players[recv_pl].currentweapon = weaponheld[send_pl]; - - P_SpawnShieldOrb(&players[recv_pl]); - if (P_IsLocalPlayer(&players[recv_pl])) - P_RestoreMusic(&players[recv_pl]); - P_FlashPal(&players[recv_pl], PAL_RECYCLE, 10); - } - - S_StartSound(NULL, sfx_gravch); //heh, the sound effect I used is already in -} - -// Function: A_Boss1Chase -// -// Description: Like A_Chase, but for Boss 1. -// -// var1 = unused -// var2 = unused -// -void A_Boss1Chase(mobj_t *actor) -{ - INT32 delta; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Boss1Chase", actor)) - return; -#endif - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { - // look for a new target - if (P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - P_SetMobjStateNF(actor, actor->info->spawnstate); - return; - } - - if (actor->reactiontime) - actor->reactiontime--; - - // turn towards movement direction if not there yet - if (actor->movedir < NUMDIRS) - { - actor->angle &= (7<<29); - delta = actor->angle - (actor->movedir << 29); - - if (delta > 0) - actor->angle -= ANGLE_45; - else if (delta < 0) - actor->angle += ANGLE_45; - } - - // do not attack twice in a row - if (actor->flags2 & MF2_JUSTATTACKED) - { - actor->flags2 &= ~MF2_JUSTATTACKED; - P_NewChaseDir(actor); - return; - } - - if (actor->movecount) - goto nomissile; - - if (!P_CheckMissileRange(actor)) - goto nomissile; - - if (actor->reactiontime <= 0) - { - if (actor->health > actor->info->damage) - { - if (P_RandomChance(FRACUNIT/2)) - P_SetMobjState(actor, actor->info->missilestate); - else - P_SetMobjState(actor, actor->info->meleestate); - } - else - { - P_LinedefExecute(LE_PINCHPHASE, actor, NULL); - P_SetMobjState(actor, actor->info->raisestate); - } - - actor->flags2 |= MF2_JUSTATTACKED; - actor->reactiontime = actor->info->reactiontime; - return; - } - - // ? -nomissile: - // possibly choose another target - if (multiplayer && P_RandomChance(FRACUNIT/128)) - { - if (P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - } - - if (actor->flags & MF_FLOAT && !(actor->flags2 & MF2_SKULLFLY)) - { // Float up/down to your target's position. Stay above them, but not out of jump range. - fixed_t target_min = actor->target->floorz+FixedMul(64*FRACUNIT, actor->scale); - if (target_min < actor->target->z - actor->height) - target_min = actor->target->z - actor->height; - if (target_min < actor->floorz+FixedMul(33*FRACUNIT, actor->scale)) - target_min = actor->floorz+FixedMul(33*FRACUNIT, actor->scale); - if (actor->z > target_min+FixedMul(16*FRACUNIT, actor->scale)) - actor->momz = FixedMul((-actor->info->speed<<(FRACBITS-1)), actor->scale); - else if (actor->z < target_min) - actor->momz = FixedMul(actor->info->speed<<(FRACBITS-1), actor->scale); - else - actor->momz = FixedMul(actor->momz,7*FRACUNIT/8); - } - - // chase towards player - if (P_AproxDistance(actor->target->x-actor->x, actor->target->y-actor->y) > actor->radius+actor->target->radius) - { - if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) - P_NewChaseDir(actor); - } - // too close, don't want to chase. - else if (--actor->movecount < 0) - { - // A mini-A_FaceTarget based on P_NewChaseDir. - // Yes, it really is this simple when you get down to it. - fixed_t deltax, deltay; - - deltax = actor->target->x - actor->x; - deltay = actor->target->y - actor->y; - - actor->movedir = diags[((deltay < 0)<<1) + (deltax > 0)]; - actor->movecount = P_RandomByte() & 15; - } -} - -// Function: A_Boss2Chase -// -// Description: Really doesn't 'chase', but rather goes in a circle. -// -// var1 = unused -// var2 = unused -// -void A_Boss2Chase(mobj_t *actor) -{ - fixed_t radius; - boolean reverse = false; - INT32 speedvar; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Boss2Chase", actor)) - return; -#endif - - if (actor->health <= 0) - return; - - // Startup randomness - if (actor->reactiontime <= -666) - actor->reactiontime = 2*TICRATE + P_RandomByte(); - - // When reactiontime hits zero, he will go the other way - if (--actor->reactiontime <= 0) - { - reverse = true; - actor->reactiontime = 2*TICRATE + P_RandomByte(); - } - - P_SetTarget(&actor->target, P_GetClosestAxis(actor)); - - if (!actor->target) // This should NEVER happen. - { - CONS_Debug(DBG_GAMELOGIC, "Boss2 has no target!\n"); - A_BossDeath(actor); - return; - } - - radius = actor->target->radius; - - if (reverse) - { - actor->watertop = -actor->watertop; - actor->extravalue1 = 18; - if (actor->flags2 & MF2_AMBUSH) - actor->extravalue1 -= (actor->info->spawnhealth - actor->health)*2; - actor->extravalue2 = actor->extravalue1; - } - - // Turnaround - if (actor->extravalue1 > 0) - { - --actor->extravalue1; - - // Set base angle - { - const angle_t fa = (actor->target->angle + FixedAngle(actor->watertop))>>ANGLETOFINESHIFT; - const fixed_t fc = FixedMul(FINECOSINE(fa),radius); - const fixed_t fs = FixedMul(FINESINE(fa),radius); - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x + fc, actor->target->y + fs); - } - - // Now turn you around! - // Note that the start position is the final position, we move it back around - // to intermediary positions... - actor->angle -= FixedAngle(FixedMul(FixedDiv(180<extravalue2<extravalue1<flags2 & MF2_AMBUSH) - speedvar = actor->health; - else - speedvar = actor->info->spawnhealth; - - actor->target->angle += // Don't use FixedAngleC! - FixedAngle(FixedDiv(FixedMul(actor->watertop, (actor->info->spawnhealth*(FRACUNIT/4)*3)), speedvar*FRACUNIT)); - - P_UnsetThingPosition(actor); - { - const angle_t fa = actor->target->angle>>ANGLETOFINESHIFT; - const fixed_t fc = FixedMul(FINECOSINE(fa),radius); - const fixed_t fs = FixedMul(FINESINE(fa),radius); - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x + fc, actor->target->y + fs); - actor->x = actor->target->x + fc; - actor->y = actor->target->y + fs; - } - P_SetThingPosition(actor); - - // Spray goo once every second - if (leveltime % (speedvar*15/10)-1 == 0) - { - const fixed_t ns = FixedMul(3 * FRACUNIT, actor->scale); - mobj_t *goop; - fixed_t fz = actor->z+actor->height+FixedMul(24*FRACUNIT, actor->scale); - angle_t fa; - // actor->movedir is used to determine the last - // direction goo was sprayed in. There are 8 possible - // directions to spray. (45-degree increments) - - actor->movedir++; - actor->movedir %= NUMDIRS; - fa = (actor->movedir*FINEANGLES/8) & FINEMASK; - - goop = P_SpawnMobj(actor->x, actor->y, fz, actor->info->painchance); - goop->momx = FixedMul(FINECOSINE(fa),ns); - goop->momy = FixedMul(FINESINE(fa),ns); - goop->momz = FixedMul(4*FRACUNIT, actor->scale); - goop->fuse = 10*TICRATE; - - if (actor->info->attacksound) - S_StartAttackSound(actor, actor->info->attacksound); - - if (P_RandomChance(FRACUNIT/2)) - { - goop->momx *= 2; - goop->momy *= 2; - } - else if (P_RandomChance(129*FRACUNIT/256)) - { - goop->momx *= 3; - goop->momy *= 3; - } - - actor->flags2 |= MF2_JUSTATTACKED; - } - } -} - -// Function: A_Boss2Pogo -// -// Description: Pogo part of Boss 2 AI. -// -// var1 = unused -// var2 = unused -// -void A_Boss2Pogo(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Boss2Pogo", actor)) - return; -#endif - if (actor->z <= actor->floorz + FixedMul(8*FRACUNIT, actor->scale) && actor->momz <= 0) - { - if (actor->state != &states[actor->info->raisestate]) - P_SetMobjState(actor, actor->info->raisestate); - // Pogo Mode - } - else if (actor->momz < 0 && actor->reactiontime) - { - const fixed_t ns = FixedMul(3 * FRACUNIT, actor->scale); - mobj_t *goop; - fixed_t fz = actor->z+actor->height+FixedMul(24*FRACUNIT, actor->scale); - angle_t fa; - INT32 i; - // spray in all 8 directions! - for (i = 0; i < 8; i++) - { - actor->movedir++; - actor->movedir %= NUMDIRS; - fa = (actor->movedir*FINEANGLES/8) & FINEMASK; - - goop = P_SpawnMobj(actor->x, actor->y, fz, actor->info->painchance); - goop->momx = FixedMul(FINECOSINE(fa),ns); - goop->momy = FixedMul(FINESINE(fa),ns); - goop->momz = FixedMul(4*FRACUNIT, actor->scale); - - goop->fuse = 10*TICRATE; - } - actor->reactiontime = 0; // we already shot goop, so don't do it again! - if (actor->info->attacksound) - S_StartAttackSound(actor, actor->info->attacksound); - actor->flags2 |= MF2_JUSTATTACKED; - } -} - -// Function: A_Boss2TakeDamage -// -// Description: Special function for Boss 2 so you can't just sit and destroy him. -// -// var1 = Invincibility duration -// var2 = unused -// -void A_Boss2TakeDamage(mobj_t *actor) -{ - INT32 locvar1 = var1; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Boss2TakeDamage", actor)) - return; -#endif - A_Pain(actor); - actor->reactiontime = 1; // turn around - if (locvar1 == 0) // old A_Invincibilerize behavior - actor->movecount = TICRATE; - else - actor->movecount = locvar1; // become flashing invulnerable for this long. -} - -// Function: A_Boss7Chase -// -// Description: Like A_Chase, but for Black Eggman -// -// var1 = unused -// var2 = unused -// -void A_Boss7Chase(mobj_t *actor) -{ - INT32 delta; - INT32 i; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Boss7Chase", actor)) - return; -#endif - - if (actor->z != actor->floorz) - return; - - // Self-adjust if stuck on the edge - if (actor->tracer) - { - if (P_AproxDistance(actor->x - actor->tracer->x, actor->y - actor->tracer->y) > 128*FRACUNIT - actor->radius) - P_InstaThrust(actor, R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y), FRACUNIT); - } - - if (actor->flags2 & MF2_FRET) - { - P_SetMobjState(actor, S_BLACKEGG_DESTROYPLAT1); - S_StartSound(0, sfx_s3k53); - actor->flags2 &= ~MF2_FRET; - return; - } - - // turn towards movement direction if not there yet - if (actor->movedir < NUMDIRS) - { - actor->angle &= (7<<29); - delta = actor->angle - (actor->movedir << 29); - - if (delta > 0) - actor->angle -= ANGLE_45; - else if (delta < 0) - actor->angle += ANGLE_45; - } - - // Is a player on top of us? - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - if (players[i].mo->health <= 0) - continue; - - if (P_AproxDistance(players[i].mo->x - actor->x, players[i].mo->y - actor->y) > actor->radius) - continue; - - if (players[i].mo->z > actor->z + actor->height - 2*FRACUNIT - && players[i].mo->z < actor->z + actor->height + 32*FRACUNIT) - { - // Punch him! - P_SetMobjState(actor, actor->info->meleestate); - S_StartSound(0, sfx_begrnd); // warning sound - return; - } - } - - if (actor->health <= actor->info->damage - && actor->target - && actor->target->player - && (actor->target->player->powers[pw_carry] == CR_GENERIC)) - { - A_FaceTarget(actor); - P_SetMobjState(actor, S_BLACKEGG_SHOOT1); - actor->movecount = TICRATE + P_RandomByte()/2; - return; - } - - if (actor->reactiontime) - actor->reactiontime--; - - if (actor->reactiontime <= 0 && actor->z == actor->floorz) - { - // Here, we'll call P_RandomByte() and decide what kind of attack to do - switch(actor->threshold) - { - case 0: // Lob cannon balls - if (actor->z < 1056*FRACUNIT) - { - A_FaceTarget(actor); - P_SetMobjState(actor, actor->info->xdeathstate); - actor->movecount = 7*TICRATE + P_RandomByte(); - break; - } - actor->threshold++; - /* FALLTHRU */ - case 1: // Chaingun Goop - A_FaceTarget(actor); - P_SetMobjState(actor, S_BLACKEGG_SHOOT1); - - if (actor->health > actor->info->damage) - actor->movecount = TICRATE + P_RandomByte()/3; - else - actor->movecount = TICRATE + P_RandomByte()/2; - break; - case 2: // Homing Missile - A_FaceTarget(actor); - P_SetMobjState(actor, actor->info->missilestate); - S_StartSound(0, sfx_beflap); - break; - } - - actor->threshold++; - actor->threshold %= 3; - return; - } - - // possibly choose another target - if (multiplayer && (actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) - && P_BossTargetPlayer(actor, false)) - return; // got a new target - - if (leveltime & 1) - { - // chase towards player - if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) - P_NewChaseDir(actor); - } -} - -// Function: A_GoopSplat -// -// Description: Black Eggman goop hits a target and sticks around for awhile. -// -// var1 = unused -// var2 = unused -// -void A_GoopSplat(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_GoopSplat", actor)) - return; -#endif - P_UnsetThingPosition(actor); - if (sector_list) - { - P_DelSeclist(sector_list); - sector_list = NULL; - } - actor->flags = MF_SPECIAL; // Not a typo - P_SetThingPosition(actor); -} - -// Function: A_Boss2PogoSFX -// -// Description: Pogoing for Boss 2 -// -// var1 = pogo jump strength -// var2 = idle pogo speed -// -void A_Boss2PogoSFX(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Boss2PogoSFX", actor)) - return; -#endif - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { - // look for a new target - if (P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - return; - } - - // Boing! - if (P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) < FixedMul(256*FRACUNIT, actor->scale)) - { - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); - P_InstaThrust(actor, actor->angle, FixedMul(actor->info->speed, actor->scale)); - // pogo on player - } - else - { - UINT8 prandom = P_RandomByte(); - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom); - P_InstaThrust(actor, actor->angle, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale)); - } - if (actor->info->activesound) S_StartSound(actor, actor->info->activesound); - actor->momz = FixedMul(locvar1, actor->scale); // Bounce up in air - actor->reactiontime = 1; -} - -// Function: A_Boss2PogoTarget -// -// Description: Pogoing for Boss 2, tries to actually land on the player directly. -// -// var1 = pogo jump strength -// var2 = idle pogo speed -// -void A_Boss2PogoTarget(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Boss2PogoTarget", actor)) - return; -#endif - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE) || (actor->target->player && actor->target->player->powers[pw_flashing]) - || P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) >= FixedMul(512*FRACUNIT, actor->scale)) - { - // look for a new target - if (P_LookForPlayers(actor, true, false, 512*FRACUNIT)) - ; // got a new target - else if (P_LookForPlayers(actor, true, false, 0)) - ; // got a new target - else - return; - } - - // Target hit, retreat! - if (actor->target->player->powers[pw_flashing] > TICRATE || actor->flags2 & MF2_FRET) - { - UINT8 prandom = P_RandomByte(); - actor->z++; // unstick from the floor - actor->momz = FixedMul(locvar1, actor->scale); // Bounce up in air - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom); // Pick a direction, and randomize it. - P_InstaThrust(actor, actor->angle+ANGLE_180, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale)); // Move at wandering speed - } - // Try to land on top of the player. - else if (P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) < FixedMul(512*FRACUNIT, actor->scale)) - { - fixed_t airtime, gravityadd, zoffs; - - // check gravity in the sector (for later math) - P_CheckGravity(actor, true); - gravityadd = actor->momz; - - actor->z++; // unstick from the floor - actor->momz = FixedMul(locvar1 + (locvar1>>2), actor->scale); // Bounce up in air - - /*badmath = 0; - airtime = 0; - do { - badmath += momz; - momz += gravityadd; - airtime++; - } while(badmath > 0); - airtime = 2*airtime<momz<<1, gravityadd)<<1; // going from 0 to 0 is much simpler - zoffs = (P_GetPlayerHeight(actor->target->player)>>1) + (actor->target->floorz - actor->floorz); // offset by the difference in floor height plus half the player height, - airtime = FixedDiv((-actor->momz - FixedSqrt(FixedMul(actor->momz,actor->momz)+zoffs)), gravityadd)<<1; // to try and land on their head rather than on their feet - - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); - P_InstaThrust(actor, actor->angle, FixedDiv(P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y), airtime)); - } - // Wander semi-randomly towards the player to get closer. - else - { - UINT8 prandom = P_RandomByte(); - actor->z++; // unstick from the floor - actor->momz = FixedMul(locvar1, actor->scale); // Bounce up in air - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom); // Pick a direction, and randomize it. - P_InstaThrust(actor, actor->angle, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale)); // Move at wandering speed - } - // Boing! - if (actor->info->activesound) S_StartSound(actor, actor->info->activesound); - - if (actor->info->missilestate) // spawn the pogo stick collision box - { - mobj_t *pogo = P_SpawnMobj(actor->x, actor->y, actor->z - mobjinfo[actor->info->missilestate].height, (mobjtype_t)actor->info->missilestate); - pogo->target = actor; - } - - actor->reactiontime = 1; -} - -// Function: A_EggmanBox -// -// Description: Harms the player -// -// var1 = unused -// var2 = unused -// -void A_EggmanBox(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_EggmanBox", actor)) - return; -#endif - if (!actor->target || !actor->target->player) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); - return; - } - - P_DamageMobj(actor->target, actor, actor, 1, 0); // Ow! -} - -// Function: A_TurretFire -// -// Description: Initiates turret fire. -// -// var1 = object # to repeatedly fire -// var2 = distance threshold -// -void A_TurretFire(mobj_t *actor) -{ - INT32 count = 0; - fixed_t dist; - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_TurretFire", actor)) - return; -#endif - - if (locvar2) - dist = FixedMul(locvar2*FRACUNIT, actor->scale); - else - dist = FixedMul(2048*FRACUNIT, actor->scale); - - if (!locvar1) - locvar1 = MT_TURRETLASER; - - while (P_SupermanLook4Players(actor) && count < MAXPLAYERS) - { - if (P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) < dist) - { - actor->flags2 |= MF2_FIRING; - actor->extravalue1 = locvar1; - break; - } - - count++; - } -} - -// Function: A_SuperTurretFire -// -// Description: Initiates turret fire that even stops Super Sonic. -// -// var1 = object # to repeatedly fire -// var2 = distance threshold -// -void A_SuperTurretFire(mobj_t *actor) -{ - INT32 count = 0; - fixed_t dist; - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SuperTurretFire", actor)) - return; -#endif - - if (locvar2) - dist = FixedMul(locvar2*FRACUNIT, actor->scale); - else - dist = FixedMul(2048*FRACUNIT, actor->scale); - - if (!locvar1) - locvar1 = MT_TURRETLASER; - - while (P_SupermanLook4Players(actor) && count < MAXPLAYERS) - { - if (P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) < dist) - { - actor->flags2 |= MF2_FIRING; - actor->flags2 |= MF2_SUPERFIRE; - actor->extravalue1 = locvar1; - break; - } - - count++; - } -} - -// Function: A_TurretStop -// -// Description: Stops the turret fire. -// -// var1 = Don't play activesound? -// var2 = unused -// -void A_TurretStop(mobj_t *actor) -{ - INT32 locvar1 = var1; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_TurretStop", actor)) - return; -#endif - - actor->flags2 &= ~MF2_FIRING; - actor->flags2 &= ~MF2_SUPERFIRE; - - if (actor->target && actor->info->activesound && !locvar1) - S_StartSound(actor, actor->info->activesound); -} - -// Function: A_SparkFollow -// -// Description: Used by the hyper sparks to rotate around their target. -// -// var1 = unused -// var2 = unused -// -void A_SparkFollow(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SparkFollow", actor)) - return; -#endif - - if ((!actor->target || (actor->target->health <= 0)) - || (actor->target->player && !actor->target->player->powers[pw_super])) - { - P_RemoveMobj(actor); - return; - } - - actor->angle += FixedAngle(actor->info->damage*FRACUNIT); - P_UnsetThingPosition(actor); - { - const angle_t fa = actor->angle>>ANGLETOFINESHIFT; - actor->x = actor->target->x + FixedMul(FINECOSINE(fa),FixedMul(actor->info->speed, actor->scale)); - actor->y = actor->target->y + FixedMul(FINESINE(fa),FixedMul(actor->info->speed, actor->scale)); - if (actor->target->eflags & MFE_VERTICALFLIP) - actor->z = actor->target->z + actor->target->height - FixedDiv(actor->target->height,3*FRACUNIT); - else - actor->z = actor->target->z + FixedDiv(actor->target->height,3*FRACUNIT) - actor->height; - } - P_SetThingPosition(actor); -} - -// Function: A_BuzzFly -// -// Description: Makes an object slowly fly after a player, in the manner of a Buzz. -// -// var1 = sfx to play -// var2 = length of sfx, set to threshold if played -// -void A_BuzzFly(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_BuzzFly", actor)) - return; -#endif - if (actor->flags2 & MF2_AMBUSH) - return; - - if (actor->reactiontime) - actor->reactiontime--; - - // modify target threshold - if (actor->threshold) - { - if (!actor->target || actor->target->health <= 0) - actor->threshold = 0; - else - actor->threshold--; - } - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { - // look for a new target - if (P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - actor->momz = actor->momy = actor->momx = 0; - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - - // turn towards movement direction if not there yet - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); - - if (actor->target->health <= 0 || (!actor->threshold && !P_CheckSight(actor, actor->target))) - { - if ((multiplayer || netgame) && P_LookForPlayers(actor, true, false, FixedMul(3072*FRACUNIT, actor->scale))) - return; // got a new target - - actor->momx = actor->momy = actor->momz = 0; - P_SetMobjState(actor, actor->info->spawnstate); // Go back to looking around - return; - } - - // If the player is over 3072 fracunits away, then look for another player - if (P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), - actor->target->z - actor->z) > FixedMul(3072*FRACUNIT, actor->scale)) - { - if (multiplayer || netgame) - P_LookForPlayers(actor, true, false, FixedMul(3072*FRACUNIT, actor->scale)); // maybe get a new target - - return; - } - - // chase towards player - { - INT32 dist, realspeed; - const fixed_t mf = 5*(FRACUNIT/4); - - if (ultimatemode) - realspeed = FixedMul(FixedMul(actor->info->speed,mf), actor->scale); - else - realspeed = FixedMul(actor->info->speed, actor->scale); - - dist = P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, - actor->target->y - actor->y), actor->target->z - actor->z); - - if (dist < 1) - dist = 1; - - actor->momx = FixedMul(FixedDiv(actor->target->x - actor->x, dist), realspeed); - actor->momy = FixedMul(FixedDiv(actor->target->y - actor->y, dist), realspeed); - actor->momz = FixedMul(FixedDiv(actor->target->z - actor->z, dist), realspeed); - - if (actor->z+actor->momz >= actor->waterbottom && actor->watertop > actor->floorz - && actor->z+actor->momz > actor->watertop - FixedMul(256*FRACUNIT, actor->scale) - && actor->z+actor->momz <= actor->watertop) - { - actor->momz = 0; - actor->z = actor->watertop; - } - } - - if (locvar1 != sfx_None && !actor->threshold) - { - S_StartSound(actor, locvar1); - actor->threshold = locvar2; - } -} - -// Function: A_GuardChase -// -// Description: Modified A_Chase for Egg Guard -// -// var1 = unused -// var2 = unused -// -void A_GuardChase(mobj_t *actor) -{ - INT32 delta; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_GuardChase", actor)) - return; -#endif - - if (actor->reactiontime) - actor->reactiontime--; - - if (actor->threshold != 42) // In formation... - { - fixed_t speed; - - if (!actor->tracer || !actor->tracer->health) - { - P_SetTarget(&actor->tracer, NULL); - actor->threshold = 42; - P_SetMobjState(actor, actor->info->painstate); - actor->flags |= MF_SPECIAL|MF_SHOOTABLE; - return; - } - - speed = actor->extravalue1*actor->scale; - - if (actor->flags2 & MF2_AMBUSH) - speed <<= 1; - - if (speed - && !P_TryMove(actor, - actor->x + P_ReturnThrustX(actor, actor->angle, speed), - actor->y + P_ReturnThrustY(actor, actor->angle, speed), - false) - && speed > 0) // can't be the same check as previous so that P_TryMove gets to happen. - { - if (actor->spawnpoint && ((actor->spawnpoint->options & (MTF_EXTRA|MTF_OBJECTSPECIAL)) == MTF_OBJECTSPECIAL)) - actor->angle += ANGLE_90; - else if (actor->spawnpoint && ((actor->spawnpoint->options & (MTF_EXTRA|MTF_OBJECTSPECIAL)) == MTF_EXTRA)) - actor->angle -= ANGLE_90; - else - actor->angle += ANGLE_180; - } - - if (actor->extravalue1 < actor->info->speed) - actor->extravalue1++; - } - else // Break ranks! - { - // turn towards movement direction if not there yet - if (actor->movedir < NUMDIRS) - { - actor->angle &= (7<<29); - delta = actor->angle - (actor->movedir << 29); - - if (delta > 0) - actor->angle -= ANGLE_45; - else if (delta < 0) - actor->angle += ANGLE_45; - } - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { - // look for a new target - if (P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - P_SetMobjStateNF(actor, actor->info->spawnstate); - return; - } - - // possibly choose another target - if (multiplayer && (actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) - && P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - // chase towards player - if (--actor->movecount < 0 || !P_Move(actor, (actor->flags2 & MF2_AMBUSH) ? actor->info->speed * 2 : actor->info->speed)) - { - P_NewChaseDir(actor); - actor->movecount += 5; // Increase tics before change in direction allowed. - } - } - - // Now that we've moved, its time for our shield to move! - // Otherwise it'll never act as a proper overlay. - if (actor->tracer && actor->tracer->state - && actor->tracer->state->action.acp1) - { - var1 = actor->tracer->state->var1, var2 = actor->tracer->state->var2; - actor->tracer->state->action.acp1(actor->tracer); - } -} - -// Function: A_EggShield -// -// Description: Modified A_Chase for Egg Guard's shield -// -// var1 = unused -// var2 = unused -// -void A_EggShield(mobj_t *actor) -{ - INT32 i; - player_t *player; - fixed_t blockdist; - fixed_t newx, newy; - fixed_t movex, movey; - angle_t angle; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_EggShield", actor)) - return; -#endif - - if (!actor->target || !actor->target->health) - { - P_RemoveMobj(actor); - return; - } - - newx = actor->target->x + P_ReturnThrustX(actor, actor->target->angle, FixedMul(FRACUNIT, actor->scale)); - newy = actor->target->y + P_ReturnThrustY(actor, actor->target->angle, FixedMul(FRACUNIT, actor->scale)); - - movex = newx - actor->x; - movey = newy - actor->y; - - actor->angle = actor->target->angle; - if (actor->target->eflags & MFE_VERTICALFLIP) - { - actor->eflags |= MFE_VERTICALFLIP; - actor->z = actor->target->z + actor->target->height - actor->height; - } - else - actor->z = actor->target->z; - - actor->destscale = actor->target->destscale; - P_SetScale(actor, actor->target->scale); - - actor->floorz = actor->target->floorz; - actor->ceilingz = actor->target->ceilingz; - - if (!movex && !movey) - return; - - P_UnsetThingPosition(actor); - actor->x = newx; - actor->y = newy; - P_SetThingPosition(actor); - - // Search for players to push - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - player = &players[i]; - - if (!player->mo) - continue; - - if (player->mo->z > actor->z + actor->height) - continue; - - if (player->mo->z + player->mo->height < actor->z) - continue; - - blockdist = actor->radius + player->mo->radius; - - if (abs(actor->x - player->mo->x) >= blockdist || abs(actor->y - player->mo->y) >= blockdist) - continue; // didn't hit it - - angle = R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y) - actor->angle; - - if (angle > ANGLE_90 && angle < ANGLE_270) - continue; - - // Blocked by the shield - player->mo->momx += movex; - player->mo->momy += movey; - return; - } -} - - -// Function: A_SetReactionTime -// -// Description: Sets the object's reaction time. -// -// var1 = 1 (use value in var2); 0 (use info table value) -// var2 = if var1 = 1, then value to set -// -void A_SetReactionTime(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SetReactionTime", actor)) - return; -#endif - if (var1) - actor->reactiontime = var2; - else - actor->reactiontime = actor->info->reactiontime; -} - -// Function: A_Boss1Spikeballs -// -// Description: Boss 1 spikeball spawning loop. -// -// var1 = ball number -// var2 = total balls -// -void A_Boss1Spikeballs(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - mobj_t *ball; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Boss1Spikeballs", actor)) - return; -#endif - - ball = P_SpawnMobj(actor->x, actor->y, actor->z, MT_EGGMOBILE_BALL); - P_SetTarget(&ball->target, actor); - ball->movedir = FixedAngle(FixedMul(FixedDiv(locvar1<threshold = ball->radius + actor->radius + ball->info->painchance; - - S_StartSound(ball, ball->info->seesound); - var1 = ball->state->var1, var2 = ball->state->var2; - ball->state->action.acp1(ball); -} - -// Function: A_Boss3TakeDamage -// -// Description: Called when Boss 3 takes damage. -// -// var1 = movecount value -// var2 = unused -// -void A_Boss3TakeDamage(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Boss3TakeDamage", actor)) - return; -#endif - actor->movecount = var1; - - if (actor->target && actor->target->spawnpoint) - actor->threshold = actor->target->spawnpoint->extrainfo; -} - -// Function: A_Boss3Path -// -// Description: Does pathfinding along Boss 3's nodes. -// -// var1 = unused -// var2 = unused -// -void A_Boss3Path(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Boss3Path", actor)) - return; -#endif - - if (actor->tracer && actor->tracer->health && actor->tracer->movecount) - actor->movecount |= 1; - else if (actor->movecount & 1) - actor->movecount = 0; - - if (actor->movecount & 2) // We've reached a firing point? - { - // Wait here and pretend to be angry or something. - actor->momx = 0; - actor->momy = 0; - actor->momz = 0; - P_SetTarget(&actor->target, actor->tracer->target); - var1 = 0, var2 = 0; - A_FaceTarget(actor); - if (actor->tracer->state == &states[actor->tracer->info->missilestate]) - P_SetMobjState(actor, actor->info->missilestate); - return; - } - else if (actor->threshold >= 0) // Traveling mode - { - thinker_t *th; - mobj_t *mo2; - fixed_t dist, dist2; - fixed_t speed; - - P_SetTarget(&actor->target, NULL); - - // scan the thinkers - // to find a point that matches - // the number - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && mo2->spawnpoint->angle == actor->threshold) - { - P_SetTarget(&actor->target, mo2); - break; - } - } - - if (!actor->target) // Should NEVER happen - { - CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 Dummy was unable to find specified waypoint: %d\n", actor->threshold); - return; - } - - dist = P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), actor->target->z - actor->z); - - if (dist < 1) - dist = 1; - - if (actor->tracer && ((actor->tracer->movedir) - || (actor->tracer->health <= actor->tracer->info->damage))) - speed = actor->info->speed * 2; - else - speed = actor->info->speed; - - actor->momx = FixedMul(FixedDiv(actor->target->x - actor->x, dist), speed); - actor->momy = FixedMul(FixedDiv(actor->target->y - actor->y, dist), speed); - actor->momz = FixedMul(FixedDiv(actor->target->z - actor->z, dist), speed); - - if (actor->momx != 0 || actor->momy != 0) - actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); - - dist2 = P_AproxDistance(P_AproxDistance(actor->target->x - (actor->x + actor->momx), actor->target->y - (actor->y + actor->momy)), actor->target->z - (actor->z + actor->momz)); - - if (dist2 < 1) - dist2 = 1; - - if ((dist >> FRACBITS) <= (dist2 >> FRACBITS)) - { - // If further away, set XYZ of mobj to waypoint location - P_UnsetThingPosition(actor); - actor->x = actor->target->x; - actor->y = actor->target->y; - actor->z = actor->target->z; - actor->momx = actor->momy = actor->momz = 0; - P_SetThingPosition(actor); - - if (actor->threshold == 0) - { - P_RemoveMobj(actor); // Cycle completed. Dummy removed. - return; - } - - // Set to next waypoint in sequence - if (actor->target->spawnpoint) - { - // From the center point, choose one of the five paths - if (actor->target->spawnpoint->angle == 0) - { - P_RemoveMobj(actor); // Cycle completed. Dummy removed. - return; - } - else - actor->threshold = actor->target->spawnpoint->extrainfo; - - // If the deaf flag is set, go into firing mode - if (actor->target->spawnpoint->options & MTF_AMBUSH) - actor->movecount |= 2; - } - else // This should never happen, as well - CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 Dummy waypoint has no spawnpoint associated with it.\n"); - } - } -} - -// Function: A_LinedefExecute -// -// Description: Object's location is used to set the calling sector. The tag used is var1. Optionally, if var2 is set, the actor's angle (multiplied by var2) is added to the tag number as well. -// -// var1 = tag -// var2 = add angle to tag (optional) -// -void A_LinedefExecute(mobj_t *actor) -{ - INT32 tagnum; - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_LinedefExecute", actor)) - return; -#endif - - tagnum = locvar1; - // state numbers option is no more, custom states cannot be guaranteed to stay the same number anymore, now that they can be defined by names instead - - if (locvar2) - tagnum += locvar2*(AngleFixed(actor->angle)>>FRACBITS); - - CONS_Debug(DBG_GAMELOGIC, "A_LinedefExecute: Running mobjtype %d's sector with tag %d\n", actor->type, tagnum); - - // tag 32768 displayed in map editors is actually tag -32768, tag 32769 is -32767, 65535 is -1 etc. - P_LinedefExecute((INT16)tagnum, actor, actor->subsector->sector); -} - -// Function: A_PlaySeeSound -// -// Description: Plays the object's seesound. -// -// var1 = unused -// var2 = unused -// -void A_PlaySeeSound(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_PlaySeeSound", actor)) - return; -#endif - if (actor->info->seesound) - S_StartScreamSound(actor, actor->info->seesound); -} - -// Function: A_PlayAttackSound -// -// Description: Plays the object's attacksound. -// -// var1 = unused -// var2 = unused -// -void A_PlayAttackSound(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_PlayAttackSound", actor)) - return; -#endif - if (actor->info->attacksound) - S_StartAttackSound(actor, actor->info->attacksound); -} - -// Function: A_PlayActiveSound -// -// Description: Plays the object's activesound. -// -// var1 = unused -// var2 = unused -// -void A_PlayActiveSound(mobj_t *actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_PlayActiveSound", actor)) - return; -#endif - if (actor->info->activesound) - S_StartSound(actor, actor->info->activesound); -} - -// Function: A_SmokeTrailer -// -// Description: Adds smoke trails to an object. -// -// var1 = object # to spawn as smoke -// var2 = unused -// -void A_SmokeTrailer(mobj_t *actor) -{ - mobj_t *th; - INT32 locvar1 = var1; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SmokeTrailer", actor)) - return; -#endif - - if (leveltime % 4) - return; - - // add the smoke behind the rocket - if (actor->eflags & MFE_VERTICALFLIP) - { - th = P_SpawnMobj(actor->x-actor->momx, actor->y-actor->momy, actor->z + actor->height - FixedMul(mobjinfo[locvar1].height, actor->scale), locvar1); - th->flags2 |= MF2_OBJECTFLIP; - } - else - th = P_SpawnMobj(actor->x-actor->momx, actor->y-actor->momy, actor->z, locvar1); - P_SetObjectMomZ(th, FRACUNIT, false); - th->destscale = actor->scale; - P_SetScale(th, actor->scale); - th->tics -= P_RandomByte() & 3; - if (th->tics < 1) - th->tics = 1; -} - -// Function: A_SpawnObjectAbsolute -// -// Description: Spawns an object at an absolute position -// -// var1: -// var1 >> 16 = x -// var1 & 65535 = y -// var2: -// var2 >> 16 = z -// var2 & 65535 = type -// -void A_SpawnObjectAbsolute(mobj_t *actor) -{ - INT16 x, y, z; // Want to be sure we can use negative values - mobjtype_t type; - mobj_t *mo; - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SpawnObjectAbsolute", actor)) - return; -#endif - - x = (INT16)(locvar1>>16); - y = (INT16)(locvar1&65535); - z = (INT16)(locvar2>>16); - type = (mobjtype_t)(locvar2&65535); - - mo = P_SpawnMobj(x<angle = actor->angle; - - if (actor->eflags & MFE_VERTICALFLIP) - mo->flags2 |= MF2_OBJECTFLIP; -} - -// Function: A_SpawnObjectRelative -// -// Description: Spawns an object relative to the location of the actor -// -// var1: -// var1 >> 16 = x -// var1 & 65535 = y -// var2: -// var2 >> 16 = z -// var2 & 65535 = type -// -void A_SpawnObjectRelative(mobj_t *actor) -{ - INT16 x, y, z; // Want to be sure we can use negative values - mobjtype_t type; - mobj_t *mo; - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SpawnObjectRelative", actor)) - return; -#endif - - CONS_Debug(DBG_GAMELOGIC, "A_SpawnObjectRelative called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); - - x = (INT16)(locvar1>>16); - y = (INT16)(locvar1&65535); - z = (INT16)(locvar2>>16); - type = (mobjtype_t)(locvar2&65535); - - // Spawn objects correctly in reverse gravity. - // NOTE: Doing actor->z + actor->height is the bottom of the object while the object has reverse gravity. - Flame - mo = P_SpawnMobj(actor->x + FixedMul(x<scale), - actor->y + FixedMul(y<scale), - (actor->eflags & MFE_VERTICALFLIP) ? ((actor->z + actor->height - mobjinfo[type].height) - FixedMul(z<scale)) : (actor->z + FixedMul(z<scale)), type); - - // Spawn objects with an angle matching the spawner's, rather than spawning Eastwards - Monster Iestyn - mo->angle = actor->angle; - - if (actor->eflags & MFE_VERTICALFLIP) - mo->flags2 |= MF2_OBJECTFLIP; - -} - -// Function: A_ChangeAngleRelative -// -// Description: Changes the angle to a random relative value between the min and max. Set min and max to the same value to eliminate randomness -// -// var1 = min -// var2 = max -// -void A_ChangeAngleRelative(mobj_t *actor) -{ - // Oh god, the old code /sucked/. Changed this and the absolute version to get a random range using amin and amax instead of - // getting a random angle from the _entire_ spectrum and then clipping. While we're at it, do the angle conversion to the result - // rather than the ranges, so <0 and >360 work as possible values. -Red - INT32 locvar1 = var1; - INT32 locvar2 = var2; - //angle_t angle = (P_RandomByte()+1)<<24; - const fixed_t amin = locvar1*FRACUNIT; - const fixed_t amax = locvar2*FRACUNIT; - //const angle_t amin = FixedAngle(locvar1*FRACUNIT); - //const angle_t amax = FixedAngle(locvar2*FRACUNIT); -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ChangeAngleRelative", actor)) - return; -#endif - -#ifdef PARANOIA - if (amin > amax) - I_Error("A_ChangeAngleRelative: var1 is greater then var2"); -#endif -/* - if (angle < amin) - angle = amin; - if (angle > amax) - angle = amax;*/ - - actor->angle += FixedAngle(P_RandomRange(amin, amax)); -} - -// Function: A_ChangeAngleAbsolute -// -// Description: Changes the angle to a random absolute value between the min and max. Set min and max to the same value to eliminate randomness -// -// var1 = min -// var2 = max -// -void A_ChangeAngleAbsolute(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - //angle_t angle = (P_RandomByte()+1)<<24; - const fixed_t amin = locvar1*FRACUNIT; - const fixed_t amax = locvar2*FRACUNIT; - //const angle_t amin = FixedAngle(locvar1*FRACUNIT); - //const angle_t amax = FixedAngle(locvar2*FRACUNIT); -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ChangeAngleAbsolute", actor)) - return; -#endif - -#ifdef PARANOIA - if (amin > amax) - I_Error("A_ChangeAngleAbsolute: var1 is greater then var2"); -#endif -/* - if (angle < amin) - angle = amin; - if (angle > amax) - angle = amax;*/ - - actor->angle = FixedAngle(P_RandomRange(amin, amax)); -} - -// Function: A_PlaySound -// -// Description: Plays a sound -// -// var1 = sound # to play -// var2: -// 0 = Play sound without an origin -// 1 = Play sound using calling object as origin -// -void A_PlaySound(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_PlaySound", actor)) - return; -#endif - - S_StartSound(locvar2 ? actor : NULL, locvar1); -} - -// Function: A_FindTarget -// -// Description: Finds the nearest/furthest mobj of the specified type and sets actor->target to it. -// -// var1 = mobj type -// var2 = if (0) nearest; else furthest; -// -void A_FindTarget(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - mobj_t *targetedmobj = NULL; - thinker_t *th; - mobj_t *mo2; - fixed_t dist1 = 0, dist2 = 0; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FindTarget", actor)) - return; -#endif - - CONS_Debug(DBG_GAMELOGIC, "A_FindTarget called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); - - // scan the thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type == (mobjtype_t)locvar1) - { - if (mo2->player && (mo2->player->spectator || mo2->player->pflags & PF_INVIS)) - continue; // Ignore spectators - if ((mo2->player || mo2->flags & MF_ENEMY) && mo2->health <= 0) - continue; // Ignore dead things - if (targetedmobj == NULL) - { - targetedmobj = mo2; - dist2 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); - } - else - { - dist1 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); - - if ((!locvar2 && dist1 < dist2) || (locvar2 && dist1 > dist2)) - { - targetedmobj = mo2; - dist2 = dist1; - } - } - } - } - - if (!targetedmobj) - { - CONS_Debug(DBG_GAMELOGIC, "A_FindTarget: Unable to find the specified object to target.\n"); - return; // Oops, nothing found.. - } - - CONS_Debug(DBG_GAMELOGIC, "A_FindTarget: Found a target.\n"); - - P_SetTarget(&actor->target, targetedmobj); -} - -// Function: A_FindTracer -// -// Description: Finds the nearest/furthest mobj of the specified type and sets actor->tracer to it. -// -// var1 = mobj type -// var2 = if (0) nearest; else furthest; -// -void A_FindTracer(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - mobj_t *targetedmobj = NULL; - thinker_t *th; - mobj_t *mo2; - fixed_t dist1 = 0, dist2 = 0; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FindTracer", actor)) - return; -#endif - - CONS_Debug(DBG_GAMELOGIC, "A_FindTracer called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); - - // scan the thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type == (mobjtype_t)locvar1) - { - if (mo2->player && (mo2->player->spectator || mo2->player->pflags & PF_INVIS)) - continue; // Ignore spectators - if ((mo2->player || mo2->flags & MF_ENEMY) && mo2->health <= 0) - continue; // Ignore dead things - if (targetedmobj == NULL) - { - targetedmobj = mo2; - dist2 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); - } - else - { - dist1 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); - - if ((!locvar2 && dist1 < dist2) || (locvar2 && dist1 > dist2)) - { - targetedmobj = mo2; - dist2 = dist1; - } - } - } - } - - if (!targetedmobj) - { - CONS_Debug(DBG_GAMELOGIC, "A_FindTracer: Unable to find the specified object to target.\n"); - return; // Oops, nothing found.. - } - - CONS_Debug(DBG_GAMELOGIC, "A_FindTracer: Found a target.\n"); - - P_SetTarget(&actor->tracer, targetedmobj); -} - -// Function: A_SetTics -// -// Description: Sets the animation tics of an object -// -// var1 = tics to set to -// var2 = if this is set, and no var1 is supplied, the mobj's threshold value will be used. -// -void A_SetTics(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SetTics", actor)) - return; -#endif - - if (locvar1) - actor->tics = locvar1; - else if (locvar2) - actor->tics = actor->threshold; -} - -// Function: A_SetRandomTics -// -// Description: Sets the animation tics of an object to a random value -// -// var1 = lower bound -// var2 = upper bound -// -void A_SetRandomTics(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SetRandomTics", actor)) - return; -#endif - - actor->tics = P_RandomRange(locvar1, locvar2); -} - -// Function: A_ChangeColorRelative -// -// Description: Changes the color of an object -// -// var1 = if (var1 > 0), find target and add its color value to yours -// var2 = if (var1 = 0), color value to add -// -void A_ChangeColorRelative(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ChangeColorRelative", actor)) - return; -#endif - - if (locvar1) - { - // Have you ever seen anything so hideous? - if (actor->target) - actor->color = (UINT8)(actor->color + actor->target->color); - } - else - actor->color = (UINT8)(actor->color + locvar2); -} - -// Function: A_ChangeColorAbsolute -// -// Description: Changes the color of an object by an absolute value. Note: 0 is default colormap. -// -// var1 = if (var1 > 0), set your color to your target's color -// var2 = if (var1 = 0), color value to set to -// -void A_ChangeColorAbsolute(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ChangeColorAbsolute", actor)) - return; -#endif - - if (locvar1) - { - if (actor->target) - actor->color = actor->target->color; - } - else - actor->color = (UINT8)locvar2; -} - -// Function: A_MoveRelative -// -// Description: Moves an object (wrapper for P_Thrust) -// -// var1 = angle -// var2 = force -// -void A_MoveRelative(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_MoveRelative", actor)) - return; -#endif - - P_Thrust(actor, actor->angle+FixedAngle(locvar1*FRACUNIT), FixedMul(locvar2*FRACUNIT, actor->scale)); -} - -// Function: A_MoveAbsolute -// -// Description: Moves an object (wrapper for P_InstaThrust) -// -// var1 = angle -// var2 = force -// -void A_MoveAbsolute(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_MoveAbsolute", actor)) - return; -#endif - - P_InstaThrust(actor, FixedAngle(locvar1*FRACUNIT), FixedMul(locvar2*FRACUNIT, actor->scale)); -} - -// Function: A_Thrust -// -// Description: Pushes the object horizontally at its current angle. -// -// var1 = amount of force -// var2 = If 1, xy momentum is lost. If 0, xy momentum is kept -// -void A_Thrust(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Thrust", actor)) - return; -#endif - - if (!locvar1) - CONS_Debug(DBG_GAMELOGIC, "A_Thrust: Var1 not specified!\n"); - - if (locvar2) - P_InstaThrust(actor, actor->angle, FixedMul(locvar1*FRACUNIT, actor->scale)); - else - P_Thrust(actor, actor->angle, FixedMul(locvar1*FRACUNIT, actor->scale)); -} - -// Function: A_ZThrust -// -// Description: Pushes the object up or down. -// -// var1 = amount of force -// var2: -// lower 16 bits = If 1, xy momentum is lost. If 0, xy momentum is kept -// upper 16 bits = If 1, z momentum is lost. If 0, z momentum is kept -// -void A_ZThrust(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ZThrust", actor)) - return; -#endif - - if (!locvar1) - CONS_Debug(DBG_GAMELOGIC, "A_ZThrust: Var1 not specified!\n"); - - if (locvar2 & 65535) - actor->momx = actor->momy = 0; - - if (actor->eflags & MFE_VERTICALFLIP) - actor->z--; - else - actor->z++; - - P_SetObjectMomZ(actor, locvar1*FRACUNIT, !(locvar2 >> 16)); -} - -// Function: A_SetTargetsTarget -// -// Description: Sets your target to the object who your target is targeting. Yikes! If it happens to be NULL, you're just out of luck. -// -// var1: (Your target) -// 0 = target -// 1 = tracer -// var2: (Your target's target) -// 0 = target/tracer's target -// 1 = target/tracer's tracer -// -void A_SetTargetsTarget(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - mobj_t *oldtarg = NULL, *newtarg = NULL; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SetTargetsTarget", actor)) - return; -#endif - - // actor's target - if (locvar1) // or tracer - oldtarg = actor->tracer; - else - oldtarg = actor->target; - - if (P_MobjWasRemoved(oldtarg)) - return; - - // actor's target's target! - if (locvar2) // or tracer - newtarg = oldtarg->tracer; - else - newtarg = oldtarg->target; - - if (P_MobjWasRemoved(newtarg)) - return; - - // set actor's new target - if (locvar1) // or tracer - P_SetTarget(&actor->tracer, newtarg); - else - P_SetTarget(&actor->target, newtarg); -} - -// Function: A_SetObjectFlags -// -// Description: Sets the flags of an object -// -// var1 = flag value to set -// var2: -// if var2 == 2, add the flag to the current flags -// else if var2 == 1, remove the flag from the current flags -// else if var2 == 0, set the flags to the exact value -// -void A_SetObjectFlags(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - boolean unlinkthings = false; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SetObjectFlags", actor)) - return; -#endif - - if (locvar2 == 2) - locvar1 = actor->flags | locvar1; - else if (locvar2 == 1) - locvar1 = actor->flags & ~locvar1; - - if ((UINT32)(locvar1 & (MF_NOBLOCKMAP|MF_NOSECTOR)) != (actor->flags & (MF_NOBLOCKMAP|MF_NOSECTOR))) // Blockmap/sector status has changed, so reset the links - unlinkthings = true; - - if (unlinkthings) { - P_UnsetThingPosition(actor); - if (sector_list) - { - P_DelSeclist(sector_list); - sector_list = NULL; - } - } - - actor->flags = locvar1; - - if (unlinkthings) - P_SetThingPosition(actor); -} - -// Function: A_SetObjectFlags2 -// -// Description: Sets the flags2 of an object -// -// var1 = flag value to set -// var2: -// if var2 == 2, add the flag to the current flags -// else if var2 == 1, remove the flag from the current flags -// else if var2 == 0, set the flags to the exact value -// -void A_SetObjectFlags2(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SetObjectFlags2", actor)) - return; -#endif - - if (locvar2 == 2) - actor->flags2 |= locvar1; - else if (locvar2 == 1) - actor->flags2 &= ~locvar1; - else - actor->flags2 = locvar1; -} - -// Function: A_BossJetFume -// -// Description: Spawns jet fumes/other attachment miscellany for the boss. To only be used when he is spawned. -// -// var1: -// 0 - Triple jet fume pattern -// 1 - Boss 3's propeller -// 2 - Metal Sonic jet fume -// 3 - Boss 4 jet flame -// var2 = unused -// -void A_BossJetFume(mobj_t *actor) -{ - mobj_t *filler; - INT32 locvar1 = var1; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_BossJetFume", actor)) - return; -#endif - - if (locvar1 == 0) // Boss1 jet fumes - { - fixed_t jetx, jety, jetz; - - jetx = actor->x + P_ReturnThrustX(actor, actor->angle, -FixedMul(64*FRACUNIT, actor->scale)); - jety = actor->y + P_ReturnThrustY(actor, actor->angle, -FixedMul(64*FRACUNIT, actor->scale)); - if (actor->eflags & MFE_VERTICALFLIP) - jetz = actor->z + actor->height - FixedMul(38*FRACUNIT + mobjinfo[MT_JETFUME1].height, actor->scale); - else - jetz = actor->z + FixedMul(38*FRACUNIT, actor->scale); - - filler = P_SpawnMobj(jetx, jety, jetz, MT_JETFUME1); - P_SetTarget(&filler->target, actor); - filler->destscale = actor->scale; - P_SetScale(filler, filler->destscale); - if (actor->eflags & MFE_VERTICALFLIP) - filler->flags2 |= MF2_OBJECTFLIP; - filler->fuse = 56; - - if (actor->eflags & MFE_VERTICALFLIP) - jetz = actor->z + actor->height - FixedMul(12*FRACUNIT + mobjinfo[MT_JETFUME1].height, actor->scale); - else - jetz = actor->z + FixedMul(12*FRACUNIT, actor->scale); - - filler = P_SpawnMobj(jetx + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(24*FRACUNIT, actor->scale)), - jety + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(24*FRACUNIT, actor->scale)), - jetz, MT_JETFUME1); - P_SetTarget(&filler->target, actor); - filler->destscale = actor->scale; - P_SetScale(filler, filler->destscale); - if (actor->eflags & MFE_VERTICALFLIP) - filler->flags2 |= MF2_OBJECTFLIP; - filler->fuse = 57; - - filler = P_SpawnMobj(jetx + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(24*FRACUNIT, actor->scale)), - jety + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(24*FRACUNIT, actor->scale)), - jetz, MT_JETFUME1); - P_SetTarget(&filler->target, actor); - filler->destscale = actor->scale; - P_SetScale(filler, filler->destscale); - if (actor->eflags & MFE_VERTICALFLIP) - filler->flags2 |= MF2_OBJECTFLIP; - filler->fuse = 58; - - P_SetTarget(&actor->tracer, filler); - } - else if (locvar1 == 1) // Boss 3 propeller - { - fixed_t jetx, jety, jetz; - - jetx = actor->x + P_ReturnThrustX(actor, actor->angle, -FixedMul(60*FRACUNIT, actor->scale)); - jety = actor->y + P_ReturnThrustY(actor, actor->angle, -FixedMul(60*FRACUNIT, actor->scale)); - if (actor->eflags & MFE_VERTICALFLIP) - jetz = actor->z + actor->height - FixedMul(17*FRACUNIT + mobjinfo[MT_PROPELLER].height, actor->scale); - else - jetz = actor->z + FixedMul(17*FRACUNIT, actor->scale); - - filler = P_SpawnMobj(jetx, jety, jetz, MT_PROPELLER); - P_SetTarget(&filler->target, actor); - filler->destscale = actor->scale; - P_SetScale(filler, filler->destscale); - if (actor->eflags & MFE_VERTICALFLIP) - filler->flags2 |= MF2_OBJECTFLIP; - filler->angle = actor->angle - ANGLE_180; - - P_SetTarget(&actor->tracer, filler); - } - else if (locvar1 == 2) // Metal Sonic jet fumes - { - filler = P_SpawnMobj(actor->x, actor->y, actor->z, MT_JETFUME1); - P_SetTarget(&filler->target, actor); - filler->fuse = 59; - P_SetTarget(&actor->tracer, filler); - filler->destscale = actor->scale/2; - P_SetScale(filler, filler->destscale); - if (actor->eflags & MFE_VERTICALFLIP) - filler->flags2 |= MF2_OBJECTFLIP; - } - else if (locvar1 == 3) // Boss 4 jet flame - { - fixed_t jetz; - if (actor->eflags & MFE_VERTICALFLIP) - jetz = actor->z + actor->height + FixedMul(50*FRACUNIT - mobjinfo[MT_JETFLAME].height, actor->scale); - else - jetz = actor->z - FixedMul(50*FRACUNIT, actor->scale); - filler = P_SpawnMobj(actor->x, actor->y, jetz, MT_JETFLAME); - P_SetTarget(&filler->target, actor); - // Boss 4 already uses its tracer for other things - filler->destscale = actor->scale; - P_SetScale(filler, filler->destscale); - if (actor->eflags & MFE_VERTICALFLIP) - filler->flags2 |= MF2_OBJECTFLIP; - } -} - -// Function: A_RandomState -// -// Description: Chooses one of the two state numbers supplied randomly. -// -// var1 = state number 1 -// var2 = state number 2 -// -void A_RandomState(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_RandomState", actor)) - return; -#endif - - P_SetMobjState(actor, P_RandomChance(FRACUNIT/2) ? locvar1 : locvar2); -} - -// Function: A_RandomStateRange -// -// Description: Chooses a random state within the range supplied. -// -// var1 = Minimum state number to choose. -// var2 = Maximum state number to use. -// -void A_RandomStateRange(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_RandomStateRange", actor)) - return; -#endif - - P_SetMobjState(actor, P_RandomRange(locvar1, locvar2)); -} - -// Function: A_DualAction -// -// Description: Calls two actions. Be careful, if you reference the same state this action is called from, you can create an infinite loop. -// -// var1 = state # to use 1st action from -// var2 = state # to use 2nd action from -// -void A_DualAction(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_DualAction", actor)) - return; -#endif - - CONS_Debug(DBG_GAMELOGIC, "A_DualAction called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); - - var1 = states[locvar1].var1; - var2 = states[locvar1].var2; -#ifdef HAVE_BLUA - astate = &states[locvar1]; -#endif - - CONS_Debug(DBG_GAMELOGIC, "A_DualAction: Calling First Action (state %d)...\n", locvar1); - states[locvar1].action.acp1(actor); - - var1 = states[locvar2].var1; - var2 = states[locvar2].var2; -#ifdef HAVE_BLUA - astate = &states[locvar2]; -#endif - - CONS_Debug(DBG_GAMELOGIC, "A_DualAction: Calling Second Action (state %d)...\n", locvar2); - states[locvar2].action.acp1(actor); -} - -// Function: A_RemoteAction -// -// Description: var1 is the remote object. var2 is the state reference for calling the action called on var1. var1 becomes the actor's target, the action (var2) is called on var1. actor's target is restored -// -// var1 = remote object (-2 uses tracer, -1 uses target) -// var2 = state reference for calling an action -// -void A_RemoteAction(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - mobj_t *originaltarget = actor->target; // Hold on to the target for later. -#ifdef HAVE_BLUA - if (LUA_CallAction("A_RemoteAction", actor)) - return; -#endif - - // If >=0, find the closest target. - if (locvar1 >= 0) - { - ///* DO A_FINDTARGET STUFF */// - mobj_t *targetedmobj = NULL; - thinker_t *th; - mobj_t *mo2; - fixed_t dist1 = 0, dist2 = 0; - - // scan the thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type == (mobjtype_t)locvar1) - { - if (targetedmobj == NULL) - { - targetedmobj = mo2; - dist2 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); - } - else - { - dist1 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); - - if ((locvar2 && dist1 < dist2) || (!locvar2 && dist1 > dist2)) - { - targetedmobj = mo2; - dist2 = dist1; - } - } - } - } - - if (!targetedmobj) - { - CONS_Debug(DBG_GAMELOGIC, "A_RemoteAction: Unable to find the specified object to target.\n"); - return; // Oops, nothing found.. - } - - CONS_Debug(DBG_GAMELOGIC, "A_RemoteAction: Found a target.\n"); - - P_SetTarget(&actor->target, targetedmobj); - - ///* END A_FINDTARGET STUFF */// - } - - // If -2, use the tracer as the target - else if (locvar1 == -2) - P_SetTarget(&actor->target, actor->tracer); - // if -1 or anything else, just use the target. - - if (actor->target) - { - // Steal the var1 and var2 from "locvar2" - var1 = states[locvar2].var1; - var2 = states[locvar2].var2; -#ifdef HAVE_BLUA - astate = &states[locvar2]; -#endif - - CONS_Debug(DBG_GAMELOGIC, "A_RemoteAction: Calling action on %p\n" - "var1 is %d\nvar2 is %d\n", actor->target, var1, var2); - states[locvar2].action.acp1(actor->target); - } - - P_SetTarget(&actor->target, originaltarget); // Restore the original target. -} - -// Function: A_ToggleFlameJet -// -// Description: Turns a flame jet on and off. -// -// var1 = unused -// var2 = unused -// -void A_ToggleFlameJet(mobj_t* actor) -{ -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ToggleFlameJet", actor)) - return; -#endif - // threshold - off delay - // movecount - on timer - - if (actor->flags2 & MF2_FIRING) - { - actor->flags2 &= ~MF2_FIRING; - - if (actor->threshold) - actor->tics = actor->threshold; - } - else - { - actor->flags2 |= MF2_FIRING; - - if (actor->movecount) - actor->tics = actor->movecount; - } -} - -// Function: A_OrbitNights -// -// Description: Used by Chaos Emeralds to orbit around Nights (aka Super Sonic.) -// -// var1 = Angle adjustment (aka orbit speed) -// var2 = Lower four bits: height offset, Upper 4 bits = set if object is Nightopian Helper -// -void A_OrbitNights(mobj_t* actor) -{ - INT32 ofs = (var2 & 0xFFFF); - boolean ishelper = (var2 & 0xFFFF0000); -#ifdef HAVE_BLUA - if (LUA_CallAction("A_OrbitNights", actor)) - return; -#endif - - if (!actor->target - || (actor->target->player && - // if NiGHTS special stage and not NiGHTSmode. - (((maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && !(actor->target->player->powers[pw_carry] == CR_NIGHTSMODE)) - // Also remove this object if they no longer have a NiGHTS helper - || (ishelper && !actor->target->player->powers[pw_nights_helper])))) - { - P_RemoveMobj(actor); - return; - } - else - { - actor->extravalue1 += var1; - P_UnsetThingPosition(actor); - { - const angle_t fa = (angle_t)actor->extravalue1 >> ANGLETOFINESHIFT; - const angle_t ofa = ((angle_t)actor->extravalue1 + (ofs*ANG1)) >> ANGLETOFINESHIFT; - - const fixed_t fc = FixedMul(FINECOSINE(fa),FixedMul(32*FRACUNIT, actor->scale)); - const fixed_t fh = FixedMul(FINECOSINE(ofa),FixedMul(20*FRACUNIT, actor->scale)); - const fixed_t fs = FixedMul(FINESINE(fa),FixedMul(32*FRACUNIT, actor->scale)); - - actor->x = actor->target->x + fc; - actor->y = actor->target->y + fs; - actor->z = actor->target->z + fh + FixedMul(16*FRACUNIT, actor->scale); - - // Semi-lazy hack - actor->angle = (angle_t)actor->extravalue1 + ANGLE_90; - } - P_SetThingPosition(actor); - - if (ishelper && actor->target->player) // Flash a helper that's about to be removed. - { - if ((actor->target->player->powers[pw_nights_helper] < TICRATE) - && (actor->target->player->powers[pw_nights_helper] & 1)) - actor->flags2 |= MF2_DONTDRAW; - else - actor->flags2 &= ~MF2_DONTDRAW; - } - } -} - -// Function: A_GhostMe -// -// Description: Spawns a "ghost" mobj of this actor, ala spindash trails and the minus's digging "trails" -// -// var1 = duration in tics -// var2 = unused -// -void A_GhostMe(mobj_t *actor) -{ - INT32 locvar1 = var1; - mobj_t *ghost; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_GhostMe", actor)) - return; -#endif - ghost = P_SpawnGhostMobj(actor); - if (ghost && locvar1 > 0) - ghost->fuse = locvar1; -} - -// Function: A_SetObjectState -// -// Description: Changes the state of an object's target/tracer. -// -// var1 = state number -// var2: -// 0 = target -// 1 = tracer -// -void A_SetObjectState(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - mobj_t *target; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SetObjectState", actor)) - return; -#endif - - if ((!locvar2 && !actor->target) || (locvar2 && !actor->tracer)) - { - if (cv_debug) - CONS_Printf("A_SetObjectState: No target to change state!\n"); - return; - } - - if (!locvar2) // target - target = actor->target; - else // tracer - target = actor->tracer; - - if (target->health > 0) - { - if (!target->player) - P_SetMobjState(target, locvar1); - else - P_SetPlayerMobjState(target, locvar1); - } -} - -// Function: A_SetObjectTypeState -// -// Description: Changes the state of all active objects of a certain type in a certain range of the actor. -// -// var1 = state number -// var2: -// lower 16 bits = type -// upper 16 bits = range (if == 0, across whole map) -// -void A_SetObjectTypeState(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - const UINT16 loc2lw = (UINT16)(locvar2 & 65535); - const UINT16 loc2up = (UINT16)(locvar2 >> 16); - - thinker_t *th; - mobj_t *mo2; - fixed_t dist = 0; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SetObjectTypeState", actor)) - return; -#endif - - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type == (mobjtype_t)loc2lw) - { - dist = P_AproxDistance(mo2->x - actor->x, mo2->y - actor->y); - - if (mo2->health > 0) - { - if (loc2up == 0) - P_SetMobjState(mo2, locvar1); - else - { - if (dist <= FixedMul(loc2up*FRACUNIT, actor->scale)) - P_SetMobjState(mo2, locvar1); - } - } - } - } -} - -// Function: A_KnockBack -// -// Description: Knocks back the object's target at its current speed. -// -// var1: -// 0 = target -// 1 = tracer -// var2 = unused -// -void A_KnockBack(mobj_t *actor) -{ - INT32 locvar1 = var1; - mobj_t *target; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_KnockBack", actor)) - return; -#endif - - if (!locvar1) - target = actor->target; - else - target = actor->tracer; - - if (!target) - { - if(cv_debug) - CONS_Printf("A_KnockBack: No target!\n"); - return; - } - - target->momx *= -1; - target->momy *= -1; -} - -// Function: A_PushAway -// -// Description: Pushes an object's target away from the calling object. -// -// var1 = amount of force -// var2: -// lower 16 bits = If 1, xy momentum is lost. If 0, xy momentum is kept -// upper 16 bits = 0 - target, 1 - tracer -// -void A_PushAway(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - mobj_t *target; // target - angle_t an; // actor to target angle -#ifdef HAVE_BLUA - if (LUA_CallAction("A_PushAway", actor)) - return; -#endif - - if ((!(locvar2 >> 16) && !actor->target) || ((locvar2 >> 16) && !actor->tracer)) - return; - - if (!locvar1) - CONS_Printf("A_Thrust: Var1 not specified!\n"); - - if (!(locvar2 >> 16)) // target - target = actor->target; - else // tracer - target = actor->tracer; - - an = R_PointToAngle2(actor->x, actor->y, target->x, target->y); - - if (locvar2 & 65535) - P_InstaThrust(target, an, FixedMul(locvar1*FRACUNIT, actor->scale)); - else - P_Thrust(target, an, FixedMul(locvar1*FRACUNIT, actor->scale)); -} - -// Function: A_RingDrain -// -// Description: Drain targeted player's rings. -// -// var1 = ammount of drained rings -// var2 = unused -// -void A_RingDrain(mobj_t *actor) -{ - INT32 locvar1 = var1; - player_t *player; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_RingDrain", actor)) - return; -#endif - - if (!actor->target || !actor->target->player) - { - if(cv_debug) - CONS_Printf("A_RingDrain: No player targeted!\n"); - return; - } - - player = actor->target->player; - P_GivePlayerRings(player, -min(locvar1, player->rings)); -} - -// Function: A_SplitShot -// -// Description: Shoots 2 missiles that hit next to the player. -// -// var1 = target x-y-offset -// var2: -// lower 16 bits = missile type -// upper 16 bits = height offset -// -void A_SplitShot(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - const UINT16 loc2lw = (UINT16)(locvar2 & 65535); - const UINT16 loc2up = (UINT16)(locvar2 >> 16); - const fixed_t offs = (fixed_t)(locvar1*FRACUNIT); - const fixed_t hoffs = (fixed_t)(loc2up*FRACUNIT); -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SplitShot", actor)) - return; -#endif - - A_FaceTarget(actor); - { - const angle_t an = (actor->angle + ANGLE_90) >> ANGLETOFINESHIFT; - const fixed_t fasin = FINESINE(an); - const fixed_t facos = FINECOSINE(an); - fixed_t xs = FixedMul(facos,FixedMul(offs, actor->scale)); - fixed_t ys = FixedMul(fasin,FixedMul(offs, actor->scale)); - fixed_t z; - - if (actor->eflags & MFE_VERTICALFLIP) - z = actor->z + actor->height - FixedMul(hoffs, actor->scale); - else - z = actor->z + FixedMul(hoffs, actor->scale); - - P_SpawnPointMissile(actor, actor->target->x+xs, actor->target->y+ys, actor->target->z, loc2lw, actor->x, actor->y, z); - P_SpawnPointMissile(actor, actor->target->x-xs, actor->target->y-ys, actor->target->z, loc2lw, actor->x, actor->y, z); - } -} - -// Function: A_MissileSplit -// -// Description: If the object is a missile it will create a new missile with an alternate flight path owned by the one who shot the former missile. -// -// var1 = splitting missile type -// var2 = splitting angle -// -void A_MissileSplit(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_MissileSplit", actor)) - return; -#endif - if (actor->eflags & MFE_VERTICALFLIP) - P_SpawnAlteredDirectionMissile(actor, locvar1, actor->x, actor->y, actor->z+actor->height, locvar2); - else - P_SpawnAlteredDirectionMissile(actor, locvar1, actor->x, actor->y, actor->z, locvar2); -} - -// Function: A_MultiShot -// -// Description: Shoots objects horizontally that spread evenly in all directions. -// -// var1: -// lower 16 bits = number of missiles -// upper 16 bits = missile type # -// var2 = height offset -// -void A_MultiShot(mobj_t *actor) -{ - fixed_t z, xr, yr; - INT32 locvar1 = var1; - INT32 locvar2 = var2; - const UINT16 loc1lw = (UINT16)(locvar1 & 65535); - const UINT16 loc1up = (UINT16)(locvar1 >> 16); - INT32 count = 0; - fixed_t ad; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_MultiShot", actor)) - return; -#endif - - if (actor->target) - A_FaceTarget(actor); - - if(loc1lw > 90) - ad = FixedMul(90*FRACUNIT, actor->scale); - else - ad = FixedMul(loc1lw*FRACUNIT, actor->scale); - - if (actor->eflags & MFE_VERTICALFLIP) - z = actor->z + actor->height - FixedMul(48*FRACUNIT + locvar2*FRACUNIT, actor->scale); - else - z = actor->z + FixedMul(48*FRACUNIT + locvar2*FRACUNIT, actor->scale); - xr = FixedMul((P_SignedRandom()/3)<scale); // please note p_mobj.c's P_Rand() abuse - yr = FixedMul((P_SignedRandom()/3)<scale); // of rand(), RAND_MAX and signness mess - - while(count <= loc1lw && loc1lw >= 1) - { - const angle_t fa = FixedAngleC(count*FRACUNIT*360, ad)>>ANGLETOFINESHIFT; - const fixed_t rc = FINECOSINE(fa); - const fixed_t rs = FINESINE(fa); - const fixed_t xrc = FixedMul(xr, rc); - const fixed_t yrs = FixedMul(yr, rs); - const fixed_t xrs = FixedMul(xr, rs); - const fixed_t yrc = FixedMul(yr, rc); - - P_SpawnPointMissile(actor, xrc-yrs+actor->x, xrs+yrc+actor->y, z, loc1up, actor->x, actor->y, z); - count++; - } - - if (!(actor->flags & MF_BOSS)) - { - if (ultimatemode) - actor->reactiontime = actor->info->reactiontime*TICRATE; - else - actor->reactiontime = actor->info->reactiontime*TICRATE*2; - } -} - -// Function: A_InstaLoop -// -// Description: Makes the object move along a 2d (view angle, z) polygon. -// -// var1: -// lower 16 bits = current step -// upper 16 bits = maximum step # -// var2 = force -// -void A_InstaLoop(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - fixed_t force = max(locvar2, 1)*FRACUNIT; // defaults to 1 if var2 < 1 - const UINT16 loc1lw = (UINT16)(locvar1 & 65535); - const UINT16 loc1up = (UINT16)(locvar1 >> 16); - const angle_t fa = FixedAngleC(loc1lw*FRACUNIT*360, loc1up*FRACUNIT)>>ANGLETOFINESHIFT; - const fixed_t ac = FINECOSINE(fa); - const fixed_t as = FINESINE(fa); -#ifdef HAVE_BLUA - if (LUA_CallAction("A_InstaLoop", actor)) - return; -#endif - - P_InstaThrust(actor, actor->angle, FixedMul(ac, FixedMul(force, actor->scale))); - P_SetObjectMomZ(actor, FixedMul(as, force), false); -} - -// Function: A_Custom3DRotate -// -// Description: Rotates the actor around its target in 3 dimensions. -// -// var1: -// lower 16 bits = radius in fracunits -// upper 16 bits = vertical offset -// var2: -// lower 16 bits = vertical rotation speed in 1/10 fracunits per tic -// upper 16 bits = horizontal rotation speed in 1/10 fracunits per tic -// -void A_Custom3DRotate(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - - const UINT16 loc1lw = (UINT16)(locvar1 & 65535); - const UINT16 loc1up = (UINT16)(locvar1 >> 16); - const UINT16 loc2lw = (UINT16)(locvar2 & 65535); - const UINT16 loc2up = (UINT16)(locvar2 >> 16); - - const fixed_t radius = FixedMul(loc1lw*FRACUNIT, actor->scale); - const fixed_t hOff = FixedMul(loc1up*FRACUNIT, actor->scale); - const fixed_t hspeed = FixedMul(loc2up*FRACUNIT/10, actor->scale); - const fixed_t vspeed = FixedMul(loc2lw*FRACUNIT/10, actor->scale); -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Custom3DRotate", actor)) - return; -#endif - - if (actor->target->health == 0) - { - P_RemoveMobj(actor); - return; - } - - if (!actor->target) // This should NEVER happen. - { - if (cv_debug) - CONS_Printf("Error: Object has no target\n"); - P_RemoveMobj(actor); - return; - } - if (hspeed==0 && vspeed==0) - { - CONS_Printf("Error: A_Custom3DRotate: Object has no speed.\n"); - return; - } - - actor->angle += FixedAngle(hspeed); - actor->movedir += FixedAngle(vspeed); - P_UnsetThingPosition(actor); - { - const angle_t fa = actor->angle>>ANGLETOFINESHIFT; - - if (vspeed == 0 && hspeed != 0) - { - actor->x = actor->target->x + FixedMul(FINECOSINE(fa),radius); - actor->y = actor->target->y + FixedMul(FINESINE(fa),radius); - actor->z = actor->target->z + actor->target->height/2 - actor->height/2 + hOff; - } - else - { - const angle_t md = actor->movedir>>ANGLETOFINESHIFT; - actor->x = actor->target->x + FixedMul(FixedMul(FINESINE(md),FINECOSINE(fa)),radius); - actor->y = actor->target->y + FixedMul(FixedMul(FINESINE(md),FINESINE(fa)),radius); - actor->z = actor->target->z + FixedMul(FINECOSINE(md),radius) + actor->target->height/2 - actor->height/2 + hOff; - } - } - P_SetThingPosition(actor); -} - -// Function: A_SearchForPlayers -// -// Description: Checks if the actor has targeted a vulnerable player. If not a new player will be searched all around. If no players are available the object can call a specific state. (Useful for not moving enemies) -// -// var1: -// if var1 == 0, if necessary call state with same state number as var2 -// else, do not call a specific state if no players are available -// var2 = state number -// -void A_SearchForPlayers(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SearchForPlayers", actor)) - return; -#endif - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { - // look for a new target - if (P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - if(locvar1==0) - { - P_SetMobjStateNF(actor, locvar2); - return; - } - } -} - -// Function: A_CheckRandom -// -// Description: Calls a state by chance. -// -// var1: -// lower 16 bits = denominator -// upper 16 bits = numerator (defaults to 1 if zero) -// var2 = state number -// -void A_CheckRandom(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - fixed_t chance = FRACUNIT; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CheckRandom", actor)) - return; -#endif - if ((locvar1 & 0xFFFF) == 0) - return; - - // The PRNG doesn't suck anymore, OK? - if (locvar1 >> 16) - chance *= (locvar1 >> 16); - chance /= (locvar1 & 0xFFFF); - - if (P_RandomChance(chance)) - P_SetMobjState(actor, locvar2); -} - -// Function: A_CheckTargetRings -// -// Description: Calls a state depending on the ammount of rings currently owned by targeted players. -// -// var1 = if player rings >= var1 call state -// var2 = state number -// -void A_CheckTargetRings(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CheckTargetRings", actor)) - return; -#endif - - if (!(actor->target) || !(actor->target->player)) - return; - - if (actor->target->player->rings >= locvar1) - P_SetMobjState(actor, locvar2); -} - -// Function: A_CheckRings -// -// Description: Calls a state depending on the ammount of rings currently owned by all players. -// -// var1 = if player rings >= var1 call state -// var2 = state number -// -void A_CheckRings(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - INT32 i, cntr = 0; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CheckRings", actor)) - return; -#endif - - for (i = 0; i < MAXPLAYERS; i++) - cntr += players[i].rings; - - if (cntr >= locvar1) - P_SetMobjState(actor, locvar2); -} - -// Function: A_CheckTotalRings -// -// Description: Calls a state depending on the maximum ammount of rings owned by all players during this try. -// -// var1 = if total player rings >= var1 call state -// var2 = state number -// -void A_CheckTotalRings(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - - INT32 i, cntr = 0; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CheckTotalRings", actor)) - return; -#endif - - for (i = 0; i < MAXPLAYERS; i++) - cntr += players[i].totalring; - - if (cntr >= locvar1) - P_SetMobjState(actor, locvar2); -} - -// Function: A_CheckHealth -// -// Description: Calls a state depending on the object's current health. -// -// var1 = if health <= var1 call state -// var2 = state number -// -void A_CheckHealth(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CheckHealth", actor)) - return; -#endif - - if (actor->health <= locvar1) - P_SetMobjState(actor, locvar2); -} - -// Function: A_CheckRange -// -// Description: Calls a state if the object's target is in range. -// -// var1: -// lower 16 bits = range -// upper 16 bits = 0 - target, 1 - tracer -// var2 = state number -// -void A_CheckRange(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - fixed_t dist; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CheckRange", actor)) - return; -#endif - - if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer)) - return; - - if (!(locvar1 >> 16)) //target - dist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); - else //tracer - dist = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y); - - if (dist <= FixedMul((locvar1 & 65535)*FRACUNIT, actor->scale)) - P_SetMobjState(actor, locvar2); -} - -// Function: A_CheckHeight -// -// Description: Calls a state if the object and it's target have a height offset <= var1 compared to each other. -// -// var1: -// lower 16 bits = height offset -// upper 16 bits = 0 - target, 1 - tracer -// var2 = state number -// -void A_CheckHeight(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - fixed_t height; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CheckHeight", actor)) - return; -#endif - - if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer)) - return; - - if (!(locvar1 >> 16)) // target - height = abs(actor->target->z - actor->z); - else // tracer - height = abs(actor->tracer->z - actor->z); - - if (height <= FixedMul((locvar1 & 65535)*FRACUNIT, actor->scale)) - P_SetMobjState(actor, locvar2); -} - -// Function: A_CheckTrueRange -// -// Description: Calls a state if the object's target is in true range. (Checks height, too.) -// -// var1: -// lower 16 bits = range -// upper 16 bits = 0 - target, 1 - tracer -// var2 = state number -// -void A_CheckTrueRange(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - fixed_t height; // vertical range - fixed_t dist; // horizontal range - fixed_t l; // true range -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CheckTrueRange", actor)) - return; -#endif - - if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer)) - return; - - if (!(locvar1 >> 16)) // target - { - height = actor->target->z - actor->z; - dist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); - - } - else // tracer - { - height = actor->tracer->z - actor->z; - dist = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y); - } - - l = P_AproxDistance(dist, height); - - if (l <= FixedMul((locvar1 & 65535)*FRACUNIT, actor->scale)) - P_SetMobjState(actor, locvar2); - -} - -// Function: A_CheckThingCount -// -// Description: Calls a state depending on the number of active things in range. -// -// var1: -// lower 16 bits = number of things -// upper 16 bits = thing type -// var2: -// lower 16 bits = state to call -// upper 16 bits = range (if == 0, check whole map) -// -void A_CheckThingCount(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - - const UINT16 loc1lw = (UINT16)(locvar1 & 65535); - const UINT16 loc1up = (UINT16)(locvar1 >> 16); - const UINT16 loc2lw = (UINT16)(locvar2 & 65535); - const UINT16 loc2up = (UINT16)(locvar2 >> 16); - - INT32 count = 0; - thinker_t *th; - mobj_t *mo2; - fixed_t dist = 0; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CheckThingCount", actor)) - return; -#endif - - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type == (mobjtype_t)loc1up) - { - dist = P_AproxDistance(mo2->x - actor->x, mo2->y - actor->y); - - if (loc2up == 0) - count++; - else - { - if (dist <= FixedMul(loc2up*FRACUNIT, actor->scale)) - count++; - } - } - } - - if(loc1lw <= count) - P_SetMobjState(actor, loc2lw); -} - -// Function: A_CheckAmbush -// -// Description: Calls a state if the actor is behind its targeted player. -// -// var1: -// 0 = target -// 1 = tracer -// var2 = state number -// -void A_CheckAmbush(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - angle_t at; // angle target is currently facing - angle_t atp; // actor to target angle - angle_t an; // angle between at and atp - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CheckAmbush", actor)) - return; -#endif - - if ((!locvar1 && !actor->target) || (locvar1 && !actor->tracer)) - return; - - if (!locvar1) // target - { - at = actor->target->angle; - atp = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); - } - else // tracer - { - at = actor->tracer->angle; - atp = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); - } - - an = atp - at; - - if (an > ANGLE_180) // flip angle if bigger than 180 - an = InvAngle(an); - - if (an < ANGLE_90+ANGLE_22h) // within an angle of 112.5 from each other? - P_SetMobjState(actor, locvar2); -} - -// Function: A_CheckCustomValue -// -// Description: Calls a state depending on the object's custom value. -// -// var1 = if custom value >= var1, call state -// var2 = state number -// -void A_CheckCustomValue(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CheckCustomValue", actor)) - return; -#endif - - if (actor->cusval >= locvar1) - P_SetMobjState(actor, locvar2); -} - -// Function: A_CheckCusValMemo -// -// Description: Calls a state depending on the object's custom memory value. -// -// var1 = if memory value >= var1, call state -// var2 = state number -// -void A_CheckCusValMemo(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CheckCusValMemo", actor)) - return; -#endif - - if (actor->cvmem >= locvar1) - P_SetMobjState(actor, locvar2); -} - -// Function: A_SetCustomValue -// -// Description: Changes the custom value of an object. -// -// var1 = manipulating value -// var2: -// if var2 == 5, multiply the custom value by var1 -// else if var2 == 4, divide the custom value by var1 -// else if var2 == 3, apply modulo var1 to the custom value -// else if var2 == 2, add var1 to the custom value -// else if var2 == 1, substract var1 from the custom value -// else if var2 == 0, replace the custom value with var1 -// -void A_SetCustomValue(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SetCustomValue", actor)) - return; -#endif - - if (cv_debug) - CONS_Printf("Init custom value is %d\n", actor->cusval); - - if (locvar1 == 0 && locvar2 == 4) - return; // DON'T DIVIDE BY ZERO - - // no need for a "temp" value here, just modify the cusval directly - if (locvar2 == 5) // multiply - actor->cusval *= locvar1; - else if (locvar2 == 4) // divide - actor->cusval /= locvar1; - else if (locvar2 == 3) // modulo - actor->cusval %= locvar1; - else if (locvar2 == 2) // add - actor->cusval += locvar1; - else if (locvar2 == 1) // subtract - actor->cusval -= locvar1; - else // replace - actor->cusval = locvar1; - - if(cv_debug) - CONS_Printf("New custom value is %d\n", actor->cusval); -} - -// Function: A_UseCusValMemo -// -// Description: Memorizes or recalls a current custom value. -// -// var1: -// if var1 == 1, manipulate memory value -// else, recall memory value replacing the custom value -// var2: -// if var2 == 5, mem = mem*cv || cv = cv*mem -// else if var2 == 4, mem = mem/cv || cv = cv/mem -// else if var2 == 3, mem = mem%cv || cv = cv%mem -// else if var2 == 2, mem += cv || cv += mem -// else if var2 == 1, mem -= cv || cv -= mem -// else mem = cv || cv = mem -// -void A_UseCusValMemo(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - - INT32 temp = actor->cusval; // value being manipulated - INT32 tempM = actor->cvmem; // value used to manipulate temp with -#ifdef HAVE_BLUA - if (LUA_CallAction("A_UseCusValMemo", actor)) - return; -#endif - - if (locvar1 == 1) // cvmem being changed using cusval - { - temp = actor->cvmem; - tempM = actor->cusval; - } - else // cusval being changed with cvmem - { - temp = actor->cusval; - tempM = actor->cvmem; - } - - if (tempM == 0 && locvar2 == 4) - return; // DON'T DIVIDE BY ZERO - - // now get new value for cusval/cvmem using the other - if (locvar2 == 5) // multiply - temp *= tempM; - else if (locvar2 == 4) // divide - temp /= tempM; - else if (locvar2 == 3) // modulo - temp %= tempM; - else if (locvar2 == 2) // add - temp += tempM; - else if (locvar2 == 1) // subtract - temp -= tempM; - else // replace - temp = tempM; - - // finally, give cusval/cvmem the new value! - if (locvar1 == 1) - actor->cvmem = temp; - else - actor->cusval = temp; -} - -// Function: A_RelayCustomValue -// -// Description: Manipulates the custom value of the object's target/tracer. -// -// var1: -// lower 16 bits: -// if var1 == 0, use own custom value -// else, use var1 value -// upper 16 bits = 0 - target, 1 - tracer -// var2: -// if var2 == 5, multiply the target's custom value by var1 -// else if var2 == 4, divide the target's custom value by var1 -// else if var2 == 3, apply modulo var1 to the target's custom value -// else if var2 == 2, add var1 to the target's custom value -// else if var2 == 1, substract var1 from the target's custom value -// else if var2 == 0, replace the target's custom value with var1 -// -void A_RelayCustomValue(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - - INT32 temp; // reference value - var1 lower 16 bits changes this - INT32 tempT; // target's value - changed to tracer if var1 upper 16 bits set, then modified to become final value -#ifdef HAVE_BLUA - if (LUA_CallAction("A_RelayCustomValue", actor)) - return; -#endif - - if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer)) - return; - - // reference custom value - if ((locvar1 & 65535) == 0) - temp = actor->cusval; // your own custom value - else - temp = (locvar1 & 65535); // var1 value - - if (!(locvar1 >> 16)) // target's custom value - tempT = actor->target->cusval; - else // tracer's custom value - tempT = actor->tracer->cusval; - - if (temp == 0 && locvar2 == 4) - return; // DON'T DIVIDE BY ZERO - - // now get new cusval using target's and the reference - if (locvar2 == 5) // multiply - tempT *= temp; - else if (locvar2 == 4) // divide - tempT /= temp; - else if (locvar2 == 3) // modulo - tempT %= temp; - else if (locvar2 == 2) // add - tempT += temp; - else if (locvar2 == 1) // subtract - tempT -= temp; - else // replace - tempT = temp; - - // finally, give target/tracer the new cusval! - if (!(locvar1 >> 16)) // target - actor->target->cusval = tempT; - else // tracer - actor->tracer->cusval = tempT; -} - -// Function: A_CusValAction -// -// Description: Calls an action from a reference state applying custom value parameters. -// -// var1 = state # to use action from -// var2: -// if var2 == 5, only replace new action's var2 with memory value -// else if var2 == 4, only replace new action's var1 with memory value -// else if var2 == 3, replace new action's var2 with custom value and var1 with memory value -// else if var2 == 2, replace new action's var1 with custom value and var2 with memory value -// else if var2 == 1, only replace new action's var2 with custom value -// else if var2 == 0, only replace new action's var1 with custom value -// -void A_CusValAction(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CusValAction", actor)) - return; -#endif - - if (locvar2 == 5) - { - var1 = states[locvar1].var1; - var2 = (INT32)actor->cvmem; - } - else if (locvar2 == 4) - { - var1 = (INT32)actor->cvmem; - var2 = states[locvar1].var2; - } - else if (locvar2 == 3) - { - var1 = (INT32)actor->cvmem; - var2 = (INT32)actor->cusval; - } - else if (locvar2 == 2) - { - var1 = (INT32)actor->cusval; - var2 = (INT32)actor->cvmem; - } - else if (locvar2 == 1) - { - var1 = states[locvar1].var1; - var2 = (INT32)actor->cusval; - } - else - { - var1 = (INT32)actor->cusval; - var2 = states[locvar1].var2; - } - -#ifdef HAVE_BLUA - astate = &states[locvar1]; -#endif - states[locvar1].action.acp1(actor); -} - -// Function: A_ForceStop -// -// Description: Actor immediately stops its current movement. -// -// var1: -// if var1 == 0, stop x-y-z-movement -// else, stop x-y-movement only -// var2 = unused -// -void A_ForceStop(mobj_t *actor) -{ - INT32 locvar1 = var1; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ForceStop", actor)) - return; -#endif - - actor->momx = actor->momy = 0; - if (locvar1 == 0) - actor->momz = 0; -} - -// Function: A_ForceWin -// -// Description: Makes all players win the level. -// -// var1 = unused -// var2 = unused -// -void A_ForceWin(mobj_t *actor) -{ - INT32 i; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ForceWin", actor)) - return; -#else - (void)actor; -#endif - - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && ((players[i].mo && players[i].mo->health) - || ((netgame || multiplayer) && (players[i].lives || players[i].continues)))) - break; - } - - if (i == MAXPLAYERS) - return; - - for (i = 0; i < MAXPLAYERS; i++) - P_DoPlayerExit(&players[i]); -} - -// Function: A_SpikeRetract -// -// Description: Toggles actor solid flag. -// -// var1: -// if var1 == 0, actor no collide -// else, actor solid -// var2 = unused -// -void A_SpikeRetract(mobj_t *actor) -{ - INT32 locvar1 = var1; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SpikeRetract", actor)) - return; -#endif - - if (actor->flags & MF_NOBLOCKMAP) - return; - - if (locvar1 == 0) - { - actor->flags &= ~MF_SOLID; - actor->flags |= MF_NOCLIPTHING; - } - else - { - actor->flags |= MF_SOLID; - actor->flags &= ~MF_NOCLIPTHING; - } - if (actor->flags & MF_SOLID) - P_CheckPosition(actor, actor->x, actor->y); -} - -// Function: A_InfoState -// -// Description: Set mobj state to one predefined in mobjinfo. -// -// var1: -// if var1 == 0, set actor to spawnstate -// else if var1 == 1, set actor to seestate -// else if var1 == 2, set actor to meleestate -// else if var1 == 3, set actor to missilestate -// else if var1 == 4, set actor to deathstate -// else if var1 == 5, set actor to xdeathstate -// else if var1 == 6, set actor to raisestate -// var2 = unused -// -void A_InfoState(mobj_t *actor) -{ - INT32 locvar1 = var1; - switch (locvar1) - { - case 0: - if (actor->state != &states[actor->info->spawnstate]) - P_SetMobjState(actor, actor->info->spawnstate); - break; - case 1: - if (actor->state != &states[actor->info->seestate]) - P_SetMobjState(actor, actor->info->seestate); - break; - case 2: - if (actor->state != &states[actor->info->meleestate]) - P_SetMobjState(actor, actor->info->meleestate); - break; - case 3: - if (actor->state != &states[actor->info->missilestate]) - P_SetMobjState(actor, actor->info->missilestate); - break; - case 4: - if (actor->state != &states[actor->info->deathstate]) - P_SetMobjState(actor, actor->info->deathstate); - break; - case 5: - if (actor->state != &states[actor->info->xdeathstate]) - P_SetMobjState(actor, actor->info->xdeathstate); - break; - case 6: - if (actor->state != &states[actor->info->raisestate]) - P_SetMobjState(actor, actor->info->raisestate); - break; - default: - break; - } -} - -// Function: A_Repeat -// -// Description: Returns to state var2 until animation has been used var1 times, then continues to nextstate. -// -// var1 = repeat count -// var2 = state to return to if extravalue2 > 0 -// -void A_Repeat(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Repeat", actor)) - return; -#endif - - if (locvar1 && (!actor->extravalue2 || actor->extravalue2 > locvar1)) - actor->extravalue2 = locvar1; - - if (--actor->extravalue2 > 0) - P_SetMobjState(actor, locvar2); -} - -// Function: A_SetScale -// -// Description: Changes the scale of the actor or its target/tracer -// -// var1 = new scale (1*FRACUNIT = 100%) -// var2: -// upper 16 bits: 0 = actor, 1 = target, 2 = tracer -// lower 16 bits: 0 = instant change, 1 = smooth change -// -void A_SetScale(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - mobj_t *target; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SetScale", actor)) - return; -#endif - - if (locvar1 <= 0) - { - if(cv_debug) - CONS_Printf("A_SetScale: Valid scale not specified!\n"); - return; - } - - if ((locvar2>>16) == 1) - target = actor->target; - else if ((locvar2>>16) == 2) - target = actor->tracer; - else // default to yourself! - target = actor; - - if (!target) - { - if(cv_debug) - CONS_Printf("A_SetScale: No target!\n"); - return; - } - - target->destscale = locvar1; // destination scale - if (!(locvar2 & 65535)) - P_SetScale(target, locvar1); // this instantly changes current scale to var1 if used, if not destscale will alter scale to var1 anyway -} - -// Function: A_RemoteDamage -// -// Description: Damages, kills or even removes either the actor or its target/tracer. Actor acts as the inflictor/source unless harming itself -// -// var1 = Mobj affected: 0 - actor, 1 - target, 2 - tracer -// var2 = Action: 0 - Damage, 1 - Kill, 2 - Remove -// -void A_RemoteDamage(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - mobj_t *target; // we MUST have a target - mobj_t *source = NULL; // on the other hand we don't necessarily need a source -#ifdef HAVE_BLUA - if (LUA_CallAction("A_RemoteDamage", actor)) - return; -#endif - if (locvar1 == 1) - target = actor->target; - else if (locvar1 == 2) - target = actor->tracer; - else // default to yourself! - target = actor; - - if (locvar1 == 1 || locvar1 == 2) - source = actor; - - if (!target) - { - if(cv_debug) - CONS_Printf("A_RemoteDamage: No target!\n"); - return; - } - - if (locvar2 == 1) // Kill mobj! - { - if (target->player) // players die using P_DamageMobj instead for some reason - P_DamageMobj(target, source, source, 1, DMG_INSTAKILL); - else - P_KillMobj(target, source, source, 0); - } - else if (locvar2 == 2) // Remove mobj! - { - if (target->player) //don't remove players! - return; - - P_RemoveMobj(target); - } - else // default: Damage mobj! - P_DamageMobj(target, source, source, 1, 0); -} - -// Function: A_HomingChase -// -// Description: Actor chases directly towards its destination object -// -// var1 = speed multiple -// var2 = destination: 0 = target, 1 = tracer -// -void A_HomingChase(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - mobj_t *dest; - fixed_t dist; - fixed_t speedmul; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_HomingChase", actor)) - return; -#endif - - if (locvar2 == 1) - dest = actor->tracer; - else //default - dest = actor->target; - - if (!dest || !dest->health) - return; - - actor->angle = R_PointToAngle2(actor->x, actor->y, dest->x, dest->y); - - dist = P_AproxDistance(P_AproxDistance(dest->x - actor->x, dest->y - actor->y), dest->z - actor->z); - - if (dist < 1) - dist = 1; - - speedmul = FixedMul(locvar1, actor->scale); - - actor->momx = FixedMul(FixedDiv(dest->x - actor->x, dist), speedmul); - actor->momy = FixedMul(FixedDiv(dest->y - actor->y, dist), speedmul); - actor->momz = FixedMul(FixedDiv(dest->z - actor->z, dist), speedmul); -} - -// Function: A_TrapShot -// -// Description: Fires a missile in a particular direction and angle rather than AT something, Trapgoyle-style! -// -// var1: -// lower 16 bits = object # to fire -// upper 16 bits = front offset -// var2: -// lower 15 bits = vertical angle variable -// 16th bit: -// - 0: use vertical angle variable as vertical angle in degrees -// - 1: mimic P_SpawnXYZMissile -// use z of actor minus z of missile as vertical distance to cover during momz calculation -// use vertical angle variable as horizontal distance to cover during momz calculation -// upper 16 bits = height offset -// -void A_TrapShot(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - boolean oldstyle = (locvar2 & 32768) ? true : false; - mobjtype_t type = (mobjtype_t)(locvar1 & 65535); - mobj_t *missile; - INT16 frontoff = (INT16)(locvar1 >> 16); - INT16 vertoff = (INT16)(locvar2 >> 16); - fixed_t x, y, z; - fixed_t speed; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_TrapShot", actor)) - return; -#endif - - x = actor->x + P_ReturnThrustX(actor, actor->angle, FixedMul(frontoff*FRACUNIT, actor->scale)); - y = actor->y + P_ReturnThrustY(actor, actor->angle, FixedMul(frontoff*FRACUNIT, actor->scale)); - - if (actor->eflags & MFE_VERTICALFLIP) - z = actor->z + actor->height - FixedMul(vertoff*FRACUNIT, actor->scale) - FixedMul(mobjinfo[type].height, actor->scale); - else - z = actor->z + FixedMul(vertoff*FRACUNIT, actor->scale); - - CONS_Debug(DBG_GAMELOGIC, "A_TrapShot: missile no. = %d, front offset = %d, vertical angle = %d, z offset = %d\n", - type, frontoff, (INT16)(locvar2 & 65535), vertoff); - - missile = P_SpawnMobj(x, y, z, type); - - if (actor->eflags & MFE_VERTICALFLIP) - missile->flags2 |= MF2_OBJECTFLIP; - - missile->destscale = actor->scale; - P_SetScale(missile, actor->scale); - - if (missile->info->seesound) - S_StartSound(missile, missile->info->seesound); - - P_SetTarget(&missile->target, actor); - missile->angle = actor->angle; - - speed = FixedMul(missile->info->speed, missile->scale); - - if (oldstyle) - { - missile->momx = FixedMul(FINECOSINE(missile->angle>>ANGLETOFINESHIFT), speed); - missile->momy = FixedMul(FINESINE(missile->angle>>ANGLETOFINESHIFT), speed); - // The below line basically mimics P_SpawnXYZMissile's momz calculation. - missile->momz = (actor->z + ((actor->eflags & MFE_VERTICALFLIP) ? actor->height : 0) - z) / ((fixed_t)(locvar2 & 32767)*FRACUNIT / speed); - P_CheckMissileSpawn(missile); - } - else - { - angle_t vertang = FixedAngle(((INT16)(locvar2 & 32767))*FRACUNIT); - if (actor->eflags & MFE_VERTICALFLIP) - vertang = InvAngle(vertang); // flip firing angle - missile->momx = FixedMul(FINECOSINE(vertang>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(missile->angle>>ANGLETOFINESHIFT), speed)); - missile->momy = FixedMul(FINECOSINE(vertang>>ANGLETOFINESHIFT), FixedMul(FINESINE(missile->angle>>ANGLETOFINESHIFT), speed)); - missile->momz = FixedMul(FINESINE(vertang>>ANGLETOFINESHIFT), speed); - } -} - -// Function: A_VileTarget -// -// Description: Spawns an object directly on the target, and sets this object as the actor's tracer. -// Originally used by Archviles to summon a pillar of hellfire, hence the name. -// -// var1 = mobj to spawn -// var2 = If 0, target only the actor's target. Else, target every player, period. -// -void A_VileTarget(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - mobj_t *fog; - mobjtype_t fogtype; - INT32 i; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_VileTarget", actor)) - return; -#endif - - if (!actor->target) - return; - - A_FaceTarget(actor); - - // Determine object to spawn - if (locvar1 <= 0 || locvar1 >= NUMMOBJTYPES) - fogtype = MT_CYBRAKDEMON_TARGET_RETICULE; - else - fogtype = (mobjtype_t)locvar1; - - if (!locvar2) - { - fog = P_SpawnMobj(actor->target->x, - actor->target->y, - actor->target->z + ((actor->target->eflags & MFE_VERTICALFLIP) ? actor->target->height - mobjinfo[fogtype].height : 0), - fogtype); - if (actor->target->eflags & MFE_VERTICALFLIP) - { - fog->eflags |= MFE_VERTICALFLIP; - fog->flags2 |= MF2_OBJECTFLIP; - } - fog->destscale = actor->target->scale; - P_SetScale(fog, fog->destscale); - - P_SetTarget(&actor->tracer, fog); - P_SetTarget(&fog->target, actor); - P_SetTarget(&fog->tracer, actor->target); - A_VileFire(fog); - } - else - { - // Our "Archvile" here is actually Oprah. "YOU GET A TARGET! YOU GET A TARGET! YOU ALL GET A TARGET!" - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - if (!players[i].mo->health) - continue; - - fog = P_SpawnMobj(players[i].mo->x, - players[i].mo->y, - players[i].mo->z + ((players[i].mo->eflags & MFE_VERTICALFLIP) ? players[i].mo->height - mobjinfo[fogtype].height : 0), - fogtype); - if (players[i].mo->eflags & MFE_VERTICALFLIP) - { - fog->eflags |= MFE_VERTICALFLIP; - fog->flags2 |= MF2_OBJECTFLIP; - } - fog->destscale = players[i].mo->scale; - P_SetScale(fog, fog->destscale); - - if (players[i].mo == actor->target) // We only care to track the fog targeting who we REALLY hate right now - P_SetTarget(&actor->tracer, fog); - P_SetTarget(&fog->target, actor); - P_SetTarget(&fog->tracer, players[i].mo); - A_VileFire(fog); - } - } -} - -// Function: A_VileAttack -// -// Description: Instantly hurts the actor's target, if it's in the actor's line of sight. -// Originally used by Archviles to cause explosions where their hellfire pillars were, hence the name. -// -// var1 = sound to play -// var2: -// Lower 16 bits = optional explosion object -// Upper 16 bits = If 0, attack only the actor's target. Else, attack all the players. All of them. -// -void A_VileAttack(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - sfxenum_t soundtoplay; - mobjtype_t explosionType = MT_NULL; - mobj_t *fire; - INT32 i; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_VileAttack", actor)) - return; -#endif - - if (!actor->target) - return; - - A_FaceTarget(actor); - - if (locvar1 <= 0 || locvar1 >= NUMSFX) - soundtoplay = sfx_brakrx; - else - soundtoplay = (sfxenum_t)locvar1; - - if ((locvar2 & 0xFFFF) > 0 && (locvar2 & 0xFFFF) <= NUMMOBJTYPES) - { - explosionType = (mobjtype_t)(locvar2 & 0xFFFF); - } - - if (!(locvar2 & 0xFFFF0000)) { - if (!P_CheckSight(actor, actor->target)) - return; - - S_StartSound(actor, soundtoplay); - P_DamageMobj(actor->target, actor, actor, 1, 0); - //actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; // How id did it - actor->target->momz += FixedMul(10*FRACUNIT, actor->scale)*P_MobjFlip(actor->target); // How we're doing it - if (explosionType != MT_NULL) - { - P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, explosionType); - } - - // Extra attack. This was for additional damage in Doom. Doesn't really belong in SRB2, but the heck with it, it's here anyway. - fire = actor->tracer; - - if (!fire) - return; - - // move the fire between the vile and the player - //fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]); - //fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]); - P_TeleportMove(fire, - actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), - actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), - fire->z); - P_RadiusAttack(fire, actor, 70*FRACUNIT, 0); - } - else - { - // Oprahvile strikes again, but this time, she brings HOT PAIN - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - if (!players[i].mo->health) - continue; - - if (!P_CheckSight(actor, players[i].mo)) - continue; - - S_StartSound(actor, soundtoplay); - P_DamageMobj(players[i].mo, actor, actor, 1, 0); - //actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; // How id did it - players[i].mo->momz += FixedMul(10*FRACUNIT, actor->scale)*P_MobjFlip(players[i].mo); // How we're doing it - if (explosionType != MT_NULL) - { - P_SpawnMobj(players[i].mo->x, players[i].mo->y, players[i].mo->z, explosionType); - } - - // Extra attack. This was for additional damage in Doom. Doesn't really belong in SRB2, but the heck with it, it's here anyway. - // However, it ONLY applies to the actor's target. Nobody else matters! - if (actor->target != players[i].mo) - continue; - - fire = actor->tracer; - - if (!fire) - continue; - - // move the fire between the vile and the player - //fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]); - //fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]); - P_TeleportMove(fire, - actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), - actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), - fire->z); - P_RadiusAttack(fire, actor, 70*FRACUNIT, 0); - } - } - -} - -// Function: A_VileFire -// -// Description: Kind of like A_CapeChase; keeps this object in front of its tracer, unless its target can't see it. -// Originally used by Archviles to keep their hellfire pillars on top of the player, hence the name (although it was just "A_Fire" there; added "Vile" to make it more specific). -// Added some functionality to optionally draw a line directly to the enemy doing the targetting. Y'know, to hammer things in a bit. -// -// var1 = sound to play -// var2: -// Lower 16 bits = mobj to spawn (0 doesn't spawn a line at all) -// Upper 16 bits = # to spawn (default is 8) -// -void A_VileFire(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - mobj_t *dest; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_VileFire", actor)) - return; -#endif - - dest = actor->tracer; - if (!dest) - return; - - // don't move it if the vile lost sight - if (!P_CheckSight(actor->target, dest)) - return; - - // keep to same scale and gravity as tracer ALWAYS - actor->destscale = dest->scale; - P_SetScale(actor, actor->destscale); - if (dest->eflags & MFE_VERTICALFLIP) - { - actor->eflags |= MFE_VERTICALFLIP; - actor->flags2 |= MF2_OBJECTFLIP; - } - else - { - actor->eflags &= ~MFE_VERTICALFLIP; - actor->flags2 &= ~MF2_OBJECTFLIP; - } - - P_UnsetThingPosition(actor); - actor->x = dest->x + P_ReturnThrustX(actor, dest->angle, FixedMul(24*FRACUNIT, actor->scale)); - actor->y = dest->y + P_ReturnThrustY(actor, dest->angle, FixedMul(24*FRACUNIT, actor->scale)); - actor->z = dest->z + ((actor->eflags & MFE_VERTICALFLIP) ? dest->height-actor->height : 0); - P_SetThingPosition(actor); - - // Play sound, if one's specified - if (locvar1 > 0 && locvar1 < NUMSFX) - S_StartSound(actor, (sfxenum_t)locvar1); - - // Now draw the line to the actor's target - if (locvar2 & 0xFFFF) - { - mobjtype_t lineMobj; - UINT16 numLineMobjs; - fixed_t distX; - fixed_t distY; - fixed_t distZ; - UINT16 i; - - lineMobj = (mobjtype_t)(locvar2 & 0xFFFF); - numLineMobjs = (UINT16)(locvar2 >> 16); - if (numLineMobjs == 0) { - numLineMobjs = 8; - } - - // Get distance for each step - distX = (actor->target->x - actor->x) / numLineMobjs; - distY = (actor->target->y - actor->y) / numLineMobjs; - distZ = ((actor->target->z + FixedMul(actor->target->height/2, actor->target->scale)) - (actor->z + FixedMul(actor->height/2, actor->scale))) / numLineMobjs; - - for (i = 1; i <= numLineMobjs; i++) - { - P_SpawnMobj(actor->x + (distX * i), actor->y + (distY * i), actor->z + (distZ * i) + FixedMul(actor->height/2, actor->scale), lineMobj); - } - } -} - -// Function: A_BrakChase -// -// Description: Chase after your target, but speed and attack are tied to health. -// -// Every time this is called, generate a random number from a 1/4 to 3/4 of mobj's spawn health. -// If health is above that value, use missilestate to attack. -// If health is at or below that value, use meleestate to attack (default to missile state if not available). -// -// Likewise, state will linearly speed up as health goes down. -// Upper bound will be the frame's normal length. -// Lower bound defaults to 1 tic (technically 0, but we round up), unless a lower bound is specified in var1. -// -// var1 = lower-bound of frame length, in tics -// var2 = optional sound to play -// -void A_BrakChase(mobj_t *actor) -{ - INT32 delta; - INT32 lowerbound; - INT32 newtics; - INT32 locvar1 = var1; - INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_BrakChase", actor)) - return; -#endif - - // Set new tics NOW, in case the state changes while we're doing this and we try applying this to the painstate or something silly - if (actor->tics > 1 && locvar1 < actor->tics) // Not much point, otherwise - { - if (locvar1 < 0) - lowerbound = 0; - else - lowerbound = locvar1; - - newtics = (((actor->tics - lowerbound) * actor->health) / actor->info->spawnhealth) + lowerbound; - if (newtics < 1) - newtics = 1; - - actor->tics = newtics; - } - - if (actor->reactiontime) - { - actor->reactiontime--; - if (actor->reactiontime == 0 && actor->type == MT_CYBRAKDEMON) - S_StartSound(0, sfx_bewar1 + P_RandomKey(4)); - } - - // modify target threshold - if (actor->threshold) - { - if (!actor->target || actor->target->health <= 0) - actor->threshold = 0; - else - actor->threshold--; - } - - // turn towards movement direction if not there yet - if (actor->movedir < NUMDIRS) - { - actor->angle &= (7<<29); - delta = actor->angle - (actor->movedir << 29); - - if (delta > 0) - actor->angle -= ANGLE_45; - else if (delta < 0) - actor->angle += ANGLE_45; - } - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { - // look for a new target - if (P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - P_SetMobjStateNF(actor, actor->info->spawnstate); - return; - } - - // do not attack twice in a row - if (actor->flags2 & MF2_JUSTATTACKED) - { - actor->flags2 &= ~MF2_JUSTATTACKED; - P_NewChaseDir(actor); - return; - } - - // Check if we can attack - if (P_CheckMissileRange(actor) && !actor->movecount) - { - // Check if we should use "melee" attack first. (Yes, this still runs outside of melee range. Quiet, you.) - if (actor->info->meleestate - && actor->health <= P_RandomRange(actor->info->spawnhealth/4, (actor->info->spawnhealth * 3)/4)) // Guaranteed true if <= 1/4 health, guaranteed false if > 3/4 health - { - if (actor->info->attacksound) - S_StartAttackSound(actor, actor->info->attacksound); - - P_SetMobjState(actor, actor->info->meleestate); - actor->flags2 |= MF2_JUSTATTACKED; - return; - } - // Else, check for missile attack. - else if (actor->info->missilestate) - { - P_SetMobjState(actor, actor->info->missilestate); - actor->flags2 |= MF2_JUSTATTACKED; - return; - } - } - - // possibly choose another target - if (multiplayer && !actor->threshold && (actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) - && P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - // chase towards player - if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) - P_NewChaseDir(actor); - - // Optionally play a sound effect - if (locvar2 > 0 && locvar2 < NUMSFX) - S_StartSound(actor, (sfxenum_t)locvar2); - - // make active sound - if (actor->type != MT_CYBRAKDEMON && actor->info->activesound && P_RandomChance(3*FRACUNIT/256)) - { - S_StartSound(actor, actor->info->activesound); - } -} - -// Function: A_BrakFireShot -// -// Description: Shoot an object at your target, offset to match where Brak's gun is. -// Also, sets Brak's reaction time; behaves normally otherwise. -// -// var1 = object # to shoot -// var2 = unused -// -void A_BrakFireShot(mobj_t *actor) -{ - fixed_t x, y, z; - INT32 locvar1 = var1; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_BrakFireShot", actor)) - return; -#endif - if (!actor->target) - return; - - A_FaceTarget(actor); - - x = actor->x - + P_ReturnThrustX(actor, actor->angle, FixedMul(64*FRACUNIT, actor->scale)) - + P_ReturnThrustX(actor, actor->angle+ANGLE_270, FixedMul(32*FRACUNIT, actor->scale)); - y = actor->y - + P_ReturnThrustY(actor, actor->angle, FixedMul(64*FRACUNIT, actor->scale)) - + P_ReturnThrustY(actor, actor->angle+ANGLE_270, FixedMul(32*FRACUNIT, actor->scale)); - if (actor->eflags & MFE_VERTICALFLIP) - z = actor->z + actor->height - FixedMul(144*FRACUNIT, actor->scale); - else - z = actor->z + FixedMul(144*FRACUNIT, actor->scale); - - P_SpawnXYZMissile(actor, actor->target, locvar1, x, y, z); - - if (!(actor->flags & MF_BOSS)) - { - if (ultimatemode) - actor->reactiontime = actor->info->reactiontime*TICRATE; - else - actor->reactiontime = actor->info->reactiontime*TICRATE*2; - } -} - -// Function: A_BrakLobShot -// -// Description: Lobs an object at the floor about a third of the way toward your target. -// Implication is it'll bounce the rest of the way. -// (You can also just aim straight at the target, but whatever) -// Formula grabbed from http://en.wikipedia.org/wiki/Trajectory_of_a_projectile#Angle_required_to_hit_coordinate_.28x.2Cy.29 -// -// var1 = object # to lob -// var2: -// Lower 16 bits: height offset to shoot from, from the actor's bottom (none that "airtime" malarky) -// Upper 16 bits: if 0, aim 1/3 of the way. Else, aim directly at target. -// - -void A_BrakLobShot(mobj_t *actor) -{ - fixed_t v; // Velocity to shoot object - fixed_t a1, a2, aToUse; // Velocity squared - fixed_t g; // Gravity - fixed_t x; // Horizontal difference - INT32 x_int; // x! But in integer form! - fixed_t y; // Vertical difference (yes that's normally z in SRB2 shut up) - INT32 y_int; // y! But in integer form! - INT32 intHypotenuse; // x^2 + y^2. Frequently overflows fixed point, hence why we need integers proper. - fixed_t fixedHypotenuse; // However, we can work around that and still get a fixed-point number. - angle_t theta; // Angle of attack - mobjtype_t typeOfShot; - mobj_t *shot; // Object to shoot - fixed_t newTargetX; // If not aiming directly - fixed_t newTargetY; // If not aiming directly - INT32 locvar1 = var1; - INT32 locvar2 = var2 & 0x0000FFFF; - INT32 aimDirect = var2 & 0xFFFF0000; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_BrakLobShot", actor)) - return; -#endif - - if (!actor->target) - return; // Don't even bother if we've got nothing to aim at. - - // Look up actor's current gravity situation - if (actor->subsector->sector->gravity) - g = FixedMul(gravity,(FixedDiv(*actor->subsector->sector->gravity>>FRACBITS, 1000))); - else - g = gravity; - - // Look up distance between actor and its target - x = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); - if (!aimDirect) - { - // Distance should actually be a third of the way over - x = FixedDiv(x, 3<x + P_ReturnThrustX(actor, actor->angle, x); - newTargetY = actor->y + P_ReturnThrustY(actor, actor->angle, x); - x = P_AproxDistance(newTargetX - actor->x, newTargetY - actor->y); - // Look up height difference between actor and the ground 1/3 of the way to its target - y = P_FloorzAtPos(newTargetX, newTargetY, actor->target->z, actor->target->height) - (actor->z + FixedMul(locvar2*FRACUNIT, actor->scale)); - } - else - { - // Look up height difference between actor and its target - y = actor->target->z - (actor->z + FixedMul(locvar2*FRACUNIT, actor->scale)); - } - - // Get x^2 + y^2. Have to do it in a roundabout manner, because this overflows fixed_t way too easily otherwise. - x_int = x>>FRACBITS; - y_int = y>>FRACBITS; - intHypotenuse = (x_int*x_int) + (y_int*y_int); - fixedHypotenuse = FixedSqrt(intHypotenuse) *256; - - // a = g(y+/-sqrt(x^2+y^2)). a1 can be +, a2 can be -. - a1 = FixedMul(g,y+fixedHypotenuse); - a2 = FixedMul(g,y-fixedHypotenuse); - - // Determine which one isn't actually an imaginary number (or the smaller of the two, if both are real), and use that for v. - if (a1 < 0 || a2 < 0) - { - if (a1 < 0 && a2 < 0) - { - //Somehow, v^2 is negative in both cases. v is therefore imaginary and something is horribly wrong. Abort! - return; - } - // Just find which one's NOT negative, and use that - aToUse = max(a1,a2); - } - else - { - // Both are positive; use whichever's smaller so it can decay faster - aToUse = min(a1,a2); - } - v = FixedSqrt(aToUse); - // Okay, so we know the velocity. Let's actually find theta. - // We can cut the "+/- sqrt" part out entirely, since v was calculated specifically for it to equal zero. So: - //theta = tantoangle[FixedDiv(aToUse,FixedMul(g,x)) >> DBITS]; - theta = tantoangle[SlopeDiv(aToUse,FixedMul(g,x))]; - - // Okay, complicated math done. Let's fire our object already, sheesh. - A_FaceTarget(actor); - if (locvar1 <= 0 || locvar1 >= NUMMOBJTYPES) - typeOfShot = MT_CANNONBALL; - else typeOfShot = (mobjtype_t)locvar1; - shot = P_SpawnMobj(actor->x, actor->y, actor->z + FixedMul(locvar2*FRACUNIT, actor->scale), typeOfShot); - if (shot->info->seesound) - S_StartSound(shot, shot->info->seesound); - P_SetTarget(&shot->target, actor); // where it came from - - shot->angle = actor->angle; - - // Horizontal axes first. First parameter is initial horizontal impulse, second is to correct its angle. - shot->momx = FixedMul(FixedMul(v, FINECOSINE(theta >> ANGLETOFINESHIFT)), FINECOSINE(shot->angle >> ANGLETOFINESHIFT)); - shot->momy = FixedMul(FixedMul(v, FINECOSINE(theta >> ANGLETOFINESHIFT)), FINESINE(shot->angle >> ANGLETOFINESHIFT)); - // Then the vertical axis. No angle-correction needed here. - shot->momz = FixedMul(v, FINESINE(theta >> ANGLETOFINESHIFT)); - // I hope that's all that's needed, ugh -} - -// Function: A_NapalmScatter -// -// Description: Scatters a specific number of projectiles around in a circle. -// Intended for use with objects that are affected by gravity; would be kind of silly otherwise. -// -// var1: -// Lower 16 bits: object # to lob (TODO: come up with a default) -// Upper 16 bits: Number to lob (default 8) -// var2: -// Lower 16 bits: distance to toss them (No default - 0 does just that - but negatives will revert to 128) -// Upper 16 bits: airtime in tics (default 16) -// -void A_NapalmScatter(mobj_t *actor) -{ - mobjtype_t typeOfShot = var1 & 0x0000FFFF; // Type - INT32 numToShoot = (var1 & 0xFFFF0000) >> 16; // How many - fixed_t distance = (var2 & 0x0000FFFF) << FRACBITS; // How far - fixed_t airtime = var2 & 0xFFFF0000; // How long until impact (assuming no obstacles) - fixed_t vx; // Horizontal momentum - fixed_t vy; // Vertical momentum - fixed_t g; // Gravity - INT32 i; // for-loop cursor - mobj_t *mo; // each and every spawned napalm burst - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_NapalmScatter", actor)) - return; -#endif - - // Some quick sanity-checking - if (typeOfShot >= NUMMOBJTYPES) // I'd add a <0 check, too, but 0x0000FFFF isn't negative in this case - typeOfShot = MT_NULL; - if (numToShoot <= 0) // Presumably you forgot to set var1 up; else, why are you calling this to shoot nothing? - numToShoot = 8; - else if (numToShoot > 8192) // If you seriously need this many objects spawned, stop and ask yourself "Why am I doing this?" - numToShoot = 8192; - if (distance < 0) // Presumably you thought this was an unsigned integer, you naive fool - distance = 32767<subsector->sector->gravity) - g = FixedMul(gravity,(FixedDiv(*actor->subsector->sector->gravity>>FRACBITS, 1000))); - else - g = gravity; - - // vy = (g*(airtime-1))/2 - vy = FixedMul(g,(airtime-(1<>1; - // vx = distance/airtime - vx = FixedDiv(distance, airtime); - - for (i = 0; ix, actor->y, actor->z, typeOfShot); - P_SetTarget(&mo->target, actor->target); // Transfer target so Brak doesn't hit himself like an idiot - - mo->angle = fa << ANGLETOFINESHIFT; - mo->momx = FixedMul(FINECOSINE(fa),vx); - mo->momy = FixedMul(FINESINE(fa),vx); - mo->momz = vy; - } -} - -// Function: A_SpawnFreshCopy -// -// Description: Spawns a copy of the mobj. x, y, z, angle, scale, target and tracer carry over; everything else starts anew. -// Mostly writing this because I want to do multiple actions to pass these along in a single frame instead of several. -// -// var1 = unused -// var2 = unused -// -void A_SpawnFreshCopy(mobj_t *actor) -{ - mobj_t *newObject; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SpawnFreshCopy", actor)) - return; -#endif - - newObject = P_SpawnMobjFromMobj(actor, 0, 0, 0, actor->type); - newObject->flags2 = actor->flags2 & MF2_AMBUSH; - newObject->angle = actor->angle; - newObject->color = actor->color; - P_SetTarget(&newObject->target, actor->target); - P_SetTarget(&newObject->tracer, actor->tracer); - - if (newObject->info->seesound) - S_StartSound(newObject, newObject->info->seesound); -} - -// Internal Flicky spawning function. -mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz, boolean lookforplayers) -{ - mobj_t *flicky; - - if (!flickytype) - { - if (!mapheaderinfo[gamemap-1] || !mapheaderinfo[gamemap-1]->numFlickies) // No mapheader, no shoes, no service. - return NULL; - else - { - INT32 prandom = P_RandomKey(mapheaderinfo[gamemap-1]->numFlickies); - flickytype = mapheaderinfo[gamemap-1]->flickies[prandom]; - } - } - - flicky = P_SpawnMobjFromMobj(actor, 0, 0, 0, flickytype); - flicky->angle = actor->angle; - - if (flickytype == MT_SEED) - flicky->z += P_MobjFlip(actor)*(actor->height - flicky->height)/2; - - if (actor->eflags & MFE_UNDERWATER) - momz = FixedDiv(momz, FixedSqrt(3*FRACUNIT)); - - P_SetObjectMomZ(flicky, momz, false); - flicky->movedir = (P_RandomChance(FRACUNIT/2) ? -1 : 1); - flicky->fuse = P_RandomRange(595, 700); // originally 300, 350 - flicky->threshold = 0; - - if (lookforplayers) - P_LookForPlayers(flicky, true, false, 0); - - return flicky; -} - -// Function: A_FlickySpawn -// -// Description: Flicky spawning function. -// -// var1: -// lower 16 bits: if 0, spawns random flicky based on level header. Else, spawns the designated thing type. -// upper 16 bits: if 0, no sound is played. Else, A_Scream is called. -// var2 = upwards thrust for spawned flicky. If zero, default value is provided. -// -void A_FlickySpawn(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FlickySpawn", actor)) - return; -#endif - - if (locvar1 >> 16) { - A_Scream(actor); // A shortcut for the truly lazy. - locvar1 &= 65535; - } - - P_InternalFlickySpawn(actor, locvar1, ((locvar2) ? locvar2 : 8*FRACUNIT), true); -} - -// Internal Flicky color setting -void P_InternalFlickySetColor(mobj_t *actor, UINT8 extrainfo) -{ - UINT8 flickycolors[] = { - SKINCOLOR_RED, - SKINCOLOR_CYAN, - SKINCOLOR_BLUE, - SKINCOLOR_VAPOR, - SKINCOLOR_PURPLE, - SKINCOLOR_BUBBLEGUM, - SKINCOLOR_NEON, - SKINCOLOR_BLACK, - SKINCOLOR_BEIGE, - SKINCOLOR_LAVENDER, - SKINCOLOR_RUBY, - SKINCOLOR_SALMON, - SKINCOLOR_SUNSET, - SKINCOLOR_ORANGE, - SKINCOLOR_YELLOW, - }; - - if (extrainfo == 0) - // until we can customize flicky colors by level header, just stick to SRB2's defaults - actor->color = flickycolors[P_RandomKey(2)]; //flickycolors[P_RandomKey(sizeof(flickycolors))]; - else - actor->color = flickycolors[min(extrainfo-1, 14)]; // sizeof(flickycolors)-1 -} - -// Function: A_FlickyCenter -// -// Description: Place flickies in-level. -// -// var1: -// Lower 16 bits = if 0, spawns random flicky based on level header. Else, spawns the designated thing type. -// Bits 17-20 = Flicky color, up to 15. Applies to fish. -// Bit 21 = Flag MF_SLIDEME (see below) -// Bit 22 = Flag MF_GRENADEBOUNCE (see below) -// Bit 23 = Flag MF_NOCLIPTHING (see below) -// -// If actor is placed from a spawnpoint (map Thing), the Thing's properties take precedence. -// -// var2 = maximum default distance away from spawn the flickies are allowed to travel. If angle != 0, then that's the radius. -// -// If MTF_EXTRA (MF_SLIDEME): is flagged, Flickies move aimlessly. Else, orbit around the target. -// If MTF_OBJECTSPECIAL (MF_GRENADEBOUNCE): Flickies stand in-place without gravity (unless they hop, then gravity is applied.) -// If MTF_AMBUSH (MF_NOCLIPTHING): is flagged, Flickies hop. -// -void A_FlickyCenter(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - UINT16 flickytype = (locvar1 & 0xFFFF); - UINT8 flickycolor = ((locvar1 >> 16) & 0xFF); - UINT8 flickyflags = ((locvar1 >> 20) & 0xF); -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FlickyCenter", actor)) - return; -#endif - - if (!actor->tracer) - { - mobj_t *flicky = P_InternalFlickySpawn(actor, locvar1, 1, false); - P_SetTarget(&flicky->target, actor); - P_SetTarget(&actor->tracer, flicky); - - if (actor->spawnpoint) - { - actor->flags &= ~(MF_SLIDEME|MF_GRENADEBOUNCE|MF_NOCLIPTHING); - actor->flags |= ( - ((actor->spawnpoint->options & MTF_EXTRA) ? MF_SLIDEME : 0) - | ((actor->spawnpoint->options & MTF_OBJECTSPECIAL) ? MF_GRENADEBOUNCE : 0) - | ((actor->spawnpoint->options & MTF_AMBUSH) ? MF_NOCLIPTHING : 0) - ); - actor->extravalue1 = actor->spawnpoint->angle ? abs(actor->spawnpoint->angle) * FRACUNIT - : locvar2 ? abs(locvar2) : 384 * FRACUNIT; - actor->extravalue2 = actor->spawnpoint->extrainfo; - actor->friction = actor->spawnpoint->x*FRACUNIT; - actor->movefactor = actor->spawnpoint->y*FRACUNIT; - actor->watertop = actor->spawnpoint->z*FRACUNIT; - } - else - { - actor->flags &= ~(MF_SLIDEME|MF_GRENADEBOUNCE|MF_NOCLIPTHING); - actor->flags |= ( - ((flickyflags & 1) ? MF_SLIDEME : 0) - | ((flickyflags & 2) ? MF_GRENADEBOUNCE : 0) - | ((flickyflags & 4) ? MF_NOCLIPTHING : 0) - ); - actor->extravalue1 = abs(locvar2); - actor->extravalue2 = flickycolor; - actor->friction = actor->x; - actor->movefactor = actor->y; - actor->watertop = actor->z; - locvar1 = flickytype; - } - - if (actor->flags & MF_GRENADEBOUNCE) // in-place - actor->tracer->fuse = 0; - else if (actor->flags & MF_SLIDEME) // aimless - { - actor->tracer->fuse = 0; // less than 2*TICRATE means move aimlessly. - actor->tracer->angle = P_RandomKey(180)*ANG2; - } - else //orbit - actor->tracer->fuse = FRACUNIT; - - if (locvar1 == MT_FLICKY_08) - P_InternalFlickySetColor(actor->tracer, actor->extravalue2); - - actor->extravalue2 = 0; - } - - if (!(actor->flags & MF_SLIDEME) && !(actor->flags & MF_GRENADEBOUNCE)) - { - fixed_t originx = actor->friction; - fixed_t originy = actor->movefactor; - fixed_t originz = actor->watertop; - - actor->tracer->fuse = FRACUNIT; - - // Impose default home radius if flicky orbits around player - if (!actor->extravalue1) - actor->extravalue1 = locvar2 ? abs(locvar2) : 384 * FRACUNIT; - - P_LookForPlayers(actor, true, false, actor->extravalue1); - - if (actor->target && P_AproxDistance(actor->target->x - originx, actor->target->y - originy) < actor->extravalue1) - { - actor->extravalue2 = 1; - P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z); - } - else if(actor->extravalue2) - { - actor->extravalue2 = 0; - P_TeleportMove(actor, originx, originy, originz); - } - } -} - -// Internal Flicky bubbling function. -void P_InternalFlickyBubble(mobj_t *actor) -{ - if (actor->eflags & MFE_UNDERWATER) - { - mobj_t *overlay; - - if (!((actor->z + 3*actor->height/2) < actor->watertop) || !mobjinfo[actor->type].raisestate || actor->tracer) - return; - - overlay = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY); - P_SetMobjStateNF(overlay, mobjinfo[actor->type].raisestate); - P_SetTarget(&actor->tracer, overlay); - P_SetTarget(&overlay->target, actor); - return; - } - - if (!actor->tracer || P_MobjWasRemoved(actor->tracer)) - return; - - P_RemoveMobj(actor->tracer); - P_SetTarget(&actor->tracer, NULL); -} - -// Function: A_FlickyAim -// -// Description: Flicky aiming function. -// -// var1 = how far around the target (in angle constants) the flicky should look -// var2 = distance from target to aim for -// -void A_FlickyAim(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - boolean flickyhitwall = false; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FlickyAim", actor)) - return; -#endif - - if ((actor->momx == actor->momy && actor->momy == 0) - || (actor->target && P_IsFlickyCenter(actor->target->type) - && actor->target->extravalue1 && (actor->target->flags & MF_SLIDEME) - && P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) >= actor->target->extravalue1)) - flickyhitwall = true; - - P_InternalFlickyBubble(actor); - P_InstaThrust(actor, 0, 0); - - if (!actor->target) - { - P_LookForPlayers(actor, true, false, 0); - actor->angle = P_RandomKey(36)*ANG10; - return; - } - - if (actor->fuse > 2*TICRATE) - { - angle_t posvar; - fixed_t chasevar, chasex, chasey; - - if (flickyhitwall) - actor->movedir *= -1; - - posvar = ((R_PointToAngle2(actor->target->x, actor->target->y, actor->x, actor->y) + actor->movedir*locvar1) >> ANGLETOFINESHIFT) & FINEMASK; - chasevar = FixedSqrt(max(FRACUNIT, P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y) - locvar2)) + locvar2; - - chasex = actor->target->x + FixedMul(FINECOSINE(posvar), chasevar); - chasey = actor->target->y + FixedMul(FINESINE(posvar), chasevar); - - if (P_AproxDistance(chasex - actor->x, chasey - actor->y)) - actor->angle = R_PointToAngle2(actor->x, actor->y, chasex, chasey); - } - else if (flickyhitwall) - { - if (actor->target && P_IsFlickyCenter(actor->target->type)) - actor->angle = R_PointToAngle2(actor->target->x, actor->target->y, actor->x, actor->y) + P_RandomRange(112, 248) * ANG1; - else - actor->angle += P_RandomRange(112, 248)*ANG1; - actor->threshold = 0; - } -} - -//Internal Flicky flying function. Also usuable as an underwater swim thrust. -void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fixed_t chasez) -{ - angle_t vertangle; - - flyspeed = FixedMul(flyspeed, actor->scale); - actor->flags |= MF_NOGRAVITY; - - var1 = ANG30; - var2 = 32*FRACUNIT; - A_FlickyAim(actor); - - chasez *= 8; - if (!actor->target || !(actor->fuse > 2*TICRATE)) - chasez += ((actor->eflags & MFE_VERTICALFLIP) ? actor->ceilingz - 24*FRACUNIT : actor->floorz + 24*FRACUNIT); - else - { - fixed_t add = actor->target->z + (actor->target->height - actor->height)/2; - if (add > (actor->ceilingz - 24*actor->scale - actor->height)) - add = actor->ceilingz - 24*actor->scale - actor->height; - else if (add < (actor->floorz + 24*actor->scale)) - add = actor->floorz + 24*actor->scale; - chasez += add; - } - - if (!targetdist) - targetdist = 16*FRACUNIT; //Default! - - if (actor->target && abs(chasez - actor->z) > targetdist) - targetdist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); - - if (actor->target - && P_IsFlickyCenter(actor->target->type) - && (actor->target->flags & MF_SLIDEME)) - vertangle = 0; - else - vertangle = (R_PointToAngle2(0, actor->z, targetdist, chasez) >> ANGLETOFINESHIFT) & FINEMASK; - - P_InstaThrust(actor, actor->angle, FixedMul(FINECOSINE(vertangle), flyspeed)); - actor->momz = FixedMul(FINESINE(vertangle), flyspeed); -} - -// Function: A_FlickyFly -// -// Description: Flicky flying function. -// -// var1 = how fast to fly -// var2 = how far ahead the target should be considered -// -void A_FlickyFly(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FlickyFly", actor)) - return; -#endif - P_InternalFlickyFly(actor, locvar1, locvar2, - FINECOSINE((((actor->fuse % 36) * ANG10) >> ANGLETOFINESHIFT) & FINEMASK) - ); -} - -// Function: A_FlickySoar -// -// Description: Flicky soaring function - specific to puffin. -// -// var1 = how fast to fly -// var2 = how far ahead the target should be considered -// -void A_FlickySoar(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FlickySoar", actor)) - return; -#endif - P_InternalFlickyFly(actor, locvar1, locvar2, - 2*(FRACUNIT/2 - abs(FINECOSINE((((actor->fuse % 144) * 5*ANG1/2) >> ANGLETOFINESHIFT) & FINEMASK))) - ); - - if (P_MobjFlip(actor)*actor->momz > 0 && actor->frame == 1 && actor->sprite == SPR_FL10) - actor->frame = 3; -} - -//Function: A_FlickyCoast -// -// Description: Flicky swim-coasting function. -// -// var1 = speed to change state upon reaching -// var2 = state to change to upon slowing down -// the spawnstate of the mobj = state to change to when above water -// -void A_FlickyCoast(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FlickyCoast", actor)) - return; -#endif - if (actor->eflags & MFE_UNDERWATER) - { - actor->momx = (11*actor->momx)/12; - actor->momy = (11*actor->momy)/12; - actor->momz = (11*actor->momz)/12; - - if (P_AproxDistance(P_AproxDistance(actor->momx, actor->momy), actor->momz) < locvar1) - P_SetMobjState(actor, locvar2); - - return; - } - - actor->flags &= ~MF_NOGRAVITY; - P_SetMobjState(actor, mobjinfo[actor->type].spawnstate); -} - -// Internal Flicky hopping function. -void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angle) -{ - if (((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) - || ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz))) - { - if (momz) - { - if (actor->eflags & MFE_UNDERWATER) - momz = FixedDiv(momz, FixedSqrt(3*FRACUNIT)); - P_SetObjectMomZ(actor, momz, false); - } - P_InstaThrust(actor, angle, FixedMul(momh, actor->scale)); - } -} - -// Function: A_FlickyHop -// -// Description: Flicky hopping function. -// -// var1 = vertical thrust -// var2 = horizontal thrust -// -void A_FlickyHop(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FlickyHop", actor)) - return; -#endif - P_InternalFlickyHop(actor, locvar1, locvar2, actor->angle); -} - -// Function: A_FlickyFlounder -// -// Description: Flicky floundering function. -// -// var1 = intended vertical thrust -// var2 = intended horizontal thrust -// -void A_FlickyFlounder(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - angle_t hopangle; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FlickyFlounder", actor)) - return; -#endif - locvar1 *= (P_RandomKey(2) + 1); - locvar2 *= (P_RandomKey(2) + 1); - hopangle = (actor->angle + (P_RandomKey(9) - 4)*ANG2); - P_InternalFlickyHop(actor, locvar1, locvar2, hopangle); -} - -// Function: A_FlickyCheck -// -// Description: Flicky airtime check function. -// -// var1 = state to change to upon touching the floor -// var2 = state to change to upon falling -// the meleestate of the mobj = state to change to when underwater -// -void A_FlickyCheck(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FlickyCheck", actor)) - return; -#endif - if (actor->target - && P_IsFlickyCenter(actor->target->type) - && (actor->target->flags & MF_GRENADEBOUNCE)) - { - if (!(actor->target->flags & MF_NOCLIPTHING)) // no hopping - { - actor->momz = 0; - actor->flags |= MF_NOGRAVITY; - } - actor->flags |= MF_NOCLIP | MF_NOBLOCKMAP | MF_SCENERY; - P_SetMobjState(actor, mobjinfo[actor->type].seestate); - } - else if (locvar2 && P_MobjFlip(actor)*actor->momz < 1) - P_SetMobjState(actor, locvar2); - else if (locvar1 && ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) - || ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz))) - P_SetMobjState(actor, locvar1); - else if (mobjinfo[actor->type].meleestate && (actor->eflags & MFE_UNDERWATER)) - P_SetMobjState(actor, mobjinfo[actor->type].meleestate); - P_InternalFlickyBubble(actor); -} - -// Function: A_FlickyHeightCheck -// -// Description: Flicky height check function. -// -// var1 = state to change to when falling below height relative to target -// var2 = height relative to target to change state at -// -void A_FlickyHeightCheck(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FlickyHeightCheck", actor)) - return; -#endif - if (actor->target - && P_IsFlickyCenter(actor->target->type) - && (actor->target->flags & MF_GRENADEBOUNCE)) - { - if (!(actor->target->flags & MF_NOCLIPTHING)) // no hopping - { - actor->momz = 0; - actor->flags |= MF_NOGRAVITY; - } - actor->flags |= MF_NOCLIP | MF_NOBLOCKMAP | MF_SCENERY; - P_SetMobjState(actor, mobjinfo[actor->type].seestate); - } - else if (locvar1 && actor->target && P_MobjFlip(actor)*actor->momz < 1 - && ((P_MobjFlip(actor)*((actor->z + actor->height/2) - (actor->target->z + actor->target->height/2)) < locvar2) - || (actor->z - actor->height < actor->floorz) || (actor->z + 2*actor->height > actor->ceilingz))) - P_SetMobjState(actor, locvar1); - P_InternalFlickyBubble(actor); -} - -// Function: A_FlickyFlutter -// -// Description: Flicky fluttering function - specific to chicken. -// -// var1 = state to change to upon touching the floor -// var2 = state to change to upon falling -// the meleestate of the mobj = state to change to when underwater -// -void A_FlickyFlutter(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FlickyFlutter", actor)) - return; -#endif - var1 = locvar1; - var2 = locvar2; - A_FlickyCheck(actor); - - var1 = ANG30; - var2 = 32*FRACUNIT; - A_FlickyAim(actor); - - P_InstaThrust(actor, actor->angle, 2*actor->scale); - if (P_MobjFlip(actor)*actor->momz < -FRACUNIT/2) - actor->momz = -P_MobjFlip(actor)*actor->scale/2; -} - -#undef FLICKYHITWALL - -// Function: A_FlameParticle -// -// Description: Creates the mobj's painchance at a random position around the object's radius. -// -// var1 = unused -// var2 = unused -// -void A_FlameParticle(mobj_t *actor) -{ - mobjtype_t type = (mobjtype_t)(mobjinfo[actor->type].painchance); - fixed_t rad, hei; - mobj_t *particle; - //INT32 locvar1 = var1; - //INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FlameParticle", actor)) - return; -#endif - - if (!type) - return; - - rad = actor->radius>>FRACBITS; - hei = actor->height>>FRACBITS; - particle = P_SpawnMobjFromMobj(actor, - P_RandomRange(rad, -rad)<frame = actor->frame; - - if (!(locvar1 & 1)) - { - fade->fuse = 15; - fade->flags2 |= MF2_BOSSNOTRAP; - } - else - fade->fuse = 20; - - if (!(locvar1 & 2)) - P_SetTarget(&actor->tracer, fade); -} - -// Function: A_Boss5Jump -// -// Description: Makes an object jump in an arc to land on their tracer precicely. -// Adapted from A_BrakLobShot, see there for explanation. -// -// var1 = unused -// var2 = unused -// -void A_Boss5Jump(mobj_t *actor) -{ - fixed_t v; // Velocity to jump at - fixed_t a1, a2, aToUse; // Velocity squared - fixed_t g; // Gravity - fixed_t x; // Horizontal difference - INT32 x_int; // x! But in integer form! - fixed_t y; // Vertical difference (yes that's normally z in SRB2 shut up) - INT32 y_int; // y! But in integer form! - INT32 intHypotenuse; // x^2 + y^2. Frequently overflows fixed point, hence why we need integers proper. - fixed_t fixedHypotenuse; // However, we can work around that and still get a fixed-point number. - angle_t theta; // Angle of attack - // INT32 locvar1 = var1; - // INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_Boss5Jump", actor)) - return; -#endif - - if (!actor->tracer) - return; // Don't even bother if we've got nothing to aim at. - - // Look up actor's current gravity situation - if (actor->subsector->sector->gravity) - g = FixedMul(gravity,(FixedDiv(*actor->subsector->sector->gravity>>FRACBITS, 1000))); - else - g = gravity; - - // Look up distance between actor and its tracer - x = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y); - // Look up height difference between actor and its tracer - y = actor->tracer->z - actor->z; - - // Get x^2 + y^2. Have to do it in a roundabout manner, because this overflows fixed_t way too easily otherwise. - x_int = x>>FRACBITS; - y_int = y>>FRACBITS; - intHypotenuse = (x_int*x_int) + (y_int*y_int); - fixedHypotenuse = FixedSqrt(intHypotenuse) *256; - - // a = g(y+/-sqrt(x^2+y^2)). a1 can be +, a2 can be -. - a1 = FixedMul(g,y+fixedHypotenuse); - a2 = FixedMul(g,y-fixedHypotenuse); - - // Determine which one isn't actually an imaginary number (or the smaller of the two, if both are real), and use that for v. - if (a1 < 0 || a2 < 0) - { - if (a1 < 0 && a2 < 0) - { - //Somehow, v^2 is negative in both cases. v is therefore imaginary and something is horribly wrong. Abort! - return; - } - // Just find which one's NOT negative, and use that - aToUse = max(a1,a2); - } - else - { - // Both are positive; use whichever's smaller so it can decay faster - aToUse = min(a1,a2); - } - v = FixedSqrt(aToUse); - // Okay, so we know the velocity. Let's actually find theta. - // We can cut the "+/- sqrt" part out entirely, since v was calculated specifically for it to equal zero. So: - //theta = tantoangle[FixedDiv(aToUse,FixedMul(g,x)) >> DBITS]; - theta = tantoangle[SlopeDiv(aToUse,FixedMul(g,x))]; - - // Okay, complicated math done. Let's make this object jump already. - A_FaceTracer(actor); - - if (actor->eflags & MFE_VERTICALFLIP) - actor->z--; - else - actor->z++; - - // Horizontal axes first. First parameter is initial horizontal impulse, second is to correct its angle. - fixedHypotenuse = FixedMul(v, FINECOSINE(theta >> ANGLETOFINESHIFT)); // variable reuse - actor->momx = FixedMul(fixedHypotenuse, FINECOSINE(actor->angle >> ANGLETOFINESHIFT)); - actor->momy = FixedMul(fixedHypotenuse, FINESINE(actor->angle >> ANGLETOFINESHIFT)); - // Then the vertical axis. No angle-correction needed here. - actor->momz = FixedMul(v, FINESINE(theta >> ANGLETOFINESHIFT)); - // I hope that's all that's needed, ugh -} - -// Function: A_LightBeamReset -// Description: Resets momentum and position for DSZ's projecting light beams -// -// var1 = unused -// var2 = unused -// -void A_LightBeamReset(mobj_t *actor) -{ - // INT32 locvar1 = var1; - // INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_LightBeamReset", actor)) - return; -#endif - - actor->destscale = FRACUNIT + P_SignedRandom()*FRACUNIT/256; - P_SetScale(actor, actor->destscale); - - if (!actor->spawnpoint) - return; // this can't work properly welp - - actor->momx = -(P_SignedRandom()*FINESINE(((actor->spawnpoint->angle*ANG1)>>ANGLETOFINESHIFT) & FINEMASK))/128; - actor->momy = (P_SignedRandom()*FINECOSINE(((actor->spawnpoint->angle*ANG1)>>ANGLETOFINESHIFT) & FINEMASK))/128; - actor->momz = (P_SignedRandom()*FRACUNIT)/128; - - P_TeleportMove(actor, - actor->spawnpoint->x*FRACUNIT - (P_SignedRandom()*FINESINE(((actor->spawnpoint->angle*ANG1)>>ANGLETOFINESHIFT) & FINEMASK))/2, - actor->spawnpoint->y*FRACUNIT + (P_SignedRandom()*FINECOSINE(((actor->spawnpoint->angle*ANG1)>>ANGLETOFINESHIFT) & FINEMASK))/2, - actor->spawnpoint->z*FRACUNIT + (P_SignedRandom()*FRACUNIT)/2); -} - -// Function: A_MineExplode -// Description: Handles the explosion of a DSZ mine. -// -// var1 = unused -// var2 = unused -// -void A_MineExplode(mobj_t *actor) -{ - // INT32 locvar1 = var1; - // INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_MineExplode", actor)) - return; -#endif - - A_Scream(actor); - actor->flags = MF_NOGRAVITY|MF_NOCLIP; - - quake.epicenter = NULL; - quake.radius = 512*FRACUNIT; - quake.intensity = 8*FRACUNIT; - quake.time = TICRATE/3; - - P_RadiusAttack(actor, actor->tracer, 192*FRACUNIT, DMG_CANHURTSELF); - P_MobjCheckWater(actor); - - { -#define dist 64 - UINT8 i; - mobjtype_t type = ((actor->eflags & MFE_UNDERWATER) ? MT_UWEXPLODE : MT_BOSSEXPLODE); - S_StartSound(actor, ((actor->eflags & MFE_UNDERWATER) ? sfx_s3k57 : sfx_s3k4e)); - P_SpawnMobj(actor->x, actor->y, actor->z, type); - for (i = 0; i < 16; i++) - { - mobj_t *b = P_SpawnMobj(actor->x+P_RandomRange(-dist, dist)*FRACUNIT, - actor->y+P_RandomRange(-dist, dist)*FRACUNIT, - actor->z+P_RandomRange(((actor->eflags & MFE_UNDERWATER) ? -dist : 0), dist)*FRACUNIT, - type); - fixed_t dx = b->x - actor->x, dy = b->y - actor->y, dz = b->z - actor->z; - fixed_t dm = P_AproxDistance(dz, P_AproxDistance(dy, dx)); - b->momx = FixedDiv(dx, dm)*3; - b->momy = FixedDiv(dy, dm)*3; - b->momz = FixedDiv(dz, dm)*3; - if ((actor->watertop == INT32_MAX) || (b->z + b->height > actor->watertop)) - b->flags &= ~MF_NOGRAVITY; - } -#undef dist - - if (actor->watertop != INT32_MAX) - P_SpawnMobj(actor->x, actor->y, actor->watertop, MT_SPLISH); - } -} - -// Function: A_MineRange -// Description: If the target gets too close, change the state to meleestate. -// -// var1 = Distance to alert at -// var2 = unused -// -void A_MineRange(mobj_t *actor) -{ - fixed_t dm; - INT32 locvar1 = var1; - // INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_MineRange", actor)) - return; -#endif - - if (!actor->target) - return; - - dm = P_AproxDistance(actor->z - actor->target->z, P_AproxDistance(actor->y - actor->target->y, actor->x - actor->target->x)); - if ((dm>>FRACBITS) < locvar1) - P_SetMobjState(actor, actor->info->meleestate); -} - -// Function: A_ConnectToGround -// Description: Create a palm tree trunk/mine chain. -// -// var1 = Object type to connect to ground -// var2 = Object type to place on ground -// -void A_ConnectToGround(mobj_t *actor) -{ - mobj_t *work; - fixed_t workz; - fixed_t workh; - SINT8 dir; - angle_t ang; - INT32 locvar1 = var1; - INT32 locvar2 = var2; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ConnectToGround", actor)) - return; -#endif - - if (actor->subsector->sector->ffloors) - P_AdjustMobjFloorZ_FFloors(actor, actor->subsector->sector, 2); - - if (actor->flags2 & MF2_OBJECTFLIP) - { - workz = actor->ceilingz - (actor->z + actor->height); - dir = -1; - } - else - { - workz = actor->floorz - actor->z; - dir = 1; - } - - if (locvar2) - { - workh = FixedMul(mobjinfo[locvar2].height, actor->scale); - if (actor->flags2 & MF2_OBJECTFLIP) - workz -= workh; - work = P_SpawnMobjFromMobj(actor, 0, 0, workz, locvar2); - workz += dir*workh; - } - - if (!locvar1) - return; - - if (!(workh = FixedMul(mobjinfo[locvar1].height, actor->scale))) - return; - - if (actor->flags2 & MF2_OBJECTFLIP) - workz -= workh; - - ang = actor->angle + ANGLE_45; - while (dir*workz < 0) - { - work = P_SpawnMobjFromMobj(actor, 0, 0, workz, locvar1); - if (work) - work->angle = ang; - ang += ANGLE_90; - workz += dir*workh; - } - - if (workz != 0) - actor->z += workz; -} - -// Function: A_SpawnParticleRelative -// -// Description: Spawns a particle effect relative to the location of the actor -// -// var1: -// var1 >> 16 = x -// var1 & 65535 = y -// var2: -// var2 >> 16 = z -// var2 & 65535 = state -// -void A_SpawnParticleRelative(mobj_t *actor) -{ - INT16 x, y, z; // Want to be sure we can use negative values - statenum_t state; - mobj_t *mo; - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SpawnParticleRelative", actor)) - return; -#endif - - CONS_Debug(DBG_GAMELOGIC, "A_SpawnParticleRelative called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); - - x = (INT16)(locvar1>>16); - y = (INT16)(locvar1&65535); - z = (INT16)(locvar2>>16); - state = (statenum_t)(locvar2&65535); - - // Spawn objects correctly in reverse gravity. - // NOTE: Doing actor->z + actor->height is the bottom of the object while the object has reverse gravity. - Flame - mo = P_SpawnMobj(actor->x + FixedMul(x<scale), - actor->y + FixedMul(y<scale), - (actor->eflags & MFE_VERTICALFLIP) ? ((actor->z + actor->height - mobjinfo[MT_PARTICLE].height) - FixedMul(z<scale)) : (actor->z + FixedMul(z<scale)), MT_PARTICLE); - - // Spawn objects with an angle matching the spawner's, rather than spawning Eastwards - Monster Iestyn - mo->angle = actor->angle; - - if (actor->eflags & MFE_VERTICALFLIP) - mo->flags2 |= MF2_OBJECTFLIP; - - P_SetMobjState(mo, state); -} - -// Function: A_MultiShotDist -// -// Description: Spawns multiple shots based on player proximity -// -// var1 = same as A_MultiShot -// var2 = same as A_MultiShot -// -void A_MultiShotDist(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_MultiShotDist", actor)) - return; -#endif - - { - UINT8 i; - // Quick! Look through players! - // Don't spawn dust unless a player is relatively close by (var1). - for (i = 0; i < MAXPLAYERS; ++i) - if (playeringame[i] && players[i].mo - && P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (1600<> 16 = mobjtype of child -// var2 & 65535 = vertical momentum -// var2: -// var2 >> 16 = forward offset -// var2 & 65535 = vertical offset -// -void A_WhoCaresIfYourSonIsABee(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; - fixed_t foffsetx; - fixed_t foffsety; - mobj_t *son; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_WhoCaresIfYourSonIsABee", actor)) - return; -#endif - - A_FaceTarget(actor); - - if (actor->extravalue1) - actor->extravalue1--; - - if (actor->info->attacksound) - S_StartSound(actor, actor->info->attacksound); - - foffsetx = P_ReturnThrustX(actor, actor->angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale)); - foffsety = P_ReturnThrustY(actor, actor->angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale)); - - if (!(son = P_SpawnMobjFromMobj(actor, foffsetx, foffsety, (locvar2&65535)*FRACUNIT, (mobjtype_t)(locvar1 >> 16)))) - return; - - P_SetObjectMomZ(son, (locvar1 & 65535)<tracer, actor); - P_SetTarget(&son->target, actor->target); -} - -// Function: A_ParentTriesToSleep -// -// Description: If extravalue1 is less than or equal to var1, go to var2. -// -// var1 = state to go to when extravalue1 -// var2 = unused -// -void A_ParentTriesToSleep(mobj_t *actor) -{ - INT32 locvar1 = var1; - //INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ParentTriesToSleep", actor)) - return; -#endif - - if (actor->extravalue1) - { - if (actor->info->seesound) - S_StartSound(actor, actor->info->seesound); - actor->reactiontime = 0; - P_SetMobjState(actor, locvar1); - } - else if (!actor->reactiontime) - { - actor->reactiontime = 1; - if (actor->info->activesound) // more like INactivesound doy hoy hoy - S_StartSound(actor, actor->info->activesound); - } -} - - -// Function: A_CryingToMomma -// -// Description: If you're a child, let your parent know something's happened to you through extravalue1. Also, prepare to die. -// -// var1 = unused -// var2 = unused -// -void A_CryingToMomma(mobj_t *actor) -{ - //INT32 locvar1 = var1; - //INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CryingToMomma", actor)) - return; -#endif - - if (actor->tracer) - actor->tracer->extravalue1++; - - actor->momx = actor->momy = actor->momz = 0; - - P_UnsetThingPosition(actor); - if (sector_list) - { - P_DelSeclist(sector_list); - sector_list = NULL; - } - actor->flags = MF_NOBLOCKMAP|MF_NOCLIPTHING; - P_SetThingPosition(actor); -} - -// Function: A_CheckFlags2 -// -// Description: If actor->flags2 & var1, goto var2. -// -// var1 = mask -// var2 = state to go -// -void A_CheckFlags2(mobj_t *actor) -{ - INT32 locvar1 = var1; - INT32 locvar2 = var2; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_CheckFlags2", actor)) - return; -#endif - - if (actor->flags2 & locvar1) - P_SetMobjState(actor, (statenum_t)locvar2); -} +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1993-1996 by id Software, Inc. +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2016 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file p_enemy.c +/// \brief Enemy thinking, AI +/// Action Pointer Functions that are associated with states/frames + +#include "doomdef.h" +#include "g_game.h" +#include "p_local.h" +#include "r_main.h" +#include "r_state.h" +#include "s_sound.h" +#include "m_random.h" +#include "m_misc.h" +#include "r_things.h" +#include "i_video.h" +#include "lua_hook.h" + +#ifdef HW3SOUND +#include "hardware/hw3sound.h" +#endif + +#ifdef HAVE_BLUA +boolean LUA_CallAction(const char *action, mobj_t *actor); +#endif + +player_t *stplyr; +INT32 var1; +INT32 var2; + +// +// P_NewChaseDir related LUT. +// +static dirtype_t opposite[] = +{ + DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, + DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_NODIR +}; + +static dirtype_t diags[] = +{ + DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST +}; + +//Real Prototypes to A_* +void A_Fall(mobj_t *actor); +void A_Look(mobj_t *actor); +void A_Chase(mobj_t *actor); +void A_FaceStabChase(mobj_t *actor); +void A_FaceStabRev(mobj_t *actor); +void A_FaceStabHurl(mobj_t *actor); +void A_FaceStabMiss(mobj_t *actor); +void A_StatueBurst(mobj_t *actor); +void A_JetJawRoam(mobj_t *actor); +void A_JetJawChomp(mobj_t *actor); +void A_PointyThink(mobj_t *actor); +void A_CheckBuddy(mobj_t *actor); +void A_HoodFire(mobj_t *actor); +void A_HoodThink(mobj_t *actor); +void A_HoodFall(mobj_t *actor); +void A_ArrowBonks(mobj_t *actor); +void A_SnailerThink(mobj_t *actor); +void A_SharpChase(mobj_t *actor); +void A_SharpSpin(mobj_t *actor); +void A_SharpDecel(mobj_t *actor); +void A_CrushstaceanWalk(mobj_t *actor); +void A_CrushstaceanPunch(mobj_t *actor); +void A_CrushclawAim(mobj_t *actor); +void A_CrushclawLaunch(mobj_t *actor); +void A_VultureVtol(mobj_t *actor); +void A_VultureCheck(mobj_t *actor); +void A_SkimChase(mobj_t *actor); +void A_FaceTarget(mobj_t *actor); +void A_FaceTracer(mobj_t *actor); +void A_LobShot(mobj_t *actor); +void A_FireShot(mobj_t *actor); +void A_SuperFireShot(mobj_t *actor); +void A_BossFireShot(mobj_t *actor); +void A_Boss7FireMissiles(mobj_t *actor); +void A_Boss1Laser(mobj_t *actor); +void A_FocusTarget(mobj_t *actor); +void A_Boss4Reverse(mobj_t *actor); +void A_Boss4SpeedUp(mobj_t *actor); +void A_Boss4Raise(mobj_t *actor); +void A_SkullAttack(mobj_t *actor); +void A_BossZoom(mobj_t *actor); +void A_BossScream(mobj_t *actor); +void A_Scream(mobj_t *actor); +void A_Pain(mobj_t *actor); +void A_1upThinker(mobj_t *actor); +void A_MonitorPop(mobj_t *actor); +void A_GoldMonitorPop(mobj_t *actor); +void A_GoldMonitorRestore(mobj_t *actor); +void A_GoldMonitorSparkle(mobj_t *actor); +void A_Explode(mobj_t *actor); +void A_BossDeath(mobj_t *actor); +void A_CustomPower(mobj_t *actor); +void A_GiveWeapon(mobj_t *actor); +void A_RingBox(mobj_t *actor); +void A_Invincibility(mobj_t *actor); +void A_SuperSneakers(mobj_t *actor); +void A_AwardScore(mobj_t *actor); +void A_ExtraLife(mobj_t *actor); +void A_GiveShield(mobj_t *actor); +void A_GravityBox(mobj_t *actor); +void A_ScoreRise(mobj_t *actor); +void A_BunnyHop(mobj_t *actor); +void A_BubbleSpawn(mobj_t *actor); +void A_FanBubbleSpawn(mobj_t *actor); +void A_BubbleRise(mobj_t *actor); +void A_BubbleCheck(mobj_t *actor); +void A_AttractChase(mobj_t *actor); +void A_DropMine(mobj_t *actor); +void A_FishJump(mobj_t *actor); +void A_ThrownRing(mobj_t *actor); +void A_SetSolidSteam(mobj_t *actor); +void A_UnsetSolidSteam(mobj_t *actor); +void A_SignPlayer(mobj_t *actor); +void A_OverlayThink(mobj_t *actor); +void A_JetChase(mobj_t *actor); +void A_JetbThink(mobj_t *actor); +void A_JetgShoot(mobj_t *actor); +void A_JetgThink(mobj_t *actor); +void A_ShootBullet(mobj_t *actor); +void A_MinusDigging(mobj_t *actor); +void A_MinusPopup(mobj_t *actor); +void A_MinusCheck(mobj_t *actor); +void A_ChickenCheck(mobj_t *actor); +void A_MouseThink(mobj_t *actor); +void A_DetonChase(mobj_t *actor); +void A_CapeChase(mobj_t *actor); +void A_RotateSpikeBall(mobj_t *actor); +void A_SlingAppear(mobj_t *actor); +void A_UnidusBall(mobj_t *actor); +void A_RockSpawn(mobj_t *actor); +void A_SetFuse(mobj_t *actor); +void A_CrawlaCommanderThink(mobj_t *actor); +void A_RingExplode(mobj_t *actor); +void A_OldRingExplode(mobj_t *actor); +void A_MixUp(mobj_t *actor); +void A_RecyclePowers(mobj_t *actor); +void A_Boss2TakeDamage(mobj_t *actor); +void A_Boss7Chase(mobj_t *actor); +void A_GoopSplat(mobj_t *actor); +void A_Boss2PogoSFX(mobj_t *actor); +void A_Boss2PogoTarget(mobj_t *actor); +void A_EggmanBox(mobj_t *actor); +void A_TurretFire(mobj_t *actor); +void A_SuperTurretFire(mobj_t *actor); +void A_TurretStop(mobj_t *actor); +void A_SparkFollow(mobj_t *actor); +void A_BuzzFly(mobj_t *actor); +void A_GuardChase(mobj_t *actor); +void A_EggShield(mobj_t *actor); +void A_SetReactionTime(mobj_t *actor); +void A_Boss1Spikeballs(mobj_t *actor); +void A_Boss3TakeDamage(mobj_t *actor); +void A_Boss3Path(mobj_t *actor); +void A_LinedefExecute(mobj_t *actor); +void A_PlaySeeSound(mobj_t *actor); +void A_PlayAttackSound(mobj_t *actor); +void A_PlayActiveSound(mobj_t *actor); +void A_SmokeTrailer(mobj_t *actor); +void A_SpawnObjectAbsolute(mobj_t *actor); +void A_SpawnObjectRelative(mobj_t *actor); +void A_ChangeAngleRelative(mobj_t *actor); +void A_ChangeAngleAbsolute(mobj_t *actor); +void A_PlaySound(mobj_t *actor); +void A_FindTarget(mobj_t *actor); +void A_FindTracer(mobj_t *actor); +void A_SetTics(mobj_t *actor); +void A_SetRandomTics(mobj_t *actor); +void A_ChangeColorRelative(mobj_t *actor); +void A_ChangeColorAbsolute(mobj_t *actor); +void A_MoveRelative(mobj_t *actor); +void A_MoveAbsolute(mobj_t *actor); +void A_Thrust(mobj_t *actor); +void A_ZThrust(mobj_t *actor); +void A_SetTargetsTarget(mobj_t *actor); +void A_SetObjectFlags(mobj_t *actor); +void A_SetObjectFlags2(mobj_t *actor); +void A_RandomState(mobj_t *actor); +void A_RandomStateRange(mobj_t *actor); +void A_DualAction(mobj_t *actor); +void A_RemoteAction(mobj_t *actor); +void A_ToggleFlameJet(mobj_t *actor); +void A_OrbitNights(mobj_t *actor); +void A_GhostMe(mobj_t *actor); +void A_SetObjectState(mobj_t *actor); +void A_SetObjectTypeState(mobj_t *actor); +void A_KnockBack(mobj_t *actor); +void A_PushAway(mobj_t *actor); +void A_RingDrain(mobj_t *actor); +void A_SplitShot(mobj_t *actor); +void A_MissileSplit(mobj_t *actor); +void A_MultiShot(mobj_t *actor); +void A_InstaLoop(mobj_t *actor); +void A_Custom3DRotate(mobj_t *actor); +void A_SearchForPlayers(mobj_t *actor); +void A_CheckRandom(mobj_t *actor); +void A_CheckTargetRings(mobj_t *actor); +void A_CheckRings(mobj_t *actor); +void A_CheckTotalRings(mobj_t *actor); +void A_CheckHealth(mobj_t *actor); +void A_CheckRange(mobj_t *actor); +void A_CheckHeight(mobj_t *actor); +void A_CheckTrueRange(mobj_t *actor); +void A_CheckThingCount(mobj_t *actor); +void A_CheckAmbush(mobj_t *actor); +void A_CheckCustomValue(mobj_t *actor); +void A_CheckCusValMemo(mobj_t *actor); +void A_SetCustomValue(mobj_t *actor); +void A_UseCusValMemo(mobj_t *actor); +void A_RelayCustomValue(mobj_t *actor); +void A_CusValAction(mobj_t *actor); +void A_ForceStop(mobj_t *actor); +void A_ForceWin(mobj_t *actor); +void A_SpikeRetract(mobj_t *actor); +void A_InfoState(mobj_t *actor); +void A_Repeat(mobj_t *actor); +void A_SetScale(mobj_t *actor); +void A_RemoteDamage(mobj_t *actor); +void A_HomingChase(mobj_t *actor); +void A_TrapShot(mobj_t *actor); +void A_Boss1Chase(mobj_t *actor); +void A_Boss2Chase(mobj_t *actor); +void A_Boss2Pogo(mobj_t *actor); +void A_BossJetFume(mobj_t *actor); +void A_VileTarget(mobj_t *actor); +void A_VileAttack(mobj_t *actor); +void A_VileFire(mobj_t *actor); +void A_BrakChase(mobj_t *actor); +void A_BrakFireShot(mobj_t *actor); +void A_BrakLobShot(mobj_t *actor); +void A_NapalmScatter(mobj_t *actor); +void A_SpawnFreshCopy(mobj_t *actor); +void A_FlickySpawn(mobj_t *actor); +void A_FlickyCenter(mobj_t *actor); +void A_FlickyAim(mobj_t *actor); +void A_FlickyFly(mobj_t *actor); +void A_FlickySoar(mobj_t *actor); +void A_FlickyCoast(mobj_t *actor); +void A_FlickyHop(mobj_t *actor); +void A_FlickyFlounder(mobj_t *actor); +void A_FlickyCheck(mobj_t *actor); +void A_FlickyHeightCheck(mobj_t *actor); +void A_FlickyFlutter(mobj_t *actor); +void A_FlameParticle(mobj_t *actor); +void A_FadeOverlay(mobj_t *actor); +void A_Boss5Jump(mobj_t *actor); +void A_LightBeamReset(mobj_t *actor); +void A_MineExplode(mobj_t *actor); +void A_MineRange(mobj_t *actor); +void A_ConnectToGround(mobj_t *actor); +void A_SpawnParticleRelative(mobj_t *actor); +void A_MultiShotDist(mobj_t *actor); +void A_WhoCaresIfYourSonIsABee(mobj_t *actor); +void A_ParentTriesToSleep(mobj_t *actor); +void A_CryingToMomma(mobj_t *actor); +void A_CheckFlags2(mobj_t *actor); +//for p_enemy.c + +// +// ENEMY THINKING +// Enemies are always spawned with targetplayer = -1, threshold = 0 +// Most monsters are spawned unaware of all players, but some can be made preaware. +// + +// +// P_CheckMeleeRange +// +boolean P_CheckMeleeRange(mobj_t *actor) +{ + mobj_t *pl; + fixed_t dist; + + if (!actor->target) + return false; + + pl = actor->target; + dist = P_AproxDistance(pl->x-actor->x, pl->y-actor->y); + + if (dist >= FixedMul(MELEERANGE - 20*FRACUNIT, actor->scale) + pl->radius) + return false; + + // check height now, so that damn crawlas cant attack + // you if you stand on a higher ledge. + if ((pl->z > actor->z + actor->height) || (actor->z > pl->z + pl->height)) + return false; + + if (!P_CheckSight(actor, actor->target)) + return false; + + return true; +} + +// P_CheckMeleeRange for Jettysyn Bomber. +boolean P_JetbCheckMeleeRange(mobj_t *actor) +{ + mobj_t *pl; + fixed_t dist; + + if (!actor->target) + return false; + + pl = actor->target; + dist = P_AproxDistance(pl->x-actor->x, pl->y-actor->y); + + if (dist >= (actor->radius + pl->radius)*2) + return false; + + if (actor->eflags & MFE_VERTICALFLIP) + { + if (pl->z < actor->z + actor->height + FixedMul(40<scale)) + return false; + } + else + { + if (pl->z + pl->height > actor->z - FixedMul(40<scale)) + return false; + } + + return true; +} + +// P_CheckMeleeRange for CastleBot FaceStabber. +boolean P_FaceStabCheckMeleeRange(mobj_t *actor) +{ + mobj_t *pl; + fixed_t dist; + + if (!actor->target) + return false; + + pl = actor->target; + dist = P_AproxDistance(pl->x-actor->x, pl->y-actor->y); + + if (dist >= (actor->radius + pl->radius)*4) + return false; + + if ((pl->z > actor->z + actor->height) || (actor->z > pl->z + pl->height)) + return false; + + if (!P_CheckSight(actor, actor->target)) + return false; + + return true; +} + +// P_CheckMeleeRange for Skim. +boolean P_SkimCheckMeleeRange(mobj_t *actor) +{ + mobj_t *pl; + fixed_t dist; + + if (!actor->target) + return false; + + pl = actor->target; + dist = P_AproxDistance(pl->x-actor->x, pl->y-actor->y); + + if (dist >= FixedMul(MELEERANGE - 20*FRACUNIT, actor->scale) + pl->radius) + return false; + + if (actor->eflags & MFE_VERTICALFLIP) + { + if (pl->z < actor->z + actor->height + FixedMul(24<scale)) + return false; + } + else + { + if (pl->z + pl->height > actor->z - FixedMul(24<scale)) + return false; + } + + return true; +} + +// +// P_CheckMissileRange +// +boolean P_CheckMissileRange(mobj_t *actor) +{ + fixed_t dist; + + if (!actor->target) + return false; + + if (actor->reactiontime) + return false; // do not attack yet + + if (!P_CheckSight(actor, actor->target)) + return false; + + // OPTIMIZE: get this from a global checksight + dist = P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) - FixedMul(64*FRACUNIT, actor->scale); + + if (!actor->info->meleestate) + dist -= FixedMul(128*FRACUNIT, actor->scale); // no melee attack, so fire more + + dist >>= FRACBITS; + + if (actor->type == MT_EGGMOBILE) + dist >>= 1; + + if (dist > 200) + dist = 200; + + if (actor->type == MT_EGGMOBILE && dist > 160) + dist = 160; + + if (P_RandomByte() < dist) + return false; + + return true; +} + +/** Checks for water in a sector. + * Used by Skim movements. + * + * \param x X coordinate on the map. + * \param y Y coordinate on the map. + * \return True if there's water at this location, false if not. + * \sa ::MT_SKIM + */ +static boolean P_WaterInSector(mobj_t *mobj, fixed_t x, fixed_t y) +{ + sector_t *sector; + + sector = R_PointInSubsector(x, y)->sector; + + if (sector->ffloors) + { + ffloor_t *rover; + + for (rover = sector->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE)) + continue; + + if (*rover->topheight >= mobj->floorz && *rover->topheight <= mobj->z) + return true; // we found water!! + } + } + + return false; +} + +static const fixed_t xspeed[NUMDIRS] = {FRACUNIT, 46341>>(16-FRACBITS), 0, -(46341>>(16-FRACBITS)), -FRACUNIT, -(46341>>(16-FRACBITS)), 0, 46341>>(16-FRACBITS)}; +static const fixed_t yspeed[NUMDIRS] = {0, 46341>>(16-FRACBITS), FRACUNIT, 46341>>(16-FRACBITS), 0, -(46341>>(16-FRACBITS)), -FRACUNIT, -(46341>>(16-FRACBITS))}; + +/** Moves an actor in its current direction. + * + * \param actor Actor object to move. + * \return False if the move is blocked, otherwise true. + */ +boolean P_Move(mobj_t *actor, fixed_t speed) +{ + fixed_t tryx, tryy; + dirtype_t movedir = actor->movedir; + + if (movedir == DI_NODIR || !actor->health) + return false; + + I_Assert(movedir < NUMDIRS); + + tryx = actor->x + FixedMul(speed*xspeed[movedir], actor->scale); + if (twodlevel || actor->flags2 & MF2_TWOD) + tryy = actor->y; + else + tryy = actor->y + FixedMul(speed*yspeed[movedir], actor->scale); + + if (actor->type == MT_SKIM && !P_WaterInSector(actor, tryx, tryy)) // bail out if sector lacks water + return false; + + if (!P_TryMove(actor, tryx, tryy, false)) + { + if (actor->flags & MF_FLOAT && floatok) + { + // must adjust height + if (actor->z < tmfloorz) + actor->z += FixedMul(FLOATSPEED, actor->scale); + else + actor->z -= FixedMul(FLOATSPEED, actor->scale); + + if (actor->type == MT_JETJAW && actor->z + actor->height > actor->watertop) + actor->z = actor->watertop - actor->height; + + actor->flags2 |= MF2_INFLOAT; + return true; + } + + return false; + } + else + actor->flags2 &= ~MF2_INFLOAT; + + return true; +} + +/** Attempts to move an actor on in its current direction. + * If the move succeeds, the actor's move count is reset + * randomly to a value from 0 to 15. + * + * \param actor Actor to move. + * \return True if the move succeeds, false if the move is blocked. + */ +static boolean P_TryWalk(mobj_t *actor) +{ + if (!P_Move(actor, actor->info->speed)) + return false; + actor->movecount = P_RandomByte() & 15; + return true; +} + +void P_NewChaseDir(mobj_t *actor) +{ + fixed_t deltax, deltay; + dirtype_t d[3]; + dirtype_t tdir = DI_NODIR, olddir, turnaround; + + I_Assert(actor->target != NULL); + I_Assert(!P_MobjWasRemoved(actor->target)); + + olddir = actor->movedir; + + if (olddir >= NUMDIRS) + olddir = DI_NODIR; + + if (olddir != DI_NODIR) + turnaround = opposite[olddir]; + else + turnaround = olddir; + + deltax = actor->target->x - actor->x; + deltay = actor->target->y - actor->y; + + if (deltax > FixedMul(10*FRACUNIT, actor->scale)) + d[1] = DI_EAST; + else if (deltax < -FixedMul(10*FRACUNIT, actor->scale)) + d[1] = DI_WEST; + else + d[1] = DI_NODIR; + + if (twodlevel || actor->flags2 & MF2_TWOD) + d[2] = DI_NODIR; + if (deltay < -FixedMul(10*FRACUNIT, actor->scale)) + d[2] = DI_SOUTH; + else if (deltay > FixedMul(10*FRACUNIT, actor->scale)) + d[2] = DI_NORTH; + else + d[2] = DI_NODIR; + + // try direct route + if (d[1] != DI_NODIR && d[2] != DI_NODIR) + { + dirtype_t newdir = diags[((deltay < 0)<<1) + (deltax > 0)]; + + actor->movedir = newdir; + if ((newdir != turnaround) && P_TryWalk(actor)) + return; + } + + // try other directions + if (P_RandomChance(25*FRACUNIT/32) || abs(deltay) > abs(deltax)) + { + tdir = d[1]; + d[1] = d[2]; + d[2] = tdir; + } + + if (d[1] == turnaround) + d[1] = DI_NODIR; + if (d[2] == turnaround) + d[2] = DI_NODIR; + + if (d[1] != DI_NODIR) + { + actor->movedir = d[1]; + + if (P_TryWalk(actor)) + return; // either moved forward or attacked + } + + if (d[2] != DI_NODIR) + { + actor->movedir = d[2]; + + if (P_TryWalk(actor)) + return; + } + + // there is no direct path to the player, so pick another direction. + if (olddir != DI_NODIR) + { + actor->movedir =olddir; + + if (P_TryWalk(actor)) + return; + } + + // randomly determine direction of search + if (P_RandomChance(FRACUNIT/2)) + { + for (tdir = DI_EAST; tdir <= DI_SOUTHEAST; tdir++) + { + if (tdir != turnaround) + { + actor->movedir = tdir; + + if (P_TryWalk(actor)) + return; + } + } + } + else + { + for (tdir = DI_SOUTHEAST; tdir >= DI_EAST; tdir--) + { + if (tdir != turnaround) + { + actor->movedir = tdir; + + if (P_TryWalk(actor)) + return; + } + } + } + + if (turnaround != DI_NODIR) + { + actor->movedir = turnaround; + + if (P_TryWalk(actor)) + return; + } + + actor->movedir = (angle_t)DI_NODIR; // cannot move +} + +/** Looks for players to chase after, aim at, or whatever. + * + * \param actor The object looking for flesh. + * \param allaround Look all around? If false, only players in a 180-degree + * range in front will be spotted. + * \param dist If > 0, checks distance + * \return True if a player is found, otherwise false. + * \sa P_SupermanLook4Players + */ +boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed_t dist) +{ + INT32 c = 0, stop; + player_t *player; + angle_t an; + + // BP: first time init, this allow minimum lastlook changes + if (actor->lastlook < 0) + actor->lastlook = P_RandomByte(); + + actor->lastlook %= MAXPLAYERS; + + stop = (actor->lastlook - 1) & PLAYERSMASK; + + for (; ; actor->lastlook = (actor->lastlook + 1) & PLAYERSMASK) + { + // done looking + if (actor->lastlook == stop) + return false; + + if (!playeringame[actor->lastlook]) + continue; + + if (c++ == 2) + return false; + + player = &players[actor->lastlook]; + + if ((netgame || multiplayer) && player->spectator) + continue; + + if (player->pflags & PF_INVIS) + continue; // ignore notarget + + if (!player->mo || P_MobjWasRemoved(player->mo)) + continue; + + if (player->mo->health <= 0) + continue; // dead + + if (dist > 0 + && P_AproxDistance(P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y), player->mo->z - actor->z) > dist) + continue; // Too far away + + if (!allaround) + { + an = R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y) - actor->angle; + if (an > ANGLE_90 && an < ANGLE_270) + { + dist = P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y); + // if real close, react anyway + if (dist > FixedMul(MELEERANGE, actor->scale)) + continue; // behind back + } + } + + if (!P_CheckSight(actor, player->mo)) + continue; // out of sight + + if (tracer) + P_SetTarget(&actor->tracer, player->mo); + else + P_SetTarget(&actor->target, player->mo); + return true; + } + + //return false; +} + +/** Looks for a player with a ring shield. + * Used by rings. + * + * \param actor Ring looking for a shield to be attracted to. + * \return True if a player with ring shield is found, otherwise false. + * \sa A_AttractChase + */ +static boolean P_LookForShield(mobj_t *actor) +{ + INT32 c = 0, stop; + player_t *player; + + // BP: first time init, this allow minimum lastlook changes + if (actor->lastlook < 0) + actor->lastlook = P_RandomByte(); + + actor->lastlook %= MAXPLAYERS; + + stop = (actor->lastlook - 1) & PLAYERSMASK; + + for (; ; actor->lastlook = ((actor->lastlook + 1) & PLAYERSMASK)) + { + // done looking + if (actor->lastlook == stop) + return false; + + if (!playeringame[actor->lastlook]) + continue; + + if (c++ == 2) + return false; + + player = &players[actor->lastlook]; + + if (!player->mo || player->mo->health <= 0) + continue; // dead + + //When in CTF, don't pull rings that you cannot pick up. + if ((actor->type == MT_REDTEAMRING && player->ctfteam != 1) || + (actor->type == MT_BLUETEAMRING && player->ctfteam != 2)) + continue; + + if ((player->powers[pw_shield] & SH_PROTECTELECTRIC) + && (P_AproxDistance(P_AproxDistance(actor->x-player->mo->x, actor->y-player->mo->y), actor->z-player->mo->z) < FixedMul(RING_DIST, player->mo->scale))) + { + P_SetTarget(&actor->tracer, player->mo); + + if (actor->hnext) + P_SetTarget(&actor->hnext->hprev, actor->hprev); + if (actor->hprev) + P_SetTarget(&actor->hprev->hnext, actor->hnext); + + return true; + } + } + + //return false; +} + +#ifdef WEIGHTEDRECYCLER +// Compares players to see who currently has the "best" items, etc. +static int P_RecycleCompare(const void *p1, const void *p2) +{ + player_t *player1 = &players[*(const UINT8 *)p1]; + player_t *player2 = &players[*(const UINT8 *)p2]; + + // Non-shooting gametypes + if (!G_PlatformGametype()) + { + // Invincibility. + if (player1->powers[pw_invulnerability] > player2->powers[pw_invulnerability]) return -1; + else if (player2->powers[pw_invulnerability] > player1->powers[pw_invulnerability]) return 1; + + // One has a shield, the other doesn't. + if (player1->powers[pw_shield] && !player2->powers[pw_shield]) return -1; + else if (player2->powers[pw_shield] && !player1->powers[pw_shield]) return 1; + + // Sneakers. + if (player1->powers[pw_sneakers] > player2->powers[pw_sneakers]) return -1; + else if (player2->powers[pw_sneakers] > player1->powers[pw_sneakers]) return 1; + } + else // Match, Team Match, CTF, Tag, Etc. + { + UINT8 player1_em = M_CountBits((UINT32)player1->powers[pw_emeralds], 7); + UINT8 player2_em = M_CountBits((UINT32)player2->powers[pw_emeralds], 7); + + UINT8 player1_rw = M_CountBits((UINT32)player1->ringweapons, NUM_WEAPONS-1); + UINT8 player2_rw = M_CountBits((UINT32)player2->ringweapons, NUM_WEAPONS-1); + + UINT16 player1_am = player1->powers[pw_infinityring] // max 800 + + player1->powers[pw_automaticring] // max 300 + + (player1->powers[pw_bouncering] * 3) // max 100 + + (player1->powers[pw_explosionring] * 6) // max 50 + + (player1->powers[pw_scatterring] * 3) // max 100 + + (player1->powers[pw_grenadering] * 6) // max 50 + + (player1->powers[pw_railring] * 6); // max 50 + UINT16 player2_am = player2->powers[pw_infinityring] // max 800 + + player2->powers[pw_automaticring] // max 300 + + (player2->powers[pw_bouncering] * 3) // max 100 + + (player2->powers[pw_explosionring] * 6) // max 50 + + (player2->powers[pw_scatterring] * 3) // max 100 + + (player2->powers[pw_grenadering] * 6) // max 50 + + (player2->powers[pw_railring] * 6); // max 50 + + // Super trumps everything. + if (player1->powers[pw_super] && !player2->powers[pw_super]) return -1; + else if (player2->powers[pw_super] && !player1->powers[pw_super]) return 1; + + // Emerald count if neither player is Super. + if (player1_em > player2_em) return -1; + else if (player1_em < player2_em) return 1; + + // One has a shield, the other doesn't. + // (the likelihood of a shielded player being worse off than one without one is low.) + if (player1->powers[pw_shield] && !player2->powers[pw_shield]) return -1; + else if (player2->powers[pw_shield] && !player1->powers[pw_shield]) return 1; + + // Ring weapons count + if (player1_rw > player2_rw) return -1; + else if (player1_rw < player2_rw) return 1; + + // Ring ammo if they have the same number of weapons + if (player1_am > player2_am) return -1; + else if (player1_am < player2_am) return 1; + } + + // Identical for our purposes + return 0; +} +#endif + +// Handles random monitor weights via console. +static mobjtype_t P_DoRandomBoxChances(void) +{ + mobjtype_t spawnchance[256]; + INT32 numchoices = 0, i = 0; + + if (!(netgame || multiplayer)) + { + switch (P_RandomKey(10)) + { + case 0: + return MT_RING_ICON; + case 1: + return MT_SNEAKERS_ICON; + case 2: + return MT_INVULN_ICON; + case 3: + return MT_WHIRLWIND_ICON; + case 4: + return MT_ELEMENTAL_ICON; + case 5: + return MT_ATTRACT_ICON; + case 6: + return MT_FORCE_ICON; + case 7: + return MT_ARMAGEDDON_ICON; + case 8: + return MT_1UP_ICON; + case 9: + return MT_EGGMAN_ICON; + } + return MT_NULL; + } + +#define QUESTIONBOXCHANCES(type, cvar) \ +for (i = cvar.value; i; --i) spawnchance[numchoices++] = type + QUESTIONBOXCHANCES(MT_RING_ICON, cv_superring); + QUESTIONBOXCHANCES(MT_SNEAKERS_ICON, cv_supersneakers); + QUESTIONBOXCHANCES(MT_INVULN_ICON, cv_invincibility); + QUESTIONBOXCHANCES(MT_WHIRLWIND_ICON, cv_jumpshield); + QUESTIONBOXCHANCES(MT_ELEMENTAL_ICON, cv_watershield); + QUESTIONBOXCHANCES(MT_ATTRACT_ICON, cv_ringshield); + QUESTIONBOXCHANCES(MT_FORCE_ICON, cv_forceshield); + QUESTIONBOXCHANCES(MT_ARMAGEDDON_ICON, cv_bombshield); + QUESTIONBOXCHANCES(MT_1UP_ICON, cv_1up); + QUESTIONBOXCHANCES(MT_EGGMAN_ICON, cv_eggmanbox); + QUESTIONBOXCHANCES(MT_MIXUP_ICON, cv_teleporters); + QUESTIONBOXCHANCES(MT_RECYCLER_ICON, cv_recycler); +#undef QUESTIONBOXCHANCES + + if (numchoices == 0) return MT_NULL; + return spawnchance[P_RandomKey(numchoices)]; +} + +// +// ACTION ROUTINES +// + +// Function: A_Look +// +// Description: Look for a player and set your target to them. +// +// var1: +// lower 16 bits = look all around +// upper 16 bits = distance limit +// var2 = If 1, only change to seestate. If 2, only play seesound. If 0, do both. +// +void A_Look(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Look", actor)) + return; +#endif + + if (!P_LookForPlayers(actor, locvar1 & 65535, false , FixedMul((locvar1 >> 16)*FRACUNIT, actor->scale))) + return; + + // go into chase state + if (!locvar2) + { + P_SetMobjState(actor, actor->info->seestate); + A_PlaySeeSound(actor); + } + else if (locvar2 == 1) // Only go into seestate + P_SetMobjState(actor, actor->info->seestate); + else if (locvar2 == 2) // Only play seesound + A_PlaySeeSound(actor); +} + +// Function: A_Chase +// +// Description: Chase after your target. +// +// var1: +// 1 = don't check meleestate +// 2 = don't check missilestate +// 3 = don't check meleestate and missilestate +// var2 = unused +// +void A_Chase(mobj_t *actor) +{ + INT32 delta; + INT32 locvar1 = var1; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Chase", actor)) + return; +#endif + + I_Assert(actor != NULL); + I_Assert(!P_MobjWasRemoved(actor)); + + if (actor->reactiontime) + actor->reactiontime--; + + // modify target threshold + if (actor->threshold) + { + if (!actor->target || actor->target->health <= 0) + actor->threshold = 0; + else + actor->threshold--; + } + + // turn towards movement direction if not there yet + if (actor->movedir < NUMDIRS) + { + actor->angle &= (7<<29); + delta = actor->angle - (actor->movedir << 29); + + if (delta > 0) + actor->angle -= ANGLE_45; + else if (delta < 0) + actor->angle += ANGLE_45; + } + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { + // look for a new target + if (P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + P_SetMobjStateNF(actor, actor->info->spawnstate); + return; + } + + // do not attack twice in a row + if (actor->flags2 & MF2_JUSTATTACKED) + { + actor->flags2 &= ~MF2_JUSTATTACKED; + P_NewChaseDir(actor); + return; + } + + // check for melee attack + if (!(locvar1 & 1) && actor->info->meleestate && P_CheckMeleeRange(actor)) + { + if (actor->info->attacksound) + S_StartAttackSound(actor, actor->info->attacksound); + + P_SetMobjState(actor, actor->info->meleestate); + return; + } + + // check for missile attack + if (!(locvar1 & 2) && actor->info->missilestate) + { + if (actor->movecount || !P_CheckMissileRange(actor)) + goto nomissile; + + P_SetMobjState(actor, actor->info->missilestate); + actor->flags2 |= MF2_JUSTATTACKED; + return; + } + +nomissile: + // possibly choose another target + if (multiplayer && !actor->threshold && (actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) + && P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + // chase towards player + if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) + P_NewChaseDir(actor); +} + +// Function: A_FaceStabChase +// +// Description: Unused variant of A_Chase for Castlebot Facestabber. +// +// var1 = unused +// var2 = unused +// +void A_FaceStabChase(mobj_t *actor) +{ + INT32 delta; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FaceStabChase", actor)) + return; +#endif + + if (actor->reactiontime) + actor->reactiontime--; + + // modify target threshold + if (actor->threshold) + { + if (!actor->target || actor->target->health <= 0) + actor->threshold = 0; + else + actor->threshold--; + } + + // turn towards movement direction if not there yet + if (actor->movedir < NUMDIRS) + { + actor->angle &= (7<<29); + delta = actor->angle - (actor->movedir << 29); + + if (delta > 0) + actor->angle -= ANGLE_45; + else if (delta < 0) + actor->angle += ANGLE_45; + } + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { + // look for a new target + if (P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + P_SetMobjStateNF(actor, actor->info->spawnstate); + return; + } + + // do not attack twice in a row + if (actor->flags2 & MF2_JUSTATTACKED) + { + actor->flags2 &= ~MF2_JUSTATTACKED; + P_NewChaseDir(actor); + return; + } + + // check for melee attack + if (actor->info->meleestate && P_FaceStabCheckMeleeRange(actor)) + { + if (actor->info->attacksound) + S_StartAttackSound(actor, actor->info->attacksound); + + P_SetMobjState(actor, actor->info->meleestate); + return; + } + + // check for missile attack + if (actor->info->missilestate) + { + if (actor->movecount || !P_CheckMissileRange(actor)) + goto nomissile; + + P_SetMobjState(actor, actor->info->missilestate); + actor->flags2 |= MF2_JUSTATTACKED; + return; + } + +nomissile: + // possibly choose another target + if (multiplayer && !actor->threshold && (actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) + && P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + // chase towards player + if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) + P_NewChaseDir(actor); +} + +static void P_SharpDust(mobj_t *actor, mobjtype_t type, angle_t ang) +{ + mobj_t *dust; + + if (!type || !P_IsObjectOnGround(actor)) + return; + + dust = P_SpawnMobjFromMobj(actor, + -P_ReturnThrustX(actor, ang, 16<angle, actor->radius), + -P_ReturnThrustY(actor, actor->angle, actor->radius), + actor->height/3, + MT_PARTICLE); + flume->destscale = actor->scale*3; + P_SetScale(flume, flume->destscale); + P_SetTarget(&flume->target, actor); + flume->sprite = SPR_JETF; + flume->frame = FF_FULLBRIGHT; + flume->tics = 2; +} + +// Function: A_FaceStabRev +// +// Description: Facestabber rev action +// +// var1 = effective duration +// var2 = effective nextstate +// +void A_FaceStabRev(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FaceStabRev", actor)) + return; +#endif + + if (!actor->target) + { + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + + actor->extravalue1 = 0; + + if (!actor->reactiontime) + { + actor->reactiontime = locvar1; + S_StartSound(actor, actor->info->activesound); + } + else + { + if ((--actor->reactiontime) == 0) + { + S_StartSound(actor, actor->info->attacksound); + P_SetMobjState(actor, locvar2); + } + else + { + P_TryMove(actor, actor->x - P_ReturnThrustX(actor, actor->angle, 2<y - P_ReturnThrustY(actor, actor->angle, 2<target) + { + angle_t visang = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + // Calculate new direction. + angle_t dirang = actor->angle; + angle_t diffang = visang - dirang; + + if (locvar1) // Allow homing? + { + if (diffang > ANGLE_180) + { + angle_t workang = locvar1*(InvAngle(diffang)>>5); + diffang += InvAngle(workang); + } + else + diffang += (locvar1*(diffang>>5)); + } + diffang += ANGLE_45; + + // Check the sight cone. + if (diffang < ANGLE_90) + { + actor->angle = dirang; + if (++actor->extravalue2 < 4) + actor->extravalue2 = 4; + else if (actor->extravalue2 > 26) + actor->extravalue2 = 26; + + if (P_TryMove(actor, + actor->x + P_ReturnThrustX(actor, dirang, actor->extravalue2<y + P_ReturnThrustY(actor, dirang, actor->extravalue2<extravalue1); + fixed_t basesize = FRACUNIT/MAXVAL; + mobj_t *hwork = actor; + INT32 dist = 113; + fixed_t xo = P_ReturnThrustX(actor, actor->angle, dist*basesize); + fixed_t yo = P_ReturnThrustY(actor, actor->angle, dist*basesize); + + while (step > 0) + { + if (!hwork->hnext) + P_SetTarget(&hwork->hnext, P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_FACESTABBERSPEAR)); + hwork = hwork->hnext; + hwork->angle = actor->angle + ANGLE_90; + hwork->destscale = FixedSqrt(step*basesize); + P_SetScale(hwork, hwork->destscale); + hwork->fuse = 2; + P_TeleportMove(hwork, actor->x + xo*(15-step), actor->y + yo*(15-step), actor->z + (actor->height - hwork->height)/2 + (P_MobjFlip(actor)*(8<extravalue1 >= MAXVAL) + actor->extravalue1 -= NUMGRADS; + + if ((step % 5) == 0) + P_SharpDust(actor, MT_SPINDUST, actor->angle); + + P_FaceStabFlume(actor); + return; +#undef MAXVAL +#undef NUMGRADS +#undef NUMSTEPS + } + } + } + + P_SetMobjState(actor, locvar2); + actor->reactiontime = actor->info->reactiontime; +} + +// Function: A_FaceStabMiss +// +// Description: Facestabber miss action +// +// var1 = unused +// var2 = effective nextstate +// +void A_FaceStabMiss(mobj_t *actor) +{ + //INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FaceStabMiss", actor)) + return; +#endif + + if (++actor->extravalue1 >= 3) + { + actor->extravalue2 -= 2; + actor->extravalue1 = 0; + S_StartSound(actor, sfx_s3k47); + P_SharpDust(actor, MT_SPINDUST, actor->angle); + } + + if (actor->extravalue2 <= 0 || !P_TryMove(actor, + actor->x + P_ReturnThrustX(actor, actor->angle, actor->extravalue2<y + P_ReturnThrustY(actor, actor->angle, actor->extravalue2<extravalue2 = 0; + P_SetMobjState(actor, locvar2); + } +} + +// Function: A_StatueBurst +// +// Description: For suspicious statues only... +// +// var1 = object to create +// var2 = effective nextstate for created object +// +void A_StatueBurst(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobjtype_t chunktype = (mobjtype_t)actor->info->raisestate; + mobj_t *new; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_StatueBurst", actor)) + return; +#endif + + if (!locvar1 || !(new = P_SpawnMobjFromMobj(actor, 0, 0, 0, locvar1))) + return; + + new->angle = actor->angle; + new->target = actor->target; + if (locvar2) + P_SetMobjState(new, (statenum_t)locvar2); + S_StartSound(new, new->info->attacksound); + S_StopSound(actor); + S_StartSound(actor, sfx_s3k96); + + { + fixed_t a, b; + fixed_t c = (actor->height>>2) - FixedMul(actor->scale, mobjinfo[chunktype].height>>1); + fixed_t v = 4<radius>>1); + mobj_t *spawned; + UINT8 i; + for (i = 0; i < 8; i++) + { + a = ((i & 1) ? r : (-r)); + b = ((i & 2) ? r : (-r)); + if (i == 4) + { + c += (actor->height>>1); + v = 8<fuse = 3*TICRATE; + } + } +} + +// Function: A_JetJawRoam +// +// Description: Roaming routine for JetJaw +// +// var1 = unused +// var2 = unused +// +void A_JetJawRoam(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_JetJawRoam", actor)) + return; +#endif + if (actor->reactiontime) + { + actor->reactiontime--; + P_InstaThrust(actor, actor->angle, FixedMul(actor->info->speed*FRACUNIT/4, actor->scale)); + } + else + { + actor->reactiontime = actor->info->reactiontime; + actor->angle += ANGLE_180; + } + + if (P_LookForPlayers(actor, false, false, actor->radius * 16)) + P_SetMobjState(actor, actor->info->seestate); +} + +// Function: A_JetJawChomp +// +// Description: Chase and chomp at the target, as long as it is in view +// +// var1 = unused +// var2 = unused +// +void A_JetJawChomp(mobj_t *actor) +{ + INT32 delta; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_JetJawChomp", actor)) + return; +#endif + + // turn towards movement direction if not there yet + if (actor->movedir < NUMDIRS) + { + actor->angle &= (7<<29); + delta = actor->angle - (actor->movedir << 29); + + if (delta > 0) + actor->angle -= ANGLE_45; + else if (delta < 0) + actor->angle += ANGLE_45; + } + + // Stop chomping if target's dead or you can't see it + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE) + || actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) + { + P_SetMobjStateNF(actor, actor->info->spawnstate); + return; + } + + // chase towards player + if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) + P_NewChaseDir(actor); +} + +// Function: A_PointyThink +// +// Description: Thinker function for Pointy +// +// var1 = unused +// var2 = unused +// +void A_PointyThink(mobj_t *actor) +{ + INT32 i; + player_t *player = NULL; + mobj_t *ball; + TVector v; + TVector *res; + angle_t fa; + fixed_t radius = FixedMul(actor->info->radius*actor->info->reactiontime, actor->scale); + boolean firsttime = true; + INT32 sign; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_PointyThink", actor)) + return; +#endif + actor->momx = actor->momy = actor->momz = 0; + + // Find nearest player + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + + if (!players[i].mo) + continue; + + if (!players[i].mo->health) + continue; + + if (!P_CheckSight(actor, players[i].mo)) + continue; + + if (firsttime) + { + firsttime = false; + player = &players[i]; + } + else + { + if (P_AproxDistance(players[i].mo->x - actor->x, players[i].mo->y - actor->y) < + P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y)) + player = &players[i]; + } + } + + if (!player) + return; + + // Okay, we found the closest player. Let's move based on his movement. + P_SetTarget(&actor->target, player->mo); + A_FaceTarget(actor); + + if (P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y) < P_AproxDistance(player->mo->x + player->mo->momx - actor->x, player->mo->y + player->mo->momy - actor->y)) + sign = -1; // Player is moving away + else + sign = 1; // Player is moving closer + + if (player->mo->momx || player->mo->momy) + { + P_InstaThrust(actor, R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y), FixedMul(actor->info->speed*sign, actor->scale)); + + // Rotate our spike balls + actor->lastlook += actor->info->damage; + actor->lastlook %= FINEANGLES/4; + } + + if (!actor->tracer) // For some reason we do not have spike balls... + return; + + // Position spike balls relative to the value of 'lastlook'. + ball = actor->tracer; + + i = 0; + while (ball) + { + fa = actor->lastlook+i; + v[0] = FixedMul(FINECOSINE(fa),radius); + v[1] = 0; + v[2] = FixedMul(FINESINE(fa),radius); + v[3] = FRACUNIT; + + res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(actor->lastlook+i))); + M_Memcpy(&v, res, sizeof (v)); + res = VectorMatrixMultiply(v, *RotateZMatrix(actor->angle+ANGLE_180)); + M_Memcpy(&v, res, sizeof (v)); + + P_UnsetThingPosition(ball); + ball->x = actor->x + v[0]; + ball->y = actor->y + v[1]; + ball->z = actor->z + (actor->height>>1) + v[2]; + P_SetThingPosition(ball); + + ball = ball->tracer; + i += ANGLE_90 >> ANGLETOFINESHIFT; + } +} + +// Function: A_CheckBuddy +// +// Description: Checks if target/tracer exists/has health. If not, the object removes itself. +// +// var1: +// 0 = target +// 1 = tracer +// var2 = unused +// +void A_CheckBuddy(mobj_t *actor) +{ + INT32 locvar1 = var1; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckBuddy", actor)) + return; +#endif + if (locvar1 && (!actor->tracer || actor->tracer->health <= 0)) + P_RemoveMobj(actor); + else if (!locvar1 && (!actor->target || actor->target->health <= 0)) + P_RemoveMobj(actor); +} + +// Helper function for the Robo Hood. +// Don't ask me how it works. Nev3r made it with dark majyks. +static void P_ParabolicMove(mobj_t *actor, fixed_t x, fixed_t y, fixed_t z, fixed_t speed) +{ + fixed_t dh; + + x -= actor->x; + y -= actor->y; + z -= actor->z; + + dh = P_AproxDistance(x, y); + + actor->momx = FixedMul(FixedDiv(x, dh), speed); + actor->momy = FixedMul(FixedDiv(y, dh), speed); + + if (!gravity) + return; + + dh = FixedDiv(FixedMul(dh, gravity), speed); + actor->momz = (dh>>1) + FixedDiv(z, dh<<1); +} + +// Function: A_HoodFire +// +// Description: Firing Robo-Hood +// +// var1 = object type to fire +// var2 = unused +// +void A_HoodFire(mobj_t *actor) +{ + mobj_t *arrow; + INT32 locvar1 = var1; + //INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_HoodFire", actor)) + return; +#endif + + // Check target first. + if (!actor->target) + { + actor->reactiontime = actor->info->reactiontime; + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + + A_FaceTarget(actor); + + if (!(arrow = P_SpawnMissile(actor, actor->target, (mobjtype_t)locvar1))) + return; + + // Set a parabolic trajectory for the arrow. + P_ParabolicMove(arrow, actor->target->x, actor->target->y, actor->target->z, arrow->info->speed); +} + +// Function: A_HoodThink +// +// Description: Thinker for Robo-Hood +// +// var1 = unused +// var2 = unused +// +void A_HoodThink(mobj_t *actor) +{ + fixed_t dx, dy, dz, dm; + boolean checksight; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_HoodThink", actor)) + return; +#endif + + // Check target first. + if (!actor->target) + { + actor->reactiontime = actor->info->reactiontime; + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + + dx = (actor->target->x - actor->x), dy = (actor->target->y - actor->y), dz = (actor->target->z - actor->z); + dm = P_AproxDistance(dx, dy); + // Target dangerously close to robohood, retreat then. + if ((dm < 256<info->raisestate); + return; + } + + // If target on sight, look at it. + if ((checksight = P_CheckSight(actor, actor->target))) + { + angle_t dang = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + if (actor->angle >= ANGLE_180) + { + actor->angle = InvAngle(actor->angle)>>1; + actor->angle = InvAngle(actor->angle); + } + else + actor->angle >>= 1; + + if (dang >= ANGLE_180) + { + dang = InvAngle(dang)>>1; + dang = InvAngle(dang); + } + else + dang >>= 1; + + actor->angle += dang; + } + + // Check whether to do anything. + if ((--actor->reactiontime) <= 0) + { + actor->reactiontime = actor->info->reactiontime; + + // If way too far, don't shoot. + if ((dm < (3072<info->missilestate); + return; + } + } +} + +// Function: A_HoodFall +// +// Description: Falling Robo-Hood +// +// var1 = unused +// var2 = unused +// +void A_HoodFall(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_HoodFall", actor)) + return; +#endif + + if (!P_IsObjectOnGround(actor)) + return; + + actor->momx = actor->momy = 0; + actor->reactiontime = actor->info->reactiontime; + P_SetMobjState(actor, actor->info->seestate); +} + +// Function: A_ArrowBonks +// +// Description: Arrow momentum setting on collision +// +// var1 = unused +// var2 = unused +// +void A_ArrowBonks(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_ArrowBonks", actor)) + return; +#endif + + if (((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz) + || (!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)) + actor->angle += ANGLE_180; + + P_SetObjectMomZ(actor, 8*actor->scale, false); + P_InstaThrust(actor, actor->angle, -6*actor->scale); + + actor->flags = (actor->flags|MF_NOCLIPHEIGHT) & ~MF_NOGRAVITY; + actor->z += P_MobjFlip(actor); +} + +// Function: A_SnailerThink +// +// Description: Thinker function for Snailer +// +// var1 = unused +// var2 = unused +// +void A_SnailerThink(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SnailerThink", actor)) + return; +#endif + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { + // look for a new target + if (!P_LookForPlayers(actor, true, false, 0)) + return; + } + + // We now have a target. Oh bliss, rapture, and contentment! + + if (actor->target->z + actor->target->height > actor->z - FixedMul(32*FRACUNIT, actor->scale) + && actor->target->z < actor->z + actor->height + FixedMul(32*FRACUNIT, actor->scale) + && !(leveltime % (TICRATE*2))) + { + angle_t an; + fixed_t z; + + // Actor shouldn't face target, so we'll do things a bit differently here + + an = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) - actor->angle; + + z = actor->z + actor->height/2; + + if (an > ANGLE_45 && an < ANGLE_315) // fire as close as you can to the target, even if too sharp an angle from your front + { + fixed_t dist; + fixed_t dx, dy; + + dist = P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y); + + if (an > ANGLE_45 && an <= ANGLE_90) // fire at 45 degrees to the left + { + dx = actor->x + P_ReturnThrustX(actor, actor->angle + ANGLE_45, dist); + dy = actor->y + P_ReturnThrustY(actor, actor->angle + ANGLE_45, dist); + } + else if (an >= ANGLE_270 && an < ANGLE_315) // fire at 45 degrees to the right + { + dx = actor->x + P_ReturnThrustX(actor, actor->angle - ANGLE_45, dist); + dy = actor->y + P_ReturnThrustY(actor, actor->angle - ANGLE_45, dist); + } + else // fire straight ahead + { + dx = actor->x + P_ReturnThrustX(actor, actor->angle, dist); + dy = actor->y + P_ReturnThrustY(actor, actor->angle, dist); + } + + P_SpawnPointMissile(actor, dx, dy, actor->target->z, MT_ROCKET, actor->x, actor->y, z); + } + else + P_SpawnXYZMissile(actor, actor->target, MT_ROCKET, actor->x, actor->y, z); + } + + if ((!(actor->eflags & MFE_VERTICALFLIP) && actor->target->z > actor->z) + || (actor->eflags & MFE_VERTICALFLIP && (actor->target->z + actor->target->height) > (actor->z + actor->height))) + actor->momz += FixedMul(actor->info->speed, actor->scale); + else if ((!(actor->eflags & MFE_VERTICALFLIP) && actor->target->z < actor->z) + || (actor->eflags & MFE_VERTICALFLIP && (actor->target->z + actor->target->height) < (actor->z + actor->height))) + actor->momz -= FixedMul(actor->info->speed, actor->scale); + + actor->momz /= 2; +} + +// Function: A_SharpChase +// +// Description: Thinker/Chase routine for Spincushions +// +// var1 = unused +// var2 = unused +// +void A_SharpChase(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SharpChase", actor)) + return; +#endif + + if (actor->reactiontime) + { + INT32 delta; + + actor->reactiontime--; + + // turn towards movement direction if not there yet + if (actor->movedir < NUMDIRS) + { + actor->angle &= (7<<29); + delta = actor->angle - (actor->movedir << 29); + + if (delta > 0) + actor->angle -= ANGLE_45; + else if (delta < 0) + actor->angle += ANGLE_45; + } + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { + // look for a new target + if (P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + + // chase towards player + if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) + P_NewChaseDir(actor); + } + else + { + actor->threshold = actor->info->painchance; + P_SetMobjState(actor, actor->info->missilestate); + S_StartSound(actor, actor->info->attacksound); + } +} + +// Function: A_SharpSpin +// +// Description: Spin chase routine for Spincushions +// +// var1 = object # to spawn as dust (if not provided not done) +// var2 = if nonzero, do the old-style spinning using this as the angle difference +// +void A_SharpSpin(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + angle_t oldang = actor->angle; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SharpSpin", actor)) + return; +#endif + + if (actor->threshold && actor->target) + { + angle_t ang = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + P_Thrust(actor, ang, actor->info->speed*actor->scale); + if (locvar2) + actor->angle += locvar2; // ANGLE_22h; + else + actor->angle = ang; + actor->threshold--; + if (leveltime & 1) + S_StartSound(actor, actor->info->painsound); + } + else + { + actor->reactiontime = actor->info->reactiontime; + P_SetMobjState(actor, actor->info->meleestate); + } + + P_SharpDust(actor, locvar1, oldang); +} + +// Function: A_SharpDecel +// +// Description: Slow down the Spincushion +// +// var1 = unused +// var2 = unused +// +void A_SharpDecel(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SharpDecel", actor)) + return; +#endif + + if (actor->momx > 2 || actor->momy > 2) + { + actor->momx >>= 1; + actor->momy >>= 1; + } + else + P_SetMobjState(actor, actor->info->xdeathstate); +} + +// Function: A_CrushstaceanWalk +// +// Description: Crushstacean movement +// +// var1 = speed (actor info's speed if 0) +// var2 = state to switch to when blocked (spawnstate if 0) +// +void A_CrushstaceanWalk(mobj_t *actor) +{ + INT32 locvar1 = (var1 ? var1 : (INT32)actor->info->speed); + INT32 locvar2 = (var2 ? var2 : (INT32)actor->info->spawnstate); + angle_t ang = actor->angle + ((actor->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270); +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CrushstaceanWalk", actor)) + return; +#endif + + actor->reactiontime--; + + if (!P_TryMove(actor, + actor->x + P_ReturnThrustX(actor, ang, locvar1*actor->scale), + actor->y + P_ReturnThrustY(actor, ang, locvar1*actor->scale), + false) + || (actor->reactiontime-- <= 0)) + { + actor->flags2 ^= MF2_AMBUSH; + P_SetMobjState(actor, locvar2); + actor->reactiontime = actor->info->reactiontime; + } +} + +// Function: A_CrushstaceanPunch +// +// Description: Crushstacean attack +// +// var1 = unused +// var2 = state to go to if unsuccessful (spawnstate if 0) +// +void A_CrushstaceanPunch(mobj_t *actor) +{ + //INT32 locvar1 = var1; + INT32 locvar2 = (var2 ? var2 : (INT32)actor->info->spawnstate); +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CrushstaceanPunch", actor)) + return; +#endif + + if (!actor->tracer) + return; + + if (!actor->target) + { + P_SetMobjState(actor, locvar2); + return; + } + + actor->tracer->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + P_SetMobjState(actor->tracer, actor->tracer->info->missilestate); + actor->tracer->extravalue1 = actor->tracer->extravalue2 = 0; + S_StartSound(actor, actor->info->attacksound); +} + +// Function: A_CrushclawAim +// +// Description: Crushstacean claw aiming +// +// var1 = sideways offset +// var2 = vertical offset +// +void A_CrushclawAim(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *crab = actor->tracer; + angle_t ang; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CrushclawAim", actor)) + return; +#endif + + if (!crab) + { + P_RemoveMobj(actor); + return; // there is only one step and it is crab + } + + if (crab->target || P_LookForPlayers(crab, true, false, 600*crab->scale)) + ang = R_PointToAngle2(crab->x, crab->y, crab->target->x, crab->target->y); + else + ang = crab->angle + ((crab->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270); + ang -= actor->angle; + +#define anglimit ANGLE_22h +#define angfactor 5 + if (ang < ANGLE_180) + { + if (ang > anglimit) + ang = anglimit; + ang /= angfactor; + } + else + { + ang = InvAngle(ang); + if (ang > anglimit) + ang = anglimit; + ang = InvAngle(ang/angfactor); + } + actor->angle += ang; +#undef anglimit +#undef angfactor + + P_TeleportMove(actor, + crab->x + P_ReturnThrustX(actor, actor->angle, locvar1*crab->scale), + crab->y + P_ReturnThrustY(actor, actor->angle, locvar1*crab->scale), + crab->z + locvar2*crab->scale); + + if (!crab->target || !crab->info->missilestate || (statenum_t)(crab->state-states) == crab->info->missilestate) + return; + + if (((ang + ANG1) < ANG2) || P_AproxDistance(crab->x - crab->target->x, crab->y - crab->target->y) < 333*crab->scale) + P_SetMobjState(crab, crab->info->missilestate); +} + +// Function: A_CrushclawLaunch +// +// Description: Crushstacean claw launching +// +// var1: +// 0 - forwards +// anything else - backwards +// var2 = state to change to when done +// +void A_CrushclawLaunch(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *crab = actor->tracer; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CrushclawLaunch", actor)) + return; +#endif + + if (!crab) + { + mobj_t *chainnext; + while (actor) + { + chainnext = actor->target; + P_RemoveMobj(actor); + actor = chainnext; + } + return; // there is only one step and it is crab + } + + if (!actor->extravalue1) + { + S_StartSound(actor, actor->info->activesound); + actor->extravalue1 = ((locvar1) ? -1 : 32); + } + else if (actor->extravalue1 != 1) + actor->extravalue1 -= 1; + +#define CSEGS 5 + if (!actor->target) + { + mobj_t *prevchain = actor; + UINT8 i = 0; + for (i = 0; (i < CSEGS); i++) + { + mobj_t *newchain = P_SpawnMobjFromMobj(actor, 0, 0, 0, actor->info->raisestate); + prevchain->target = newchain; + prevchain = newchain; + } + actor->target->angle = R_PointToAngle2(actor->target->x, actor->target->y, crab->target->x, crab->target->y); + } + + if ((!locvar1) && crab->target) + { +#define anglimit ANGLE_22h +#define angfactor 7 + angle_t ang = R_PointToAngle2(actor->target->x, actor->target->y, crab->target->x, crab->target->y) - actor->target->angle; + if (ang < ANGLE_180) + { + if (ang > anglimit) + ang = anglimit; + ang /= angfactor; + } + else + { + ang = InvAngle(ang); + if (ang > anglimit) + ang = anglimit; + ang /= angfactor; + ang = InvAngle(ang); + } + actor->target->angle += ang; + actor->angle = actor->target->angle; + } + + actor->extravalue2 += actor->extravalue1; + + if (!P_TryMove(actor, + actor->target->x + P_ReturnThrustX(actor, actor->target->angle, actor->extravalue2*actor->scale), + actor->target->y + P_ReturnThrustY(actor, actor->target->angle, actor->extravalue2*actor->scale), + true) + && !locvar1) + { + actor->extravalue1 = 0; + actor->extravalue2 = FixedHypot(actor->x - actor->target->x, actor->y - actor->target->y)>>FRACBITS; + P_SetMobjState(actor, locvar2); + S_StopSound(actor); + S_StartSound(actor, sfx_s3k49); + } + else + { + actor->z = actor->target->z; + if ((!locvar1 && (actor->extravalue2 > 256)) || (locvar1 && (actor->extravalue2 < 16))) + { + if (locvar1) // In case of retracting, resume crab and remove the chain. + { + mobj_t *chain = actor->target, *chainnext; + while (chain) + { + chainnext = chain->target; + P_RemoveMobj(chain); + chain = chainnext; + } + actor->extravalue2 = 0; + actor->angle = R_PointToAngle2(crab->x, crab->y, actor->x, actor->y); + P_SetTarget(&actor->target, NULL); + P_SetTarget(&crab->target, NULL); + P_SetMobjState(crab, crab->state->nextstate); + } + actor->extravalue1 = 0; + P_SetMobjState(actor, locvar2); + S_StopSound(actor); + if (!locvar1) + S_StartSound(actor, sfx_s3k64); + } + } + + if (!actor->target) + return; + + { + mobj_t *chain = actor->target->target; + fixed_t dx = (actor->x - actor->target->x)/CSEGS, dy = (actor->y - actor->target->y)/CSEGS, dz = (actor->z - actor->target->z)/CSEGS; + fixed_t idx = dx, idy = dy, idz = dz; + while (chain) + { + P_TeleportMove(chain, actor->target->x + idx, actor->target->y + idy, actor->target->z + idz); + chain->watertop = chain->z; + idx += dx; + idy += dy; + idz += dz; + chain = chain->target; + } + } +#undef CSEGS +} + +// Function: A_VultureVtol +// +// Description: Vulture rising up to match target's height +// +// var1 = unused +// var2 = unused +// +void A_VultureVtol(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_VultureVtol", actor)) + return; +#endif + + if (!actor->target) + return; + + actor->flags |= MF_NOGRAVITY; + actor->flags |= MF_FLOAT; + + A_FaceTarget(actor); + + S_StopSound(actor); + + if (actor->z < actor->target->z+(actor->target->height/4) && actor->z + actor->height < actor->ceilingz) + actor->momz = FixedMul(2*FRACUNIT, actor->scale); + else if (actor->z > (actor->target->z+(actor->target->height/4)*3) && actor->z > actor->floorz) + actor->momz = FixedMul(-2*FRACUNIT, actor->scale); + else + { + // Attack! + actor->momz = 0; + P_SetMobjState(actor, actor->info->missilestate); + S_StartSound(actor, actor->info->activesound); + } +} + +// Function: A_VultureCheck +// +// Description: If the vulture is stopped, look for a new target +// +// var1 = unused +// var2 = unused +// +void A_VultureCheck(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_VultureCheck", actor)) + return; +#endif + + if (actor->momx || actor->momy) + return; + + actor->flags &= ~MF_NOGRAVITY; // Fall down + + if (actor->z <= actor->floorz) + { + actor->angle -= ANGLE_180; // turn around + P_SetMobjState(actor, actor->info->spawnstate); + } +} + +// Function: A_SkimChase +// +// Description: Thinker/Chase routine for Skims +// +// var1 = unused +// var2 = unused +// +void A_SkimChase(mobj_t *actor) +{ + INT32 delta; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SkimChase", actor)) + return; +#endif + if (actor->reactiontime) + actor->reactiontime--; + + // modify target threshold + if (actor->threshold) + { + if (!actor->target || actor->target->health <= 0) + actor->threshold = 0; + else + actor->threshold--; + } + + // turn towards movement direction if not there yet + if (actor->movedir < NUMDIRS) + { + actor->angle &= (7<<29); + delta = actor->angle - (actor->movedir << 29); + + if (delta > 0) + actor->angle -= ANGLE_45; + else if (delta < 0) + actor->angle += ANGLE_45; + } + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { + // look for a new target + P_LookForPlayers(actor, true, false, 0); + + // the spawnstate for skims already calls this function so just return either way + // without changing state + return; + } + + // do not attack twice in a row + if (actor->flags2 & MF2_JUSTATTACKED) + { + actor->flags2 &= ~MF2_JUSTATTACKED; + P_NewChaseDir(actor); + return; + } + + // check for melee attack + if (actor->info->meleestate && P_SkimCheckMeleeRange(actor)) + { + if (actor->info->attacksound) + S_StartAttackSound(actor, actor->info->attacksound); + + P_SetMobjState(actor, actor->info->meleestate); + return; + } + + // check for missile attack + if (actor->info->missilestate) + { + if (actor->movecount || !P_CheckMissileRange(actor)) + goto nomissile; + + P_SetMobjState(actor, actor->info->missilestate); + actor->flags2 |= MF2_JUSTATTACKED; + return; + } + +nomissile: + // possibly choose another target + if (multiplayer && !actor->threshold && (actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) + && P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + // chase towards player + if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) + P_NewChaseDir(actor); +} + +// Function: A_FaceTarget +// +// Description: Immediately turn to face towards your target. +// +// var1 = unused +// var2 = unused +// +void A_FaceTarget(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FaceTarget", actor)) + return; +#endif + if (!actor->target) + return; + + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); +} + +// Function: A_FaceTracer +// +// Description: Immediately turn to face towards your tracer. +// +// var1 = unused +// var2 = unused +// +void A_FaceTracer(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FaceTracer", actor)) + return; +#endif + if (!actor->tracer) + return; + + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); +} + +// Function: A_LobShot +// +// Description: Lob an object at your target. +// +// var1 = object # to lob +// var2: +// var2 >> 16 = height offset +// var2 & 65535 = airtime +// +void A_LobShot(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2 >> 16; + mobj_t *shot, *hitspot; + angle_t an; + fixed_t z; + fixed_t dist; + fixed_t vertical, horizontal; + fixed_t airtime = var2 & 65535; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_LobShot", actor)) + return; +#endif + if (!actor->target) + return; + + A_FaceTarget(actor); + + if (actor->eflags & MFE_VERTICALFLIP) + { + z = actor->z + actor->height - FixedMul(locvar2*FRACUNIT, actor->scale); + if (actor->type == MT_BLACKEGGMAN) + z -= FixedMul(mobjinfo[locvar1].height, actor->scale/2); + else + z -= FixedMul(mobjinfo[locvar1].height, actor->scale); + } + else + z = actor->z + FixedMul(locvar2*FRACUNIT, actor->scale); + + shot = P_SpawnMobj(actor->x, actor->y, z, locvar1); + + if (actor->type == MT_BLACKEGGMAN) + { + shot->destscale = actor->scale/2; + P_SetScale(shot, actor->scale/2); + } + else + { + shot->destscale = actor->scale; + P_SetScale(shot, actor->scale); + } + + // Keep track of where it's going to land + hitspot = P_SpawnMobj(actor->target->x&(64*FRACUNIT-1), actor->target->y&(64*FRACUNIT-1), actor->target->subsector->sector->floorheight, MT_NULL); + hitspot->tics = airtime; + P_SetTarget(&shot->tracer, hitspot); + + P_SetTarget(&shot->target, actor); // where it came from + + shot->angle = an = actor->angle; + an >>= ANGLETOFINESHIFT; + + dist = P_AproxDistance(actor->target->x - shot->x, actor->target->y - shot->y); + + horizontal = dist / airtime; + vertical = FixedMul((gravity*airtime)/2, shot->scale); + + shot->momx = FixedMul(horizontal, FINECOSINE(an)); + shot->momy = FixedMul(horizontal, FINESINE(an)); + shot->momz = vertical; + +/* Try to adjust when destination is not the same height + if (actor->z != actor->target->z) + { + fixed_t launchhyp; + fixed_t diff; + fixed_t orig; + + diff = actor->z - actor->target->z; + { + launchhyp = P_AproxDistance(horizontal, vertical); + + orig = FixedMul(FixedDiv(vertical, horizontal), diff); + + CONS_Debug(DBG_GAMELOGIC, "orig: %d\n", (orig)>>FRACBITS); + + horizontal = dist / airtime; + vertical = (gravity*airtime)/2; + } + dist -= orig; + shot->momx = FixedMul(horizontal, FINECOSINE(an)); + shot->momy = FixedMul(horizontal, FINESINE(an)); + shot->momz = vertical; +*/ + + if (shot->info->seesound) + S_StartSound(shot, shot->info->seesound); + + if (!(actor->flags & MF_BOSS)) + { + if (ultimatemode) + actor->reactiontime = actor->info->reactiontime*TICRATE; + else + actor->reactiontime = actor->info->reactiontime*TICRATE*2; + } +} + +// Function: A_FireShot +// +// Description: Shoot an object at your target. +// +// var1 = object # to shoot +// var2 = height offset +// +void A_FireShot(mobj_t *actor) +{ + fixed_t z; + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FireShot", actor)) + return; +#endif + if (!actor->target) + return; + + A_FaceTarget(actor); + + if (actor->eflags & MFE_VERTICALFLIP) + z = actor->z + actor->height - FixedMul(48*FRACUNIT + locvar2*FRACUNIT, actor->scale); + else + z = actor->z + FixedMul(48*FRACUNIT + locvar2*FRACUNIT, actor->scale); + + P_SpawnXYZMissile(actor, actor->target, locvar1, actor->x, actor->y, z); + + if (!(actor->flags & MF_BOSS)) + { + if (ultimatemode) + actor->reactiontime = actor->info->reactiontime*TICRATE; + else + actor->reactiontime = actor->info->reactiontime*TICRATE*2; + } +} + +// Function: A_SuperFireShot +// +// Description: Shoot an object at your target that will even stall Super Sonic. +// +// var1 = object # to shoot +// var2 = height offset +// +void A_SuperFireShot(mobj_t *actor) +{ + fixed_t z; + mobj_t *mo; + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SuperFireShot", actor)) + return; +#endif + if (!actor->target) + return; + + A_FaceTarget(actor); + + if (actor->eflags & MFE_VERTICALFLIP) + z = actor->z + actor->height - FixedMul(48*FRACUNIT + locvar2*FRACUNIT, actor->scale); + else + z = actor->z + FixedMul(48*FRACUNIT + locvar2*FRACUNIT, actor->scale); + + mo = P_SpawnXYZMissile(actor, actor->target, locvar1, actor->x, actor->y, z); + + if (mo) + mo->flags2 |= MF2_SUPERFIRE; + + if (!(actor->flags & MF_BOSS)) + { + if (ultimatemode) + actor->reactiontime = actor->info->reactiontime*TICRATE; + else + actor->reactiontime = actor->info->reactiontime*TICRATE*2; + } +} + +// Function: A_BossFireShot +// +// Description: Shoot an object at your target ala Bosses: +// +// var1 = object # to shoot +// var2: +// 0 - Boss 1 Left side +// 1 - Boss 1 Right side +// 2 - Boss 3 Left side upper +// 3 - Boss 3 Left side lower +// 4 - Boss 3 Right side upper +// 5 - Boss 3 Right side lower +// +void A_BossFireShot(mobj_t *actor) +{ + fixed_t x, y, z; + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_BossFireShot", actor)) + return; +#endif + if (!actor->target) + return; + + A_FaceTarget(actor); + + switch (locvar2) + { + case 0: + x = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); + if (actor->eflags & MFE_VERTICALFLIP) + z = actor->z + actor->height - FixedMul(48*FRACUNIT, actor->scale); + else + z = actor->z + FixedMul(48*FRACUNIT, actor->scale); + break; + case 1: + x = actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); + if (actor->eflags & MFE_VERTICALFLIP) + z = actor->z + actor->height - FixedMul(48*FRACUNIT, actor->scale); + else + z = actor->z + FixedMul(48*FRACUNIT, actor->scale); + break; + case 2: + x = actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(56*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(56*FRACUNIT, actor->scale)); + if (actor->eflags & MFE_VERTICALFLIP) + z = actor->z + actor->height - FixedMul(42*FRACUNIT, actor->scale); + else + z = actor->z + FixedMul(42*FRACUNIT, actor->scale); + break; + case 3: + x = actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(58*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(58*FRACUNIT, actor->scale)); + if (actor->eflags & MFE_VERTICALFLIP) + z = actor->z + actor->height - FixedMul(30*FRACUNIT, actor->scale); + else + z = actor->z + FixedMul(30*FRACUNIT, actor->scale); + break; + case 4: + x = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(56*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(56*FRACUNIT, actor->scale)); + if (actor->eflags & MFE_VERTICALFLIP) + z = actor->z + actor->height - FixedMul(42*FRACUNIT, actor->scale); + else + z = actor->z + FixedMul(42*FRACUNIT, actor->scale); + break; + case 5: + x = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(58*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(58*FRACUNIT, actor->scale)); + if (actor->eflags & MFE_VERTICALFLIP) + z = actor->z + actor->height - FixedMul(30*FRACUNIT, actor->scale); + else + z = actor->z + FixedMul(30*FRACUNIT, actor->scale); + break; + default: + x = actor->x; + y = actor->y; + z = actor->z + actor->height/2; + break; + } + + P_SpawnXYZMissile(actor, actor->target, locvar1, x, y, z); +} + +// Function: A_Boss7FireMissiles +// +// Description: Shoot 4 missiles of a specific object type at your target ala Black Eggman +// +// var1 = object # to shoot +// var2 = firing sound +// +void A_Boss7FireMissiles(mobj_t *actor) +{ + mobj_t dummymo; + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss7FireMissiles", actor)) + return; +#endif + + if (!actor->target) + { + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + + A_FaceTarget(actor); + + S_StartSound(NULL, locvar2); + + // set dummymo's coordinates + dummymo.x = actor->target->x; + dummymo.y = actor->target->y; + dummymo.z = actor->target->z + FixedMul(16*FRACUNIT, actor->scale); // raised height + + P_SpawnXYZMissile(actor, &dummymo, locvar1, + actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedDiv(actor->radius, 3*FRACUNIT/2)+FixedMul(4*FRACUNIT, actor->scale)), + actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedDiv(actor->radius, 3*FRACUNIT/2)+FixedMul(4*FRACUNIT, actor->scale)), + actor->z + FixedDiv(actor->height, 3*FRACUNIT/2)); + + P_SpawnXYZMissile(actor, &dummymo, locvar1, + actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedDiv(actor->radius, 3*FRACUNIT/2)+FixedMul(4*FRACUNIT, actor->scale)), + actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedDiv(actor->radius, 3*FRACUNIT/2)+FixedMul(4*FRACUNIT, actor->scale)), + actor->z + FixedDiv(actor->height, 3*FRACUNIT/2)); + + P_SpawnXYZMissile(actor, &dummymo, locvar1, + actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedDiv(actor->radius, 3*FRACUNIT/2)+FixedMul(4*FRACUNIT, actor->scale)), + actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedDiv(actor->radius, 3*FRACUNIT/2)+FixedMul(4*FRACUNIT, actor->scale)), + actor->z + actor->height/2); + + P_SpawnXYZMissile(actor, &dummymo, locvar1, + actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedDiv(actor->radius, 3*FRACUNIT/2)+FixedMul(4*FRACUNIT, actor->scale)), + actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedDiv(actor->radius, 3*FRACUNIT/2)+FixedMul(4*FRACUNIT, actor->scale)), + actor->z + actor->height/2); +} + +// Function: A_Boss1Laser +// +// Description: Shoot an object at your target ala Bosses: +// +// var1 = object # to shoot +// var2: +// 0 - Boss 1 Left side +// 1 - Boss 1 Right side +// +void A_Boss1Laser(mobj_t *actor) +{ + fixed_t x, y, z, floorz, speed; + INT32 locvar1 = var1; + INT32 locvar2 = var2; + INT32 i; + angle_t angle; + mobj_t *point; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss1Laser", actor)) + return; +#endif + if (!actor->target) + return; + + switch (locvar2) + { + case 0: + x = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); + if (actor->eflags & MFE_VERTICALFLIP) + z = actor->z + actor->height - FixedMul(56*FRACUNIT, actor->scale) - mobjinfo[locvar1].height; + else + z = actor->z + FixedMul(56*FRACUNIT, actor->scale); + break; + case 1: + x = actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); + if (actor->eflags & MFE_VERTICALFLIP) + z = actor->z + actor->height - FixedMul(56*FRACUNIT, actor->scale) - mobjinfo[locvar1].height; + else + z = actor->z + FixedMul(56*FRACUNIT, actor->scale); + break; + default: + x = actor->x; + y = actor->y; + z = actor->z + actor->height/2; + break; + } + + if (!(actor->flags2 & MF2_FIRING)) + { + actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y); + if (mobjinfo[locvar1].seesound) + S_StartSound(actor, mobjinfo[locvar1].seesound); + if (!(actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH)) + { + point = P_SpawnMobj(x + P_ReturnThrustX(actor, actor->angle, actor->radius), y + P_ReturnThrustY(actor, actor->angle, actor->radius), actor->z - actor->height / 2, MT_EGGMOBILE_TARGET); + point->angle = actor->angle; + point->fuse = actor->tics+1; + P_SetTarget(&point->target, actor->target); + P_SetTarget(&actor->target, point); + } + } + /* -- the following was relevant when the MT_EGGMOBILE_TARGET was allowed to move left and right from its path + else if (actor->target && !(actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH)) + actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y);*/ + + if (actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH) + angle = FixedAngle(FixedDiv(actor->tics*160*FRACUNIT, actor->state->tics*FRACUNIT) + 10*FRACUNIT); + else + angle = R_PointToAngle2(z + (mobjinfo[locvar1].height>>1), 0, actor->target->z, R_PointToDist2(x, y, actor->target->x, actor->target->y)); + point = P_SpawnMobj(x, y, z, locvar1); + P_SetTarget(&point->target, actor); + point->angle = actor->angle; + speed = point->radius*2; + point->momz = FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT), speed); + point->momx = FixedMul(FINESINE(angle>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(point->angle>>ANGLETOFINESHIFT), speed)); + point->momy = FixedMul(FINESINE(angle>>ANGLETOFINESHIFT), FixedMul(FINESINE(point->angle>>ANGLETOFINESHIFT), speed)); + + for (i = 0; i < 256; i++) + { + mobj_t *mo = P_SpawnMobj(point->x, point->y, point->z, point->type); + mo->angle = point->angle; + P_UnsetThingPosition(mo); + mo->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY; + P_SetThingPosition(mo); + + x = point->x, y = point->y, z = point->z; + if (P_RailThinker(point)) + break; + } + + floorz = P_FloorzAtPos(x, y, z, mobjinfo[MT_EGGMOBILE_FIRE].height); + if (z - floorz < mobjinfo[MT_EGGMOBILE_FIRE].height>>1) + { + point = P_SpawnMobj(x, y, floorz+1, MT_EGGMOBILE_FIRE); + point->target = actor; + point->destscale = 3*FRACUNIT; + point->scalespeed = FRACUNIT>>2; + point->fuse = TICRATE; + } + + if (actor->tics > 1) + actor->flags2 |= MF2_FIRING; + else + actor->flags2 &= ~MF2_FIRING; +} + +// Function: A_FocusTarget +// +// Description: Home in on your target. +// +// var1: +// 0 - accelerative focus with friction +// 1 - steady focus with fixed movement speed +// anything else - don't move +// var2: +// 0 - don't trace target, just move forwards +// & 1 - change horizontal angle +// & 2 - change vertical angle +// +void A_FocusTarget(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FocusTarget", actor)) + return; +#endif + + if (actor->target) + { + fixed_t speed = FixedMul(actor->info->speed, actor->scale); + fixed_t dist = (locvar2 ? R_PointToDist2(actor->x, actor->y, actor->target->x, actor->target->y) : speed+1); + angle_t hangle = ((locvar2 & 1) ? R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) : actor->angle); + angle_t vangle = ((locvar2 & 2) ? R_PointToAngle2(actor->z , 0, actor->target->z + (actor->target->height>>1), dist) : ANGLE_90); + switch(locvar1) + { + case 0: + { + actor->momx -= actor->momx>>4, actor->momy -= actor->momy>>4, actor->momz -= actor->momz>>4; + actor->momz += FixedMul(FINECOSINE(vangle>>ANGLETOFINESHIFT), speed); + actor->momx += FixedMul(FINESINE(vangle>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(hangle>>ANGLETOFINESHIFT), speed)); + actor->momy += FixedMul(FINESINE(vangle>>ANGLETOFINESHIFT), FixedMul(FINESINE(hangle>>ANGLETOFINESHIFT), speed)); + } + break; + case 1: + if (dist > speed) + { + actor->momz = FixedMul(FINECOSINE(vangle>>ANGLETOFINESHIFT), speed); + actor->momx = FixedMul(FINESINE(vangle>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(hangle>>ANGLETOFINESHIFT), speed)); + actor->momy = FixedMul(FINESINE(vangle>>ANGLETOFINESHIFT), FixedMul(FINESINE(hangle>>ANGLETOFINESHIFT), speed)); + } + else + { + actor->momx = 0, actor->momy = 0, actor->momz = 0; + actor->z = actor->target->z + (actor->target->height>>1); + P_TryMove(actor, actor->target->x, actor->target->y, true); + } + break; + default: + break; + } + } +} + +// Function: A_Boss4Reverse +// +// Description: Reverse arms direction. +// +// var1 = sfx to play +// var2 = unused +// +void A_Boss4Reverse(mobj_t *actor) +{ + sfxenum_t locvar1 = (sfxenum_t)var1; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss4Reverse", actor)) + return; +#endif + S_StartSound(NULL, locvar1); + actor->reactiontime = 0; + if (actor->movedir == 1) + actor->movedir = 2; + else + actor->movedir = 1; +} + +// Function: A_Boss4SpeedUp +// +// Description: Speed up arms +// +// var1 = sfx to play +// var2 = unused +// +void A_Boss4SpeedUp(mobj_t *actor) +{ + sfxenum_t locvar1 = (sfxenum_t)var1; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss4SpeedUp", actor)) + return; +#endif + S_StartSound(NULL, locvar1); + actor->reactiontime = 2; +} + +// Function: A_Boss4Raise +// +// Description: Raise helmet +// +// var1 = sfx to play +// var2 = unused +// +void A_Boss4Raise(mobj_t *actor) +{ + sfxenum_t locvar1 = (sfxenum_t)var1; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss4Raise", actor)) + return; +#endif + S_StartSound(NULL, locvar1); + actor->reactiontime = 1; +} + +// Function: A_SkullAttack +// +// Description: Fly at the player like a missile. +// +// var1: +// 0 - Fly at the player +// 1 - Fly away from the player +// 2 - Strafe in relation to the player +// var2: +// 0 - Fly horizontally and vertically +// 1 - Fly horizontal-only (momz = 0) +// +#define SKULLSPEED (20*FRACUNIT) + +void A_SkullAttack(mobj_t *actor) +{ + mobj_t *dest; + angle_t an; + INT32 dist; + INT32 speed; + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SkullAttack", actor)) + return; +#endif + if (!actor->target) + return; + + speed = FixedMul(SKULLSPEED, actor->scale); + + dest = actor->target; + actor->flags2 |= MF2_SKULLFLY; + if (actor->info->activesound) + S_StartSound(actor, actor->info->activesound); + A_FaceTarget(actor); + + if (locvar1 == 1) + actor->angle += ANGLE_180; + else if (locvar1 == 2) + actor->angle += (P_RandomChance(FRACUNIT/2)) ? ANGLE_90 : -ANGLE_90; + + an = actor->angle >> ANGLETOFINESHIFT; + + actor->momx = FixedMul(speed, FINECOSINE(an)); + actor->momy = FixedMul(speed, FINESINE(an)); + dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); + dist = dist / speed; + + if (dist < 1) + dist = 1; + + actor->momz = (dest->z + (dest->height>>1) - actor->z) / dist; + + if (locvar1 == 1) + actor->momz = -actor->momz; + if (locvar2 == 1) + actor->momz = 0; +} + +// Function: A_BossZoom +// +// Description: Like A_SkullAttack, but used by Boss 1. +// +// var1 = unused +// var2 = unused +// +void A_BossZoom(mobj_t *actor) +{ + mobj_t *dest; + angle_t an; + INT32 dist; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_BossZoom", actor)) + return; +#endif + if (!actor->target) + return; + + dest = actor->target; + actor->flags2 |= MF2_SKULLFLY; + if (actor->info->attacksound) + S_StartAttackSound(actor, actor->info->attacksound); + A_FaceTarget(actor); + an = actor->angle >> ANGLETOFINESHIFT; + actor->momx = FixedMul(FixedMul(actor->info->speed*5*FRACUNIT, actor->scale), FINECOSINE(an)); + actor->momy = FixedMul(FixedMul(actor->info->speed*5*FRACUNIT, actor->scale), FINESINE(an)); + dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); + dist = dist / FixedMul(actor->info->speed*5*FRACUNIT, actor->scale); + + if (dist < 1) + dist = 1; + actor->momz = (dest->z + (dest->height>>1) - actor->z) / dist; +} + +// Function: A_BossScream +// +// Description: Spawns explosions and plays appropriate sounds around the defeated boss. +// +// var1: +// 0 - Use movecount to spawn explosions evenly +// 1 - Use P_Random to spawn explosions at complete random +// var2 = Object to spawn. Default is MT_BOSSEXPLODE. +// +void A_BossScream(mobj_t *actor) +{ + mobj_t *mo; + fixed_t x, y, z; + angle_t fa; + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobjtype_t explodetype; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_BossScream", actor)) + return; +#endif + switch (locvar1) + { + default: + case 0: + actor->movecount += 4*16; + actor->movecount %= 360; + fa = (FixedAngle(actor->movecount*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; + break; + case 1: + fa = (FixedAngle(P_RandomKey(360)*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; + break; + } + x = actor->x + FixedMul(FINECOSINE(fa),actor->radius); + y = actor->y + FixedMul(FINESINE(fa),actor->radius); + + // Determine what mobj to spawn. If undefined or invalid, use MT_BOSSEXPLODE as default. + if (locvar2 <= 0 || locvar2 >= NUMMOBJTYPES) + explodetype = MT_BOSSEXPLODE; + else + explodetype = (mobjtype_t)locvar2; + + if (actor->eflags & MFE_VERTICALFLIP) + z = actor->z + actor->height - mobjinfo[explodetype].height - FixedMul((P_RandomByte()<<(FRACBITS-2)) - 8*FRACUNIT, actor->scale); + else + z = actor->z + FixedMul((P_RandomByte()<<(FRACBITS-2)) - 8*FRACUNIT, actor->scale); + + mo = P_SpawnMobj(x, y, z, explodetype); + if (actor->eflags & MFE_VERTICALFLIP) + mo->flags2 |= MF2_OBJECTFLIP; + mo->destscale = actor->scale; + P_SetScale(mo, mo->destscale); + if (actor->info->deathsound) + S_StartSound(mo, actor->info->deathsound); +} + +// Function: A_Scream +// +// Description: Starts the death sound of the object. +// +// var1 = unused +// var2 = unused +// +void A_Scream(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Scream", actor)) + return; +#endif + if (actor->tracer && (actor->tracer->type == MT_SHELL || actor->tracer->type == MT_FIREBALL)) + S_StartScreamSound(actor, sfx_mario2); + else if (actor->info->deathsound) + S_StartScreamSound(actor, actor->info->deathsound); +} + +// Function: A_Pain +// +// Description: Starts the pain sound of the object. +// +// var1 = unused +// var2 = unused +// +void A_Pain(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Pain", actor)) + return; +#endif + if (actor->info->painsound) + S_StartSound(actor, actor->info->painsound); + + actor->flags2 &= ~MF2_FIRING; + actor->flags2 &= ~MF2_SUPERFIRE; +} + +// Function: A_Fall +// +// Description: Changes a dying object's flags to reflect its having fallen to the ground. +// +// var1 = unused +// var2 = unused +// +void A_Fall(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Fall", actor)) + return; +#endif + // actor is on ground, it can be walked over + actor->flags &= ~MF_SOLID; + + // fall through the floor + actor->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; + + // So change this if corpse objects + // are meant to be obstacles. +} + +#define LIVESBOXDISPLAYPLAYER // Use displayplayer instead of closest player + +// Function: A_1upThinker +// +// Description: Used by the 1up box to show the player's face. +// +// var1 = unused +// var2 = unused +// +void A_1upThinker(mobj_t *actor) +{ + INT32 i; + fixed_t dist = INT32_MAX; + fixed_t temp; + INT32 closestplayer = -1; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_1upThinker", actor)) + return; +#endif + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].bot || players[i].spectator) + continue; + + if (!players[i].mo) + continue; + + if ((netgame || multiplayer) && players[i].playerstate != PST_LIVE) + continue; + + temp = P_AproxDistance(players[i].mo->x-actor->x, players[i].mo->y-actor->y); + + if (temp < dist) + { + closestplayer = i; + dist = temp; + } + } + + if (closestplayer == -1 || skins[players[closestplayer].skin].sprites[SPR2_LIFE].numframes == 0) + { // Closest player not found (no players in game?? may be empty dedicated server!), or does not have correct sprite. + if (actor->tracer) { + P_RemoveMobj(actor->tracer); + actor->tracer = NULL; + } + return; + } + + // We're using the overlay, so use the overlay 1up box (no text) + actor->sprite = SPR_TV1P; + + if (!actor->tracer) + { + P_SetTarget(&actor->tracer, P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY)); + P_SetTarget(&actor->tracer->target, actor); + actor->tracer->skin = &skins[players[closestplayer].skin]; // required here to prevent spr2 default showing stand for a single frame + P_SetMobjState(actor->tracer, actor->info->seestate); + + // The overlay is going to be one tic early turning off and on + // because it's going to get its thinker run the frame we spawned it. + // So make it take one tic longer if it just spawned. + ++actor->tracer->tics; + } + + actor->tracer->color = players[closestplayer].mo->color; + actor->tracer->skin = &skins[players[closestplayer].skin]; +} + +// Function: A_MonitorPop +// +// Description: Used by monitors when they explode. +// +// var1 = unused +// var2 = unused +// +void A_MonitorPop(mobj_t *actor) +{ + mobjtype_t item = 0; + mobj_t *newmobj; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_MonitorPop", actor)) + return; +#endif + + // Spawn the "pop" explosion. + if (actor->info->deathsound) + S_StartSound(actor, actor->info->deathsound); + P_SpawnMobjFromMobj(actor, 0, 0, actor->height/4, MT_EXPLODE); + + // We're dead now. De-solidify. + actor->health = 0; + P_UnsetThingPosition(actor); + actor->flags &= ~MF_SOLID; + actor->flags |= MF_NOCLIP; + P_SetThingPosition(actor); + + if (actor->info->damage == MT_UNKNOWN) + { + // MT_UNKNOWN is random. Because it's unknown to us... get it? + item = P_DoRandomBoxChances(); + + if (item == MT_NULL) + { + CONS_Alert(CONS_WARNING, M_GetText("All monitors turned off.\n")); + return; + } + } + else + item = actor->info->damage; + + if (item == 0) + { + CONS_Debug(DBG_GAMELOGIC, "Powerup item not defined in 'damage' field for A_MonitorPop\n"); + return; + } + + newmobj = P_SpawnMobjFromMobj(actor, 0, 0, 13*FRACUNIT, item); + P_SetTarget(&newmobj->target, actor->target); // Transfer target + + if (item == MT_1UP_ICON) + { + if (actor->tracer) // Remove the old lives icon. + P_RemoveMobj(actor->tracer); + + if (!newmobj->target + || !newmobj->target->player + || !newmobj->target->skin + || ((skin_t *)newmobj->target->skin)->sprites[SPR2_LIFE].numframes == 0) + {} // No lives icon for this player, use the default. + else + { // Spawn the lives icon. + mobj_t *livesico = P_SpawnMobjFromMobj(newmobj, 0, 0, 0, MT_OVERLAY); + P_SetTarget(&livesico->target, newmobj); + P_SetTarget(&newmobj->tracer, livesico); + + livesico->color = newmobj->target->player->mo->color; + livesico->skin = &skins[newmobj->target->player->skin]; + P_SetMobjState(livesico, newmobj->info->seestate); + + // We're using the overlay, so use the overlay 1up sprite (no text) + newmobj->sprite = SPR_TV1P; + } + } + + // Run a linedef executor immediately upon popping + // You may want to delay your effects by 18 tics to sync with the reward giving + if (actor->spawnpoint && (actor->spawnpoint->options & MTF_EXTRA) && (actor->spawnpoint->angle & 16384)) + P_LinedefExecute((actor->spawnpoint->angle & 16383), actor->target, NULL); +} + +// Function: A_GoldMonitorPop +// +// Description: Used by repeating monitors when they turn off. They don't really pop, but, you know... +// +// var1 = unused +// var2 = unused +// +void A_GoldMonitorPop(mobj_t *actor) +{ + mobjtype_t item = 0; + mobj_t *newmobj; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_GoldMonitorPop", actor)) + return; +#endif + + // Don't spawn the "pop" explosion, because the monitor isn't broken. + if (actor->info->deathsound) + S_StartSound(actor, actor->info->deathsound); + //P_SpawnMobjFromMobj(actor, 0, 0, actor.height/4, MT_EXPLODE); + + // Remove our flags for a bit. + // Players can now stand on top of us. + P_UnsetThingPosition(actor); + actor->flags &= ~(MF_MONITOR|MF_SHOOTABLE); + P_SetThingPosition(actor); + + // Don't count this box in statistics. Sorry. + if (actor->target && actor->target->player) + --actor->target->player->numboxes; + actor->fuse = 0; // Don't let the monitor code screw us up. + + if (actor->info->damage == MT_UNKNOWN) + { + // MT_UNKNOWN is random. Because it's unknown to us... get it? + item = P_DoRandomBoxChances(); + + if (item == MT_NULL) + { + CONS_Alert(CONS_WARNING, M_GetText("All monitors turned off.\n")); + return; + } + } + else + item = actor->info->damage; + + if (item == 0) + { + CONS_Debug(DBG_GAMELOGIC, "Powerup item not defined in 'damage' field for A_GoldMonitorPop\n"); + return; + } + + // Note: the icon spawns 1 fracunit higher + newmobj = P_SpawnMobjFromMobj(actor, 0, 0, 14*FRACUNIT, item); + P_SetTarget(&newmobj->target, actor->target); // Transfer target + + if (item == MT_1UP_ICON) + { + if (actor->tracer) // Remove the old lives icon. + P_RemoveMobj(actor->tracer); + + if (!newmobj->target + || !newmobj->target->player + || !newmobj->target->skin + || ((skin_t *)newmobj->target->skin)->sprites[SPR2_LIFE].numframes == 0) + {} // No lives icon for this player, use the default. + else + { // Spawn the lives icon. + mobj_t *livesico = P_SpawnMobjFromMobj(newmobj, 0, 0, 0, MT_OVERLAY); + P_SetTarget(&livesico->target, newmobj); + P_SetTarget(&newmobj->tracer, livesico); + + livesico->color = newmobj->target->player->mo->color; + livesico->skin = &skins[newmobj->target->player->skin]; + P_SetMobjState(livesico, newmobj->info->seestate); + + // We're using the overlay, so use the overlay 1up sprite (no text) + newmobj->sprite = SPR_TV1P; + } + } +} + +// Function: A_GoldMonitorRestore +// +// Description: A repeating monitor is coming back to life. Reset monitor flags, etc. +// +// var1 = unused +// var2 = unused +// +void A_GoldMonitorRestore(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_GoldMonitorRestore", actor)) + return; +#endif + + actor->flags |= MF_MONITOR|MF_SHOOTABLE; + actor->health = 1; // Just in case. +} + +// Function: A_GoldMonitorSparkle +// +// Description: Spawns the little sparkly effect around big monitors. Looks pretty, doesn't it? +// +// var1 = unused +// var2 = unused +// +void A_GoldMonitorSparkle(mobj_t *actor) +{ + fixed_t i, ngangle, xofs, yofs; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_GoldMonitorSparkle", actor)) + return; +#endif + + ngangle = FixedAngle(((leveltime * 21) % 360) << FRACBITS); + xofs = FINESINE((ngangle>>ANGLETOFINESHIFT) & FINEMASK) * (actor->radius>>FRACBITS); + yofs = FINECOSINE((ngangle>>ANGLETOFINESHIFT) & FINEMASK) * (actor->radius>>FRACBITS); + + for (i = FRACUNIT*2; i <= FRACUNIT*3; i += FRACUNIT/2) + P_SetObjectMomZ(P_SpawnMobjFromMobj(actor, xofs, yofs, 0, MT_BOXSPARKLE), i, false); +} + +// Function: A_Explode +// +// Description: Explodes an object, doing damage to any objects nearby. The target is used as the cause of the explosion. Damage value is used as explosion range. +// +// var1 = damagetype +// var2 = unused +// +void A_Explode(mobj_t *actor) +{ + INT32 locvar1 = var1; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Explode", actor)) + return; +#endif + P_RadiusAttack(actor, actor->target, actor->info->damage, locvar1); +} + +// Function: A_BossDeath +// +// Description: Possibly trigger special effects when boss dies. +// +// var1 = unused +// var2 = unused +// +void A_BossDeath(mobj_t *mo) +{ + thinker_t *th; + mobj_t *mo2; + line_t junk; + INT32 i; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_BossDeath", mo)) + return; +#endif + + P_LinedefExecute(LE_BOSSDEAD, mo, NULL); + mo->health = 0; + + // Boss is dead (but not necessarily fleeing...) + // Lua may use this to ignore bosses after they start fleeing + mo->flags2 |= MF2_BOSSDEAD; + + // make sure there is a player alive for victory + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && ((players[i].mo && players[i].mo->health) + || ((netgame || multiplayer) && (players[i].lives || players[i].continues)))) + break; + + if (i == MAXPLAYERS) + return; // no one left alive, so do not end game + + // scan the remaining thinkers to see + // if all bosses are dead + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo2 = (mobj_t *)th; + if (mo2 != mo && (mo2->flags & MF_BOSS) && mo2->health > 0) + goto bossjustdie; // other boss not dead - just go straight to dying! + } + + // victory! + P_LinedefExecute(LE_ALLBOSSESDEAD, mo, NULL); + if (mo->flags2 & MF2_BOSSNOTRAP) + { + for (i = 0; i < MAXPLAYERS; i++) + P_DoPlayerExit(&players[i]); + } + else + { + // Bring the egg trap up to the surface + junk.tag = 680; + EV_DoElevator(&junk, elevateHighest, false); + junk.tag = 681; + EV_DoElevator(&junk, elevateUp, false); + junk.tag = 682; + EV_DoElevator(&junk, elevateHighest, false); + } + +bossjustdie: +#ifdef HAVE_BLUA + if (LUAh_BossDeath(mo)) + return; + else if (P_MobjWasRemoved(mo)) + return; +#endif + if (mo->type == MT_BLACKEGGMAN || mo->type == MT_CYBRAKDEMON) + { + mo->flags |= MF_NOCLIP; + mo->flags &= ~MF_SPECIAL; + + S_StartSound(NULL, sfx_befall); + } + else if (mo->type == MT_KOOPA) + { + junk.tag = 650; + EV_DoCeiling(&junk, raiseToHighest); + return; + } + else // eggmobiles + { + // Stop exploding and prepare to run. + P_SetMobjState(mo, mo->info->xdeathstate); + if (P_MobjWasRemoved(mo)) + return; + + P_SetTarget(&mo->target, NULL); + + // Flee! Flee! Find a point to escape to! If none, just shoot upward! + // scan the thinkers to find the runaway point + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type == MT_BOSSFLYPOINT) + { + // If this one's closer then the last one, go for it. + if (!mo->target || + P_AproxDistance(P_AproxDistance(mo->x - mo2->x, mo->y - mo2->y), mo->z - mo2->z) < + P_AproxDistance(P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y), mo->z - mo->target->z)) + P_SetTarget(&mo->target, mo2); + // Otherwise... Don't! + } + } + + mo->flags |= MF_NOGRAVITY|MF_NOCLIP; + mo->flags |= MF_NOCLIPHEIGHT; + + if (mo->target) + { + mo->angle = R_PointToAngle2(mo->x, mo->y, mo->target->x, mo->target->y); + mo->flags2 |= MF2_BOSSFLEE; + mo->momz = FixedMul(FixedDiv(mo->target->z - mo->z, P_AproxDistance(mo->x-mo->target->x,mo->y-mo->target->y)), FixedMul(2*FRACUNIT, mo->scale)); + } + else + mo->momz = FixedMul(2*FRACUNIT, mo->scale); + } + + if (mo->type == MT_EGGMOBILE2) + { + mo2 = P_SpawnMobj(mo->x + P_ReturnThrustX(mo, mo->angle - ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), + mo->y + P_ReturnThrustY(mo, mo->angle - ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), + mo->z + mo->height/2 + ((mo->eflags & MFE_VERTICALFLIP)? FixedMul(8*FRACUNIT, mo->scale)-mobjinfo[MT_BOSSTANK1].height : -FixedMul(8*FRACUNIT, mo->scale)), MT_BOSSTANK1); // Right tank + mo2->angle = mo->angle; + mo2->destscale = mo->scale; + P_SetScale(mo2, mo2->destscale); + if (mo->eflags & MFE_VERTICALFLIP) + { + mo2->eflags |= MFE_VERTICALFLIP; + mo2->flags2 |= MF2_OBJECTFLIP; + } + P_InstaThrust(mo2, mo2->angle - ANGLE_90, FixedMul(4*FRACUNIT, mo2->scale)); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + + mo2 = P_SpawnMobj(mo->x + P_ReturnThrustX(mo, mo->angle + ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), + mo->y + P_ReturnThrustY(mo, mo->angle + ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), + mo->z + mo->height/2 + ((mo->eflags & MFE_VERTICALFLIP)? FixedMul(8*FRACUNIT, mo->scale)-mobjinfo[MT_BOSSTANK2].height : -FixedMul(8*FRACUNIT, mo->scale)), MT_BOSSTANK2); // Left tank + mo2->angle = mo->angle; + mo2->destscale = mo->scale; + P_SetScale(mo2, mo2->destscale); + if (mo->eflags & MFE_VERTICALFLIP) + { + mo2->eflags |= MFE_VERTICALFLIP; + mo2->flags2 |= MF2_OBJECTFLIP; + } + P_InstaThrust(mo2, mo2->angle + ANGLE_90, FixedMul(4*FRACUNIT, mo2->scale)); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + + mo2 = P_SpawnMobj(mo->x, mo->y, + mo->z + ((mo->eflags & MFE_VERTICALFLIP)? mobjinfo[MT_BOSSSPIGOT].height-FixedMul(32*FRACUNIT,mo->scale): mo->height + FixedMul(32*FRACUNIT, mo->scale)), MT_BOSSSPIGOT); + mo2->angle = mo->angle; + mo2->destscale = mo->scale; + P_SetScale(mo2, mo2->destscale); + if (mo->eflags & MFE_VERTICALFLIP) + { + mo2->eflags |= MFE_VERTICALFLIP; + mo2->flags2 |= MF2_OBJECTFLIP; + } + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + return; + } +} + +// Function: A_CustomPower +// +// Description: Provides a custom powerup. Target (must be a player) is awarded the powerup. Reactiontime of the object is used as an index to the powers array. +// +// var1 = Power index # +// var2 = Power duration in tics +// +void A_CustomPower(mobj_t *actor) +{ + player_t *player; + INT32 locvar1 = var1; + INT32 locvar2 = var2; + boolean spawnshield = false; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CustomPower", actor)) + return; +#endif + if (!actor->target || !actor->target->player) + { + CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); + return; + } + + if (locvar1 >= NUMPOWERS) + { + CONS_Debug(DBG_GAMELOGIC, "Power #%d out of range!\n", locvar1); + return; + } + + player = actor->target->player; + + if (locvar1 == pw_shield && player->powers[pw_shield] != locvar2) + spawnshield = true; + + player->powers[locvar1] = (UINT16)locvar2; + if (actor->info->seesound) + S_StartSound(player->mo, actor->info->seesound); + + if (spawnshield) //workaround for a bug + P_SpawnShieldOrb(player); +} + +// Function: A_GiveWeapon +// +// Description: Gives the player the specified weapon panels. +// +// var1 = Weapon index # +// var2 = unused +// +void A_GiveWeapon(mobj_t *actor) +{ + player_t *player; + INT32 locvar1 = var1; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_GiveWeapon", actor)) + return; +#endif + if (!actor->target || !actor->target->player) + { + CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); + return; + } + + if (locvar1 >= 1<<(NUM_WEAPONS-1)) + { + CONS_Debug(DBG_GAMELOGIC, "Weapon #%d out of range!\n", locvar1); + return; + } + + player = actor->target->player; + + player->ringweapons |= locvar1; + if (actor->info->seesound) + S_StartSound(player->mo, actor->info->seesound); +} + +// Function: A_RingBox +// +// Description: Awards the player 10 rings. +// +// var1 = unused +// var2 = unused +// +void A_RingBox(mobj_t *actor) +{ + player_t *player; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RingBox", actor)) + return; +#endif + if (!actor->target || !actor->target->player) + { + CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); + return; + } + + player = actor->target->player; + + P_GivePlayerRings(player, actor->info->reactiontime); + if (actor->info->seesound) + S_StartSound(player->mo, actor->info->seesound); +} + +// Function: A_Invincibility +// +// Description: Awards the player invincibility. +// +// var1 = unused +// var2 = unused +// +void A_Invincibility(mobj_t *actor) +{ + player_t *player; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Invincibility", actor)) + return; +#endif + if (!actor->target || !actor->target->player) + { + CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); + return; + } + + player = actor->target->player; + player->powers[pw_invulnerability] = invulntics + 1; + + if (P_IsLocalPlayer(player) && !player->powers[pw_super]) + { + S_StopMusic(); + if (mariomode) + G_GhostAddColor(GHC_INVINCIBLE); + strlcpy(S_sfx[sfx_None].caption, "Invincibility", 14); + S_StartCaption(sfx_None, -1, player->powers[pw_invulnerability]); + S_ChangeMusicInternal((mariomode) ? "_minv" : "_inv", false); + } +} + +// Function: A_SuperSneakers +// +// Description: Awards the player super sneakers. +// +// var1 = unused +// var2 = unused +// +void A_SuperSneakers(mobj_t *actor) +{ + player_t *player; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SuperSneakers", actor)) + return; +#endif + if (!actor->target || !actor->target->player) + { + CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); + return; + } + + player = actor->target->player; + + actor->target->player->powers[pw_sneakers] = sneakertics + 1; + + if (P_IsLocalPlayer(player) && !player->powers[pw_super]) + { + if (S_SpeedMusic(0.0f) && (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)) + S_SpeedMusic(1.4f); + else + { + S_StopMusic(); + S_ChangeMusicInternal("_shoes", false); + } + strlcpy(S_sfx[sfx_None].caption, "Speed shoes", 12); + S_StartCaption(sfx_None, -1, player->powers[pw_sneakers]); + } +} + +// Function: A_AwardScore +// +// Description: Adds a set amount of points to the player's score. +// +// var1 = unused +// var2 = unused +// +void A_AwardScore(mobj_t *actor) +{ + player_t *player; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_AwardScore", actor)) + return; +#endif + if (!actor->target || !actor->target->player) + { + CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); + return; + } + + player = actor->target->player; + + P_AddPlayerScore(player, actor->info->reactiontime); + if (actor->info->seesound) + S_StartSound(player->mo, actor->info->seesound); +} + +// Function: A_ExtraLife +// +// Description: Awards the player an extra life. +// +// var1 = unused +// var2 = unused +// +void A_ExtraLife(mobj_t *actor) +{ + player_t *player; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_ExtraLife", actor)) + return; +#endif + if (!actor->target || !actor->target->player) + { + CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); + return; + } + + player = actor->target->player; + + if (actor->type == MT_1UP_ICON && actor->tracer) + { + // We're using the overlay, so use the overlay 1up sprite (no text) + actor->sprite = SPR_TV1P; + } + + if (ultimatemode) //I don't THINK so! + { + S_StartSound(player->mo, sfx_lose); + return; + } + + P_GiveCoopLives(player, 1, true); +} + +// Function: A_GiveShield +// +// Description: Awards the player a specified shield. +// +// var1 = Shield type (make with SH_ constants) +// var2 = unused +// +void A_GiveShield(mobj_t *actor) +{ + player_t *player; + UINT16 locvar1 = var1; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_GiveShield", actor)) + return; +#endif + if (!actor->target || !actor->target->player) + { + CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); + return; + } + + player = actor->target->player; + + P_SwitchShield(player, locvar1); + S_StartSound(player->mo, actor->info->seesound); +} + +// Function: A_GravityBox +// +// Description: Awards the player gravity boots. +// +// var1 = unused +// var2 = unused +// +void A_GravityBox(mobj_t *actor) +{ + player_t *player; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_GravityBox", actor)) + return; +#endif + if (!actor->target || !actor->target->player) + { + CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); + return; + } + + player = actor->target->player; + + S_StartSound(player, actor->info->activesound); + + player->powers[pw_gravityboots] = (UINT16)(actor->info->reactiontime + 1); +} + +// Function: A_ScoreRise +// +// Description: Makes the little score logos rise. Speed value sets speed. +// +// var1 = unused +// var2 = unused +// +void A_ScoreRise(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_ScoreRise", actor)) + return; +#endif + // make logo rise! + P_SetObjectMomZ(actor, actor->info->speed, false); +} + +// Function: A_BunnyHop +// +// Description: Makes object hop like a bunny. +// +// var1 = jump strength +// var2 = horizontal movement +// +void A_BunnyHop(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_BunnyHop", actor)) + return; +#endif + if (((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz) + || (!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)) + { + P_SetObjectMomZ(actor, locvar1*FRACUNIT, false); + P_InstaThrust(actor, actor->angle, FixedMul(locvar2*FRACUNIT, actor->scale)); // Launch the hopping action! PHOOM!! + } +} + +// Function: A_BubbleSpawn +// +// Description: Spawns a randomly sized bubble from the object's location. Only works underwater. +// +// var1 = Distance to look for players. If no player is in this distance, bubbles aren't spawned. (Ambush overrides) +// var2 = unused +// +void A_BubbleSpawn(mobj_t *actor) +{ + INT32 i, locvar1 = var1; + UINT8 prandom; + mobj_t *bubble = NULL; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_BubbleSpawn", actor)) + return; +#endif + if (!(actor->eflags & MFE_UNDERWATER)) + { + // Don't draw or spawn bubbles above water + actor->flags2 |= MF2_DONTDRAW; + return; + } + actor->flags2 &= ~MF2_DONTDRAW; + + if (!(actor->flags2 & MF2_AMBUSH)) + { + // Quick! Look through players! + // Don't spawn bubbles unless a player is relatively close by (var1). + for (i = 0; i < MAXPLAYERS; ++i) + if (playeringame[i] && players[i].mo + && P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (locvar1<x, actor->y, actor->z + (actor->height / 2), MT_EXTRALARGEBUBBLE); + else if (prandom > 128) + bubble = P_SpawnMobj(actor->x, actor->y, actor->z + (actor->height / 2), MT_SMALLBUBBLE); + else if (prandom < 128 && prandom > 96) + bubble = P_SpawnMobj(actor->x, actor->y, actor->z + (actor->height / 2), MT_MEDIUMBUBBLE); + + if (bubble) + { + bubble->destscale = actor->scale; + P_SetScale(bubble, actor->scale); + } +} + +// Function: A_FanBubbleSpawn +// +// Description: Spawns bubbles from fans, if they're underwater. +// +// var1 = Distance to look for players. If no player is in this distance, bubbles aren't spawned. (Ambush overrides) +// var2 = unused +// +void A_FanBubbleSpawn(mobj_t *actor) +{ + INT32 i, locvar1 = var1; + UINT8 prandom; + mobj_t *bubble = NULL; + fixed_t hz = actor->z + (4*actor->height)/5; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FanBubbleSpawn", actor)) + return; +#endif + if (!(actor->eflags & MFE_UNDERWATER)) + return; + + if (!(actor->flags2 & MF2_AMBUSH)) + { + // Quick! Look through players! + // Don't spawn bubbles unless a player is relatively close by (var2). + for (i = 0; i < MAXPLAYERS; ++i) + if (playeringame[i] && players[i].mo + && P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (locvar1<x, actor->y, hz, MT_SMALLBUBBLE); + else if ((prandom & 0xF0) == 0xF0) + bubble = P_SpawnMobj(actor->x, actor->y, hz, MT_MEDIUMBUBBLE); + + if (bubble) + { + bubble->destscale = actor->scale; + P_SetScale(bubble, actor->scale); + } +} + +// Function: A_BubbleRise +// +// Description: Raises a bubble +// +// var1: +// 0 = Bend around the water abit, looking more realistic +// 1 = Rise straight up +// var2 = rising speed +// +void A_BubbleRise(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_BubbleRise", actor)) + return; +#endif + if (actor->type == MT_EXTRALARGEBUBBLE) + P_SetObjectMomZ(actor, FixedDiv(6*FRACUNIT,5*FRACUNIT), false); // make bubbles rise! + else + { + P_SetObjectMomZ(actor, locvar2, true); // make bubbles rise! + + // Move around slightly to make it look like it's bending around the water + if (!locvar1) + { + UINT8 prandom = P_RandomByte(); + if (!(prandom & 0x7)) // *****000 + { + P_InstaThrust(actor, prandom & 0x70 ? actor->angle + ANGLE_90 : actor->angle, + FixedMul(prandom & 0xF0 ? FRACUNIT/2 : -FRACUNIT/2, actor->scale)); + } + else if (!(prandom & 0x38)) // **000*** + { + P_InstaThrust(actor, prandom & 0x70 ? actor->angle - ANGLE_90 : actor->angle - ANGLE_180, + FixedMul(prandom & 0xF0 ? FRACUNIT/2 : -FRACUNIT/2, actor->scale)); + } + } + } +} + +// Function: A_BubbleCheck +// +// Description: Checks if a bubble should be drawn or not. Bubbles are not drawn above water. +// +// var1 = unused +// var2 = unused +// +void A_BubbleCheck(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_BubbleCheck", actor)) + return; +#endif + if (actor->eflags & MFE_UNDERWATER) + actor->flags2 &= ~MF2_DONTDRAW; // underwater so draw + else + actor->flags2 |= MF2_DONTDRAW; // above water so don't draw +} + +// Function: A_AttractChase +// +// Description: Makes a ring chase after a player with a ring shield and also causes spilled rings to flicker. +// +// var1 = unused +// var2 = unused +// +void A_AttractChase(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_AttractChase", actor)) + return; +#endif + if (actor->flags2 & MF2_NIGHTSPULL || !actor->health) + return; + + // spilled rings flicker before disappearing + if (leveltime & 1 && actor->type == (mobjtype_t)actor->info->reactiontime && actor->fuse && actor->fuse < 2*TICRATE) + actor->flags2 |= MF2_DONTDRAW; + else + actor->flags2 &= ~MF2_DONTDRAW; + + // Turn flingrings back into regular rings if attracted. + if (actor->tracer && actor->tracer->player + && !(actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC) && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime) + { + mobj_t *newring; + newring = P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->reactiontime); + newring->momx = actor->momx; + newring->momy = actor->momy; + newring->momz = actor->momz; + P_RemoveMobj(actor); + return; + } + + P_LookForShield(actor); // Go find 'em, boy! + + if (!actor->tracer + || !actor->tracer->player + || !actor->tracer->health + || !P_CheckSight(actor, actor->tracer)) // You have to be able to SEE it...sorta + { + // Lost attracted rings don't through walls anymore. + actor->flags &= ~MF_NOCLIP; + P_SetTarget(&actor->tracer, NULL); + return; + } + + // If a FlingRing gets attracted by a shield, change it into a normal ring. + if (actor->type == (mobjtype_t)actor->info->reactiontime) + { + P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->painchance); + P_RemoveMobj(actor); + return; + } + + // Keep stuff from going down inside floors and junk + actor->flags &= ~MF_NOCLIPHEIGHT; + + // Let attracted rings move through walls and such. + actor->flags |= MF_NOCLIP; + + P_Attract(actor, actor->tracer, false); +} + +// Function: A_DropMine +// +// Description: Drops a mine. Raisestate specifies the object # to use for the mine. +// +// var1 = height offset +// var2: +// lower 16 bits = proximity check distance (0 disables) +// upper 16 bits = 0 to check proximity with target, 1 for tracer +// +void A_DropMine(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + fixed_t z; + mobj_t *mine; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_DropMine", actor)) + return; +#endif + + if (locvar2 & 65535) + { + fixed_t dist; + mobj_t *target; + + if (locvar2 >> 16) + target = actor->tracer; + else + target = actor->target; + + if (!target) + return; + + dist = P_AproxDistance(actor->x-target->x, actor->y-target->y)>>FRACBITS; + + if (dist > FixedMul((locvar2 & 65535), actor->scale)) + return; + } + + if (actor->eflags & MFE_VERTICALFLIP) + z = actor->z + actor->height - mobjinfo[actor->info->raisestate].height - FixedMul((locvar1*FRACUNIT) - 12*FRACUNIT, actor->scale); + else + z = actor->z + FixedMul((locvar1*FRACUNIT) - 12*FRACUNIT, actor->scale); + + // Use raisestate instead of MT_MINE + mine = P_SpawnMobj(actor->x, actor->y, z, (mobjtype_t)actor->info->raisestate); + if (actor->eflags & MFE_VERTICALFLIP) + mine->eflags |= MFE_VERTICALFLIP; + mine->momz = actor->momz + actor->pmomz; + + S_StartSound(actor, actor->info->attacksound); +} + +// Function: A_FishJump +// +// Description: Makes the stupid harmless fish in Greenflower Zone jump. +// +// var1 = Jump strength (in FRACBITS), if specified. Otherwise, uses the angle value. +// var2 = unused +// +void A_FishJump(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FishJump", actor)) + return; +#endif + + if (locvar2) + { + fixed_t rad = actor->radius>>FRACBITS; + P_SpawnMobjFromMobj(actor, P_RandomRange(rad, -rad)<z <= actor->floorz) || (actor->z <= actor->watertop - FixedMul((64 << FRACBITS), actor->scale))) + { + fixed_t jumpval; + + if (locvar1) + jumpval = var1; + else + jumpval = FixedMul(AngleFixed(actor->angle)/4, actor->scale); + + if (!jumpval) jumpval = FixedMul(44*(FRACUNIT/4), actor->scale); + actor->momz = jumpval; + P_SetMobjStateNF(actor, actor->info->seestate); + } + + if (actor->momz < 0 + && (actor->state < &states[actor->info->meleestate] || actor->state > &states[actor->info->xdeathstate])) + P_SetMobjStateNF(actor, actor->info->meleestate); +} + +// Function:A_ThrownRing +// +// Description: Thinker for thrown rings/sparkle trail +// +// var1 = unused +// var2 = unused +// +void A_ThrownRing(mobj_t *actor) +{ + INT32 c = 0; + INT32 stop; + player_t *player; + fixed_t dist; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_ThrownRing", actor)) + return; +#endif + + if (leveltime % (TICRATE/7) == 0) + { + mobj_t *ring = NULL; + + if (actor->flags2 & MF2_EXPLOSION) + { + if (actor->momx != 0 || actor->momy != 0) + ring = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMOKE); + // Else spawn nothing because it's totally stationary and constantly smoking would be weird -SH + } + else if (actor->flags2 & MF2_AUTOMATIC) + ring = P_SpawnGhostMobj(actor); + else if (!(actor->flags2 & MF2_RAILRING)) + ring = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SPARK); + + if (ring) + { + /* + P_SetTarget(&ring->target, actor); + ring->color = actor->color; //copy color + */ + ring->destscale = actor->scale; + P_SetScale(ring, actor->scale); + } + } + + // A_GrenadeRing beeping lives once moooooore -SH + if (actor->type == MT_THROWNGRENADE && actor->fuse % TICRATE == 0) + S_StartSound(actor, actor->info->attacksound); + + // decrement bounce ring time + if (actor->flags2 & MF2_BOUNCERING) + { + if (actor->fuse) + actor->fuse--; + else { + P_RemoveMobj(actor); + return; + } + } + + // spilled rings (and thrown bounce) flicker before disappearing + if (leveltime & 1 && actor->fuse > 0 && actor->fuse < 2*TICRATE + && actor->type != MT_THROWNGRENADE) + actor->flags2 |= MF2_DONTDRAW; + else + actor->flags2 &= ~MF2_DONTDRAW; + + if (actor->tracer && actor->tracer->health <= 0) + P_SetTarget(&actor->tracer, NULL); + + // Updated homing ring special capability + // If you have a ring shield, all rings thrown + // at you become homing (except rail)! + if (actor->tracer) + { + // A non-homing ring getting attracted by a + // magnetic player. If he gets too far away, make + // sure to stop the attraction! + if ((!actor->tracer->health) || (actor->tracer->player && (actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC) + && P_AproxDistance(P_AproxDistance(actor->tracer->x-actor->x, + actor->tracer->y-actor->y), actor->tracer->z-actor->z) > FixedMul(RING_DIST/4, actor->tracer->scale))) + { + P_SetTarget(&actor->tracer, NULL); + } + + if (actor->tracer && (actor->tracer->health) + && (actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC))// Already found someone to follow. + { + const INT32 temp = actor->threshold; + actor->threshold = 32000; + P_HomingAttack(actor, actor->tracer); + actor->threshold = temp; + return; + } + } + + // first time init, this allow minimum lastlook changes + if (actor->lastlook < 0) + actor->lastlook = P_RandomByte(); + + actor->lastlook %= MAXPLAYERS; + + stop = (actor->lastlook - 1) & PLAYERSMASK; + + for (; ; actor->lastlook = (actor->lastlook + 1) & PLAYERSMASK) + { + // done looking + if (actor->lastlook == stop) + return; + + if (!playeringame[actor->lastlook]) + continue; + + if (c++ == 2) + return; + + player = &players[actor->lastlook]; + + if (!player->mo) + continue; + + if (player->mo->health <= 0) + continue; // dead + + if ((netgame || multiplayer) && player->spectator) + continue; // spectator + + if (actor->target && actor->target->player) + { + if (player->mo == actor->target) + continue; + + // Don't home in on teammates. + if (gametype == GT_CTF + && actor->target->player->ctfteam == player->ctfteam) + continue; + } + + dist = P_AproxDistance(P_AproxDistance(player->mo->x-actor->x, + player->mo->y-actor->y), player->mo->z-actor->z); + + // check distance + if (actor->flags2 & MF2_RAILRING) + { + if (dist > FixedMul(RING_DIST/2, player->mo->scale)) + continue; + } + else if (dist > FixedMul(RING_DIST, player->mo->scale)) + continue; + + // do this after distance check because it's more computationally expensive + if (!P_CheckSight(actor, player->mo)) + continue; // out of sight + + if ((player->powers[pw_shield] & SH_PROTECTELECTRIC) + && dist < FixedMul(RING_DIST/4, player->mo->scale)) + P_SetTarget(&actor->tracer, player->mo); + return; + } + + return; +} + +// Function: A_SetSolidSteam +// +// Description: Makes steam solid so it collides with the player to boost them. +// +// var1 = unused +// var2 = unused +// +void A_SetSolidSteam(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetSolidSteam", actor)) + return; +#endif + actor->flags &= ~MF_NOCLIP; + actor->flags |= MF_SOLID; + if (!(actor->flags2 & MF2_AMBUSH)) + { + if (P_RandomChance(FRACUNIT/8)) + { + if (actor->info->deathsound) + S_StartSound(actor, actor->info->deathsound); // Hiss! + } + else + { + if (actor->info->painsound) + S_StartSound(actor, actor->info->painsound); + } + } + + P_SetObjectMomZ (actor, 1, true); +} + +// Function: A_UnsetSolidSteam +// +// Description: Makes an object non-solid and also noclip. Used by the steam. +// +// var1 = unused +// var2 = unused +// +void A_UnsetSolidSteam(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_UnsetSolidSteam", actor)) + return; +#endif + actor->flags &= ~MF_SOLID; + actor->flags |= MF_NOCLIP; +} + +// Function: A_SignPlayer +// +// Description: Changes the state of a level end sign to reflect the player that hit it. +// +// var1 = unused +// var2 = unused +// +void A_SignPlayer(mobj_t *actor) +{ + mobj_t *ov; + skin_t *skin; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SignPlayer", actor)) + return; +#endif + if (!actor->target) + return; + + if (!actor->target->player) + return; + + skin = &skins[actor->target->player->skin]; + + if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor? + { + actor->color = skin->prefoppositecolor; + /* + If you're here from the comment above Color_Opposite, + the following line is the one which is dependent on the + array being symmetrical. It gets the opposite of the + opposite of your desired colour just so it can get the + brightness frame for the End Sign. It's not a great + design choice, but it's constant time array access and + the idea that the colours should be OPPOSITES is kind + of in the name. If you have a better idea, feel free + to let me know. ~toast 2016/07/20 + */ + actor->frame += (15 - Color_Opposite[(Color_Opposite[(skin->prefoppositecolor - 1)*2] - 1)*2 + 1]); + } + else if (actor->target->player->skincolor) // Set the sign to be an appropriate background color for this player's skincolor. + { + actor->color = Color_Opposite[(actor->target->player->skincolor - 1)*2]; + actor->frame += (15 - Color_Opposite[(actor->target->player->skincolor - 1)*2 + 1]); + } + + if (skin->sprites[SPR2_SIGN].numframes) + { + // spawn an overlay of the player's face. + ov = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY); + P_SetTarget(&ov->target, actor); + ov->color = actor->target->player->skincolor; + ov->skin = skin; + P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN + } +} + +// Function: A_OverlayThink +// +// Description: Moves the overlay to the position of its target. +// +// var1 = unused +// var2 = invert, z offset +// +void A_OverlayThink(mobj_t *actor) +{ + fixed_t destx, desty; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_OverlayThink", actor)) + return; +#endif + if (!actor->target) + return; + + if (!splitscreen && rendermode != render_soft) + { + angle_t viewingangle; + + if (players[displayplayer].awayviewtics) + viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, players[displayplayer].awayviewmobj->x, players[displayplayer].awayviewmobj->y); + else if (!camera.chase && players[displayplayer].mo) + viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, players[displayplayer].mo->x, players[displayplayer].mo->y); + else + viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, camera.x, camera.y); + + destx = actor->target->x + P_ReturnThrustX(actor->target, viewingangle, FixedMul(FRACUNIT, actor->scale)); + desty = actor->target->y + P_ReturnThrustY(actor->target, viewingangle, FixedMul(FRACUNIT, actor->scale)); + } + else + { + destx = actor->target->x; + desty = actor->target->y; + } + P_UnsetThingPosition(actor); + actor->x = destx; + actor->y = desty; + P_SetThingPosition(actor); + if (actor->eflags & MFE_VERTICALFLIP) + actor->z = actor->target->z + actor->target->height - mobjinfo[actor->type].height - ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT; + else + actor->z = actor->target->z + ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT; + actor->angle = actor->target->angle; + actor->eflags = actor->target->eflags; + + actor->momx = actor->target->momx; + actor->momy = actor->target->momy; + actor->momz = actor->target->momz; // assume target has correct momz! Do not use P_SetObjectMomZ! +} + +// Function: A_JetChase +// +// Description: A_Chase for Jettysyns +// +// var1 = unused +// var2 = unused +// +void A_JetChase(mobj_t *actor) +{ + fixed_t thefloor; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_JetChase", actor)) + return; +#endif + + if (actor->flags2 & MF2_AMBUSH) + return; + + if (actor->z >= actor->waterbottom && actor->watertop > actor->floorz + && actor->z > actor->watertop - FixedMul(256*FRACUNIT, actor->scale)) + thefloor = actor->watertop; + else + thefloor = actor->floorz; + + if (actor->reactiontime) + actor->reactiontime--; + + if (P_RandomChance(FRACUNIT/32)) + { + actor->momx = actor->momx / 2; + actor->momy = actor->momy / 2; + actor->momz = actor->momz / 2; + } + + // Bounce if too close to floor or ceiling - + // ideal for Jetty-Syns above you on 3d floors + if (actor->momz && ((actor->z - FixedMul((32<scale)) < thefloor) && !((thefloor + FixedMul(32*FRACUNIT, actor->scale) + actor->height) > actor->ceilingz)) + actor->momz = -actor->momz/2; + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { + // look for a new target + if (P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + actor->momx = actor->momy = actor->momz = 0; + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + + // modify target threshold + if (actor->threshold) + { + if (!actor->target || actor->target->health <= 0) + actor->threshold = 0; + else + actor->threshold--; + } + + // turn towards movement direction if not there yet + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + + if ((multiplayer || netgame) && !actor->threshold && (actor->target->health <= 0 || !P_CheckSight(actor, actor->target))) + if (P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + // If the player is over 3072 fracunits away, then look for another player + if (P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), + actor->target->z - actor->z) > FixedMul(3072*FRACUNIT, actor->scale) && P_LookForPlayers(actor, true, false, FixedMul(3072*FRACUNIT, actor->scale))) + { + return; // got a new target + } + + // chase towards player + if (ultimatemode) + P_Thrust(actor, actor->angle, FixedMul(actor->info->speed/2, actor->scale)); + else + P_Thrust(actor, actor->angle, FixedMul(actor->info->speed/4, actor->scale)); + + // must adjust height + if (ultimatemode) + { + if (actor->z < (actor->target->z + actor->target->height + FixedMul((64<scale))) + actor->momz += FixedMul(FRACUNIT/2, actor->scale); + else + actor->momz -= FixedMul(FRACUNIT/2, actor->scale); + } + else + { + if (actor->z < (actor->target->z + actor->target->height + FixedMul((32<scale))) + actor->momz += FixedMul(FRACUNIT/2, actor->scale); + else + actor->momz -= FixedMul(FRACUNIT/2, actor->scale); + } +} + +// Function: A_JetbThink +// +// Description: Thinker for Jetty-Syn bombers +// +// var1 = unused +// var2 = unused +// +void A_JetbThink(mobj_t *actor) +{ + sector_t *nextsector; + fixed_t thefloor; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_JetbThink", actor)) + return; +#endif + + if (actor->z >= actor->waterbottom && actor->watertop > actor->floorz + && actor->z > actor->watertop - FixedMul(256*FRACUNIT, actor->scale)) + thefloor = actor->watertop; + else + thefloor = actor->floorz; + + if (actor->target) + { + A_JetChase(actor); + // check for melee attack + if (actor->info->raisestate + && (actor->z > (actor->floorz + FixedMul((32<scale))) + && P_JetbCheckMeleeRange(actor) && !actor->reactiontime + && (actor->target->z >= actor->floorz)) + { + mobj_t *bomb; + if (actor->info->attacksound) + S_StartAttackSound(actor, actor->info->attacksound); + + // use raisestate instead of MT_MINE + bomb = P_SpawnMobj(actor->x, actor->y, actor->z - FixedMul((32<scale), (mobjtype_t)actor->info->raisestate); + + P_SetTarget(&bomb->target, actor); + bomb->destscale = actor->scale; + P_SetScale(bomb, actor->scale); + actor->reactiontime = TICRATE; // one second + S_StartSound(actor, actor->info->attacksound); + } + } + else if (((actor->z - FixedMul((32<scale)) < thefloor) && !((thefloor + FixedMul((32<scale) + actor->height) > actor->ceilingz)) + actor->z = thefloor+FixedMul((32<scale); + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { + // look for a new target + if (P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + + nextsector = R_PointInSubsector(actor->x + actor->momx, actor->y + actor->momy)->sector; + + // Move downwards or upwards to go through a passageway. + if (nextsector->ceilingheight < actor->z + actor->height) + actor->momz -= FixedMul(5*FRACUNIT, actor->scale); + else if (nextsector->floorheight > actor->z) + actor->momz += FixedMul(5*FRACUNIT, actor->scale); +} + +// Function: A_JetgShoot +// +// Description: Firing function for Jetty-Syn gunners. +// +// var1 = unused +// var2 = unused +// +void A_JetgShoot(mobj_t *actor) +{ + fixed_t dist; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_JetgShoot", actor)) + return; +#endif + + if (!actor->target) + return; + + if (actor->reactiontime) + return; + + dist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); + + if (dist > FixedMul(actor->info->painchance*FRACUNIT, actor->scale)) + return; + + if (dist < FixedMul(64*FRACUNIT, actor->scale)) + return; + + A_FaceTarget(actor); + P_SpawnMissile(actor, actor->target, (mobjtype_t)actor->info->raisestate); + + if (ultimatemode) + actor->reactiontime = actor->info->reactiontime*TICRATE; + else + actor->reactiontime = actor->info->reactiontime*TICRATE*2; + + if (actor->info->attacksound) + S_StartSound(actor, actor->info->attacksound); +} + +// Function: A_ShootBullet +// +// Description: Shoots a bullet. Raisestate defines object # to use as projectile. +// +// var1 = unused +// var2 = unused +// +void A_ShootBullet(mobj_t *actor) +{ + fixed_t dist; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_ShootBullet", actor)) + return; +#endif + + if (!actor->target) + return; + + dist = P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), actor->target->z - actor->z); + + if (dist > FixedMul(actor->info->painchance*FRACUNIT, actor->scale)) + return; + + A_FaceTarget(actor); + P_SpawnMissile(actor, actor->target, (mobjtype_t)actor->info->raisestate); + + if (actor->info->attacksound) + S_StartSound(actor, actor->info->attacksound); +} + +// Function: A_MinusDigging +// +// Description: Minus digging in the ground. +// +// var1 = unused +// var2 = unused +// +void A_MinusDigging(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_MinusDigging", actor)) + return; +#endif + actor->flags &= ~MF_SPECIAL; + actor->flags &= ~MF_SHOOTABLE; + + if (!actor->target) + { + A_Look(actor); + return; + } + + if (actor->reactiontime) + { + actor->reactiontime--; + return; + } + + // Dirt trail + P_SpawnGhostMobj(actor); + + actor->flags |= MF_NOCLIPTHING; + var1 = 3; + A_Chase(actor); + actor->flags &= ~MF_NOCLIPTHING; + + // Play digging sound + if (!(leveltime & 15)) + S_StartSound(actor, actor->info->activesound); + + // If we're close enough to our target, pop out of the ground + if (P_AproxDistance(actor->target->x-actor->x, actor->target->y-actor->y) < actor->radius + && abs(actor->target->z - actor->z) < 2*actor->height) + P_SetMobjState(actor, actor->info->missilestate); + + // Snap to ground + if (actor->eflags & MFE_VERTICALFLIP) + actor->z = actor->ceilingz - actor->height; + else + actor->z = actor->floorz; +} + +// Function: A_MinusPopup +// +// Description: Minus popping out of the ground. +// +// var1 = unused +// var2 = unused +// +void A_MinusPopup(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_MinusPopup", actor)) + return; +#endif + P_SetObjectMomZ(actor, 10*FRACUNIT, false); + + actor->flags |= MF_SPECIAL; + actor->flags |= MF_SHOOTABLE; + + // Sound for busting out of the ground. + S_StartSound(actor, actor->info->attacksound); +} + +// Function: A_MinusCheck +// +// Description: If the minus hits the floor, dig back into the ground. +// +// var1 = unused +// var2 = unused +// +void A_MinusCheck(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_MinusCheck", actor)) + return; +#endif + if ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) + || ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz)) + { + actor->flags &= ~MF_SPECIAL; + actor->flags &= ~MF_SHOOTABLE; + actor->reactiontime = TICRATE; + P_SetMobjState(actor, actor->info->seestate); + return; + } + + // 'Falling' animation + if (P_MobjFlip(actor)*actor->momz < 0 && actor->state < &states[actor->info->meleestate]) + P_SetMobjState(actor, actor->info->meleestate); +} + +// Function: A_ChickenCheck +// +// Description: Resets the chicken once it hits the floor again. +// +// var1 = unused +// var2 = unused +// +void A_ChickenCheck(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_ChickenCheck", actor)) + return; +#endif + if ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) + || (actor->eflags & MFE_VERTICALFLIP && actor->z + actor->height >= actor->ceilingz)) + { + if (!(actor->momx || actor->momy || actor->momz) + && actor->state > &states[actor->info->seestate]) + { + A_Chase(actor); + P_SetMobjState(actor, actor->info->seestate); + } + + actor->momx >>= 2; + actor->momy >>= 2; + } +} + +// Function: A_JetgThink +// +// Description: Thinker for Jetty-Syn Gunners +// +// var1 = unused +// var2 = unused +// +void A_JetgThink(mobj_t *actor) +{ + sector_t *nextsector; + + fixed_t thefloor; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_JetgThink", actor)) + return; +#endif + + if (actor->z >= actor->waterbottom && actor->watertop > actor->floorz + && actor->z > actor->watertop - FixedMul(256*FRACUNIT, actor->scale)) + thefloor = actor->watertop; + else + thefloor = actor->floorz; + + if (actor->target) + { + if (P_RandomChance(FRACUNIT/8) && !actor->reactiontime) + P_SetMobjState(actor, actor->info->missilestate); + else + A_JetChase (actor); + } + else if (actor->z - FixedMul((32<scale) < thefloor && !(thefloor + FixedMul((32<scale) + + actor->height > actor->ceilingz)) + { + actor->z = thefloor + FixedMul((32<scale); + } + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { + // look for a new target + if (P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + + nextsector = R_PointInSubsector(actor->x + actor->momx, actor->y + actor->momy)->sector; + + // Move downwards or upwards to go through a passageway. + if (nextsector->ceilingheight < actor->z + actor->height) + actor->momz -= FixedMul(5*FRACUNIT, actor->scale); + else if (nextsector->floorheight > actor->z) + actor->momz += FixedMul(5*FRACUNIT, actor->scale); +} + +// Function: A_MouseThink +// +// Description: Thinker for scurrying mice. +// +// var1 = unused +// var2 = unused +// +void A_MouseThink(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_MouseThink", actor)) + return; +#endif + + if (actor->reactiontime) + actor->reactiontime--; + + if (((!(actor->eflags & MFE_VERTICALFLIP) && actor->z == actor->floorz) + || (actor->eflags & MFE_VERTICALFLIP && actor->z + actor->height == actor->ceilingz)) + && !actor->reactiontime) + { + if (twodlevel || actor->flags2 & MF2_TWOD) + { + if (P_RandomChance(FRACUNIT/2)) + actor->angle += ANGLE_180; + } + else if (P_RandomChance(FRACUNIT/2)) + actor->angle += ANGLE_90; + else + actor->angle -= ANGLE_90; + + P_InstaThrust(actor, actor->angle, FixedMul(actor->info->speed, actor->scale)); + actor->reactiontime = TICRATE/5; + } +} + +// Function: A_DetonChase +// +// Description: Chases a Deton after a player. +// +// var1 = unused +// var2 = unused +// +void A_DetonChase(mobj_t *actor) +{ + angle_t exact; + fixed_t xydist, dist; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_DetonChase", actor)) + return; +#endif + + // modify tracer threshold + if (!actor->tracer || actor->tracer->health <= 0) + actor->threshold = 0; + else + actor->threshold = 1; + + if (!actor->tracer || !(actor->tracer->flags & MF_SHOOTABLE)) + { + // look for a new target + if (P_LookForPlayers(actor, true, true, 0)) + return; // got a new target + + actor->momx = actor->momy = actor->momz = 0; + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + + if (multiplayer && !actor->threshold && P_LookForPlayers(actor, true, true, 0)) + return; // got a new target + + // Face movement direction if not doing so + exact = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); + actor->angle = exact; + /*if (exact != actor->angle) + { + if (exact - actor->angle > ANGLE_180) + { + actor->angle -= actor->info->raisestate; + if (exact - actor->angle < ANGLE_180) + actor->angle = exact; + } + else + { + actor->angle += actor->info->raisestate; + if (exact - actor->angle > ANGLE_180) + actor->angle = exact; + } + }*/ + // movedir is up/down angle: how much it has to go up as it goes over to the player + xydist = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y); + exact = R_PointToAngle2(0, 0, xydist, actor->tracer->z - actor->z); + actor->movedir = exact; + /*if (exact != actor->movedir) + { + if (exact - actor->movedir > ANGLE_180) + { + actor->movedir -= actor->info->raisestate; + if (exact - actor->movedir < ANGLE_180) + actor->movedir = exact; + } + else + { + actor->movedir += actor->info->raisestate; + if (exact - actor->movedir > ANGLE_180) + actor->movedir = exact; + } + }*/ + + // check for melee attack + if (actor->tracer) + { + if (P_AproxDistance(actor->tracer->x-actor->x, actor->tracer->y-actor->y) < actor->radius+actor->tracer->radius) + { + if (!((actor->tracer->z > actor->z + actor->height) || (actor->z > actor->tracer->z + actor->tracer->height))) + { + P_ExplodeMissile(actor); + return; + } + } + } + + // chase towards player + if ((dist = P_AproxDistance(xydist, actor->tracer->z-actor->z)) + > FixedMul((actor->info->painchance << FRACBITS), actor->scale)) + { + P_SetTarget(&actor->tracer, NULL); // Too far away + return; + } + + if (actor->reactiontime == 0) + { + actor->reactiontime = actor->info->reactiontime; + return; + } + + if (actor->reactiontime > 1) + { + actor->reactiontime--; + return; + } + + if (actor->reactiontime > 0) + { + actor->reactiontime = -42; + + if (actor->info->seesound) + S_StartScreamSound(actor, actor->info->seesound); + } + + if (actor->reactiontime == -42) + { + fixed_t xyspeed; + + actor->reactiontime = -42; + + exact = actor->movedir>>ANGLETOFINESHIFT; + xyspeed = FixedMul(FixedMul(actor->tracer->player->normalspeed,3*FRACUNIT/4), FINECOSINE(exact)); + actor->momz = FixedMul(FixedMul(actor->tracer->player->normalspeed,3*FRACUNIT/4), FINESINE(exact)); + + exact = actor->angle>>ANGLETOFINESHIFT; + actor->momx = FixedMul(xyspeed, FINECOSINE(exact)); + actor->momy = FixedMul(xyspeed, FINESINE(exact)); + + // Variable re-use + xyspeed = (P_AproxDistance(actor->tracer->x - actor->x, P_AproxDistance(actor->tracer->y - actor->y, actor->tracer->z - actor->z))>>(FRACBITS+6)); + + if (xyspeed < 1) + xyspeed = 1; + + if (leveltime % xyspeed == 0) + S_StartSound(actor, sfx_deton); + } +} + +// Function: A_CapeChase +// +// Description: Set an object's location to its target or tracer. +// +// var1: +// 0 = Use target +// 1 = Use tracer +// upper 16 bits = Z offset +// var2: +// upper 16 bits = forward/backward offset +// lower 16 bits = sideways offset +// +void A_CapeChase(mobj_t *actor) +{ + mobj_t *chaser; + fixed_t foffsetx, foffsety, boffsetx, boffsety; + INT32 locvar1 = var1; + INT32 locvar2 = var2; + angle_t angle; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CapeChase", actor)) + return; +#endif + + CONS_Debug(DBG_GAMELOGIC, "A_CapeChase called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); + + if (locvar1 & 65535) + chaser = actor->tracer; + else + chaser = actor->target; + + if (!chaser || (chaser->health <= 0)) + { + if (chaser) + CONS_Debug(DBG_GAMELOGIC, "Hmm, the guy I'm chasing (object type %d) has no health.. so I'll die too!\n", chaser->type); + + P_RemoveMobj(actor); + return; + } + + angle = (chaser->player ? chaser->player->drawangle : chaser->angle); + + foffsetx = P_ReturnThrustX(chaser, angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale)); + foffsety = P_ReturnThrustY(chaser, angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale)); + + boffsetx = P_ReturnThrustX(chaser, angle-ANGLE_90, FixedMul((locvar2 & 65535)*FRACUNIT, actor->scale)); + boffsety = P_ReturnThrustY(chaser, angle-ANGLE_90, FixedMul((locvar2 & 65535)*FRACUNIT, actor->scale)); + + P_UnsetThingPosition(actor); + actor->x = chaser->x + foffsetx + boffsetx; + actor->y = chaser->y + foffsety + boffsety; + if (chaser->eflags & MFE_VERTICALFLIP) + { + actor->eflags |= MFE_VERTICALFLIP; + actor->flags2 |= MF2_OBJECTFLIP; + actor->z = chaser->z + chaser->height - actor->height - FixedMul((locvar1 >> 16)*FRACUNIT, actor->scale); + } + else + { + actor->eflags &= ~MFE_VERTICALFLIP; + actor->flags2 &= ~MF2_OBJECTFLIP; + actor->z = chaser->z + FixedMul((locvar1 >> 16)*FRACUNIT, actor->scale); + } + actor->angle = angle; + P_SetThingPosition(actor); +} + +// Function: A_RotateSpikeBall +// +// Description: Rotates a spike ball around its target/tracer. +// +// var1: +// 0 = Use target +// 1 = Use tracer +// var2 = unused +// +void A_RotateSpikeBall(mobj_t *actor) +{ + INT32 locvar1 = var1; + const fixed_t radius = FixedMul(12*actor->info->speed, actor->scale); +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RotateSpikeBall", actor)) + return; +#endif + + if (!((!locvar1 && (actor->target)) || (locvar1 && (actor->tracer))))// This should NEVER happen. + { + CONS_Debug(DBG_GAMELOGIC, "A_RotateSpikeBall: Spikeball has no target\n"); + P_RemoveMobj(actor); + return; + } + + if (!actor->info->speed) + { + CONS_Debug(DBG_GAMELOGIC, "A_RotateSpikeBall: Object has no speed.\n"); + return; + } + + actor->angle += FixedAngle(actor->info->speed); + P_UnsetThingPosition(actor); + { + const angle_t fa = actor->angle>>ANGLETOFINESHIFT; + if (!locvar1) + { + actor->x = actor->target->x + FixedMul(FINECOSINE(fa),radius); + actor->y = actor->target->y + FixedMul(FINESINE(fa),radius); + actor->z = actor->target->z + actor->target->height/2; + } + else + { + actor->x = actor->tracer->x + FixedMul(FINECOSINE(fa),radius); + actor->y = actor->tracer->y + FixedMul(FINESINE(fa),radius); + actor->z = actor->tracer->z + actor->tracer->height/2; + } + P_SetThingPosition(actor); + } +} + +// Function: A_UnidusBall +// +// Description: Rotates a spike ball around its target. +// +// var1: +// 0 = Don't throw +// 1 = Throw +// 2 = Throw when target leaves MF2_SKULLFLY. +// var2 = unused +// +void A_UnidusBall(mobj_t *actor) +{ + INT32 locvar1 = var1; + boolean canthrow = false; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_UnidusBall", actor)) + return; +#endif + + actor->angle += ANGLE_11hh; + + if (actor->movecount) + { + if (P_AproxDistance(actor->momx, actor->momy) < FixedMul(actor->info->damage/2, actor->scale)) + P_ExplodeMissile(actor); + return; + } + + if (!actor->target || !actor->target->health) + { + CONS_Debug(DBG_GAMELOGIC, "A_UnidusBall: Removing unthrown spikeball from nonexistant Unidus\n"); + P_RemoveMobj(actor); + return; + } + + P_UnsetThingPosition(actor); + { + const angle_t angle = actor->movedir + FixedAngle(actor->info->speed*(leveltime%360)); + const UINT16 fa = angle>>ANGLETOFINESHIFT; + + actor->x = actor->target->x + FixedMul(FINECOSINE(fa),actor->threshold); + actor->y = actor->target->y + FixedMul( FINESINE(fa),actor->threshold); + actor->z = actor->target->z + actor->target->height/2 - actor->height/2; + + if (locvar1 == 1 && actor->target->target) + { + const angle_t tang = R_PointToAngle2(actor->target->x, actor->target->y, actor->target->target->x, actor->target->target->y); + const angle_t mina = tang-ANGLE_11hh; + canthrow = (angle-mina < FixedAngle(actor->info->speed*3)); + } + } + P_SetThingPosition(actor); + + if (locvar1 == 1 && canthrow) + { + if (P_AproxDistance(actor->target->target->x - actor->target->x, actor->target->target->y - actor->target->y) > FixedMul(MISSILERANGE>>1, actor->scale) + || !P_CheckSight(actor, actor->target->target)) + return; + + actor->movecount = actor->info->damage>>FRACBITS; + actor->flags &= ~(MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING); + P_InstaThrust(actor, R_PointToAngle2(actor->x, actor->y, actor->target->target->x, actor->target->target->y), FixedMul(actor->info->damage, actor->scale)); + } + else if (locvar1 == 2) + { + boolean skull = (actor->target->flags2 & MF2_SKULLFLY) == MF2_SKULLFLY; + if (actor->target->state == &states[actor->target->info->painstate]) + { + P_KillMobj(actor, NULL, NULL, 0); + return; + } + switch(actor->extravalue2) + { + case 0: // at least one frame where not dashing + if (!skull) ++actor->extravalue2; + else break; + /* FALLTHRU */ + case 1: // at least one frame where ARE dashing + if (skull) ++actor->extravalue2; + else break; + /* FALLTHRU */ + case 2: // not dashing again? + if (skull) break; + // launch. + { + mobj_t *target = actor->target; + if (actor->target->target) + target = actor->target->target; + actor->movecount = actor->info->damage>>FRACBITS; + actor->flags &= ~(MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING); + P_InstaThrust(actor, R_PointToAngle2(actor->x, actor->y, target->x, target->y), FixedMul(actor->info->damage, actor->scale)); + } + default: // from our compiler appeasement program (CAP). + break; + } + } +} + +// Function: A_RockSpawn +// +// Spawns rocks at a specified interval +// +// var1 = unused +// var2 = unused +void A_RockSpawn(mobj_t *actor) +{ + mobj_t *mo; + mobjtype_t type; + INT32 i = P_FindSpecialLineFromTag(12, (INT16)actor->threshold, -1); + line_t *line; + fixed_t dist; + fixed_t randomoomph; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RockSpawn", actor)) + return; +#endif + + if (i == -1) + { + CONS_Debug(DBG_GAMELOGIC, "A_RockSpawn: Unable to find parameter line 12 (tag %d)!\n", actor->threshold); + return; + } + + line = &lines[i]; + + if (!(sides[line->sidenum[0]].textureoffset >> FRACBITS)) + { + CONS_Debug(DBG_GAMELOGIC, "A_RockSpawn: No X-offset detected! (tag %d)!\n", actor->threshold); + return; + } + + dist = P_AproxDistance(line->dx, line->dy)/16; + + if (dist < 1) + dist = 1; + + type = MT_ROCKCRUMBLE1 + (sides[line->sidenum[0]].rowoffset >> FRACBITS); + + if (line->flags & ML_NOCLIMB) + randomoomph = P_RandomByte() * (FRACUNIT/32); + else + randomoomph = 0; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FALLINGROCK); + P_SetMobjState(mo, mobjinfo[type].spawnstate); + mo->angle = R_PointToAngle2(line->v2->x, line->v2->y, line->v1->x, line->v1->y); + + P_InstaThrust(mo, mo->angle, dist + randomoomph); + mo->momz = dist + randomoomph; + + var1 = sides[line->sidenum[0]].textureoffset >> FRACBITS; + A_SetTics(actor); +} + +// +// Function: A_SlingAppear +// +// Appears a sling. +// +// var1 = unused +// var2 = unused +// +void A_SlingAppear(mobj_t *actor) +{ + UINT8 mlength = 4; + mobj_t *spawnee, *hprev; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SlingAppear", actor)) + return; +#endif + + P_UnsetThingPosition(actor); + actor->flags &= ~(MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT); + P_SetThingPosition(actor); + actor->lastlook = 128; + actor->movecount = actor->lastlook; + actor->threshold = 0; + actor->movefactor = actor->threshold; + actor->friction = 128; + + hprev = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMALLGRABCHAIN); + P_SetTarget(&hprev->tracer, actor); + P_SetTarget(&hprev->hprev, actor); + P_SetTarget(&actor->hnext, hprev); + hprev->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT; + hprev->movecount = mlength; + + mlength--; + + while (mlength > 0) + { + spawnee = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMALLMACECHAIN); + P_SetTarget(&spawnee->tracer, actor); + P_SetTarget(&spawnee->hprev, hprev); + P_SetTarget(&hprev->hnext, spawnee); + hprev = spawnee; + + spawnee->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT; + spawnee->movecount = mlength; + + mlength--; + } +} + +// Function: A_SetFuse +// +// Description: Sets the actor's fuse timer if not set already. May also change state when fuse reaches the last tic, otherwise by default the actor will die or disappear. (Replaces A_SnowBall) +// +// var1 = fuse timer duration (in tics). +// var2: +// lower 16 bits = if > 0, state to change to when fuse = 1 +// upper 16 bits: 0 = (default) don't set fuse unless 0, 1 = force change, 2 = force no change +// +void A_SetFuse(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetFuse", actor)) + return; +#endif + + if ((!actor->fuse || (locvar2 >> 16)) && (locvar2 >> 16) != 2) // set the actor's fuse value + actor->fuse = locvar1; + + if (actor->fuse == 1 && (locvar2 & 65535)) // change state on the very last tic (fuse is handled before actions in P_MobjThinker) + { + actor->fuse = 0; // don't die/disappear the next tic! + P_SetMobjState(actor, locvar2 & 65535); + } +} + +// Function: A_CrawlaCommanderThink +// +// Description: Thinker for Crawla Commander. +// +// var1 = shoot bullets? +// var2 = "pogo mode" speed +// +void A_CrawlaCommanderThink(mobj_t *actor) +{ + fixed_t dist; + sector_t *nextsector; + fixed_t thefloor; + INT32 locvar1 = var1; + INT32 locvar2 = var2; + boolean hovermode = (actor->health > 1 || actor->fuse); +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CrawlaCommanderThink", actor)) + return; +#endif + + if (actor->z >= actor->waterbottom && actor->watertop > actor->floorz + && actor->z > actor->watertop - FixedMul(256*FRACUNIT, actor->scale)) + thefloor = actor->watertop; + else + thefloor = actor->floorz; + + if (!actor->fuse && actor->flags2 & MF2_FRET) + { + if (actor->info->painsound) + S_StartSound(actor, actor->info->painsound); + + actor->fuse = TICRATE/2; + actor->momz = 0; + + P_InstaThrust(actor, actor->angle-ANGLE_180, FixedMul(5*FRACUNIT, actor->scale)); + } + + if (actor->reactiontime > 0) + actor->reactiontime--; + + if (actor->fuse < 2) + { + actor->fuse = 0; + actor->flags2 &= ~MF2_FRET; + } + + // Hover mode + if (hovermode) + { + if (actor->z < thefloor + FixedMul(16*FRACUNIT, actor->scale)) + actor->momz += FixedMul(FRACUNIT, actor->scale); + else if (actor->z < thefloor + FixedMul(32*FRACUNIT, actor->scale)) + actor->momz += FixedMul(FRACUNIT/2, actor->scale); + else + actor->momz += FixedMul(16, actor->scale); + } + + if (!actor->target) + { + // look for a new target + if (P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + if (actor->state != &states[actor->info->spawnstate]) + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + + dist = P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y); + + if (actor->target->player && (!hovermode || actor->reactiontime <= 2*TICRATE)) + { + if (dist < FixedMul(64<<(FRACBITS+(hovermode ? 1 : 0)), actor->scale) + && ((actor->target->player->pflags & PF_JUMPED) || (actor->target->player->pflags & PF_SPINNING))) + { + // Auugh! She's trying to kill you! Strafe! STRAAAAFFEEE!! + P_InstaThrust(actor, actor->angle - ANGLE_180, FixedMul(20*FRACUNIT, actor->scale)); + return; + } + } + + if (locvar1) + { + if (actor->health < 2 && P_RandomChance(FRACUNIT/128)) + P_SpawnMissile(actor, actor->target, locvar1); + } + + // Face the player + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + + if (actor->threshold && dist > FixedMul(256*FRACUNIT, actor->scale)) + actor->momx = actor->momy = 0; + + if (actor->reactiontime && actor->reactiontime <= 2*TICRATE && dist > actor->target->radius - FixedMul(FRACUNIT, actor->scale)) + { + actor->threshold = 0; + + // Roam around, somewhat in the player's direction. + actor->angle += (P_RandomByte()<<10); + actor->angle -= (P_RandomByte()<<10); + + if (hovermode) + { + fixed_t mom; + P_Thrust(actor, actor->angle, 2*actor->scale); + mom = P_AproxDistance(actor->momx, actor->momy); + if (mom > 20*actor->scale) + { + mom += 20*actor->scale; + mom >>= 1; + P_InstaThrust(actor, R_PointToAngle2(0, 0, actor->momx, actor->momy), mom); + } + } + } + else if (!actor->reactiontime) + { + if (hovermode && !(actor->flags2 & MF2_FRET)) // Hover Mode + { + if (dist < FixedMul(512*FRACUNIT, actor->scale)) + { + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + P_InstaThrust(actor, actor->angle, FixedMul(40*FRACUNIT, actor->scale)); + actor->threshold = 1; + if (actor->info->attacksound) + S_StartSound(actor, actor->info->attacksound); + } + } + actor->reactiontime = 3*TICRATE + (P_RandomByte()>>2); + } + + if (actor->health == 1) + P_Thrust(actor, actor->angle, 1); + + // Pogo Mode + if (!hovermode && actor->z <= actor->floorz) + { + if (actor->info->activesound) + S_StartSound(actor, actor->info->activesound); + + if (dist < FixedMul(256*FRACUNIT, actor->scale)) + { + actor->momz = FixedMul(locvar2, actor->scale); + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + P_InstaThrust(actor, actor->angle, FixedMul(locvar2/8, actor->scale)); + // pogo on player + } + else + { + UINT8 prandom = P_RandomByte(); + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom); + P_InstaThrust(actor, actor->angle, FixedDiv(FixedMul(locvar2, actor->scale), 3*FRACUNIT/2)); + actor->momz = FixedMul(locvar2, actor->scale); // Bounce up in air + } + } + + nextsector = R_PointInSubsector(actor->x + actor->momx, actor->y + actor->momy)->sector; + + // Move downwards or upwards to go through a passageway. + if (nextsector->floorheight > actor->z && nextsector->floorheight - actor->z < FixedMul(128*FRACUNIT, actor->scale)) + actor->momz += (nextsector->floorheight - actor->z) / 4; +} + +// Function: A_RingExplode +// +// Description: An explosion ring exploding +// +// var1 = unused +// var2 = unused +// +void A_RingExplode(mobj_t *actor) +{ + mobj_t *mo2; + thinker_t *th; + angle_t d; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RingExplode", actor)) + return; +#endif + + for (d = 0; d < 16; d++) + P_SpawnParaloop(actor->x, actor->y, actor->z + actor->height, FixedMul(actor->info->painchance, actor->scale), 16, MT_NIGHTSPARKLE, S_NULL, d*(ANGLE_22h), true); + + S_StartSound(actor, sfx_prloop); + + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo2 = (mobj_t *)th; + + if (mo2 == actor) // Don't explode yourself! Endless loop! + continue; + + if (P_AproxDistance(P_AproxDistance(mo2->x - actor->x, mo2->y - actor->y), mo2->z - actor->z) > FixedMul(actor->info->painchance, actor->scale)) + continue; + + if (mo2->flags & MF_SHOOTABLE) + { + actor->flags2 |= MF2_DEBRIS; + P_DamageMobj(mo2, actor, actor->target, 1, 0); + continue; + } + } + return; +} + +// Function: A_OldRingExplode +// +// Description: An explosion ring exploding, 1.09.4 style +// +// var1 = object # to explode as debris +// var2 = unused +// +void A_OldRingExplode(mobj_t *actor) { + UINT8 i; + mobj_t *mo; + const fixed_t ns = FixedMul(20 * FRACUNIT, actor->scale); + INT32 locvar1 = var1; + //INT32 locvar2 = var2; + boolean changecolor = (actor->target && actor->target->player); +#ifdef HAVE_BLUA + if (LUA_CallAction("A_OldRingExplode", actor)) + return; +#endif + + for (i = 0; i < 32; i++) + { + const angle_t fa = (i*FINEANGLES/16) & FINEMASK; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, locvar1); + P_SetTarget(&mo->target, actor->target); // Transfer target so player gets the points + + mo->momx = FixedMul(FINECOSINE(fa),ns); + mo->momy = FixedMul(FINESINE(fa),ns); + + if (i > 15) + { + if (i & 1) + mo->momz = ns; + else + mo->momz = -ns; + } + + mo->flags2 |= MF2_DEBRIS; + mo->fuse = TICRATE/5; + + if (changecolor) + { + if (gametype != GT_CTF) + mo->color = actor->target->color; //copy color + else if (actor->target->player->ctfteam == 2) + mo->color = skincolor_bluering; + } + } + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, locvar1); + + P_SetTarget(&mo->target, actor->target); + mo->momz = ns; + mo->flags2 |= MF2_DEBRIS; + mo->fuse = TICRATE/5; + + if (changecolor) + { + if (gametype != GT_CTF) + mo->color = actor->target->color; //copy color + else if (actor->target->player->ctfteam == 2) + mo->color = skincolor_bluering; + } + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, locvar1); + + P_SetTarget(&mo->target, actor->target); + mo->momz = -ns; + mo->flags2 |= MF2_DEBRIS; + mo->fuse = TICRATE/5; + + if (changecolor) + { + if (gametype != GT_CTF) + mo->color = actor->target->color; //copy color + else if (actor->target->player->ctfteam == 2) + mo->color = skincolor_bluering; + } +} + +// Function: A_MixUp +// +// Description: Mix up all of the player positions. +// +// var1 = unused +// var2 = unused +// +void A_MixUp(mobj_t *actor) +{ + boolean teleported[MAXPLAYERS]; + INT32 i, numplayers = 0, prandom = 0; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_MixUp", actor)) + return; +#else + (void)actor; +#endif + + if (!multiplayer) + return; + + // No mix-up monitors in hide and seek or time only race. + // The random factor is okay for other game modes, but in these, it is cripplingly unfair. + if (gametype == GT_HIDEANDSEEK || gametype == GT_RACE) + { + S_StartSound(actor, sfx_lose); + return; + } + + numplayers = 0; + memset(teleported, 0, sizeof (teleported)); + + // Count the number of players in the game + // and grab their xyz coords + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE + && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE) + { + if ((netgame || multiplayer) && players[i].spectator) // Ignore spectators + continue; + + numplayers++; + } + + if (numplayers <= 1) // Not enough players to mix up. + { + S_StartSound(actor, sfx_lose); + return; + } + else if (numplayers == 2) // Special case -- simple swap + { + fixed_t x, y, z; + angle_t angle; + INT32 one = -1, two = 0; // default value 0 to make the compiler shut up + + // Zoom tube stuff + mobj_t *tempthing = NULL; //tracer + UINT16 carry1,carry2; //carry + INT32 transspeed; //player speed + + // Starpost stuff + INT16 starpostx, starposty, starpostz; + INT32 starpostnum; + tic_t starposttime; + angle_t starpostangle; + + INT32 mflags2; + + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE + && !players[i].exiting && !players[i].powers[pw_super]) + { + if ((netgame || multiplayer) && players[i].spectator) // Ignore spectators + continue; + + if (one == -1) + one = i; + else + { + two = i; + break; + } + } + + //get this done first! + tempthing = players[one].mo->tracer; + P_SetTarget(&players[one].mo->tracer, players[two].mo->tracer); + P_SetTarget(&players[two].mo->tracer, tempthing); + + //zoom tubes use player->speed to determine direction and speed + transspeed = players[one].speed; + players[one].speed = players[two].speed; + players[two].speed = transspeed; + + //set flags variables now but DON'T set them. + carry1 = (players[one].powers[pw_carry] == CR_PLAYER ? CR_NONE : players[one].powers[pw_carry]); + carry2 = (players[two].powers[pw_carry] == CR_PLAYER ? CR_NONE : players[two].powers[pw_carry]); + + x = players[one].mo->x; + y = players[one].mo->y; + z = players[one].mo->z; + angle = players[one].mo->angle; + + starpostx = players[one].starpostx; + starposty = players[one].starposty; + starpostz = players[one].starpostz; + starpostangle = players[one].starpostangle; + starpostnum = players[one].starpostnum; + starposttime = players[one].starposttime; + + mflags2 = players[one].mo->flags2; + + P_MixUp(players[one].mo, players[two].mo->x, players[two].mo->y, players[two].mo->z, players[two].mo->angle, + players[two].starpostx, players[two].starposty, players[two].starpostz, + players[two].starpostnum, players[two].starposttime, players[two].starpostangle, + players[two].mo->flags2); + + P_MixUp(players[two].mo, x, y, z, angle, starpostx, starposty, starpostz, + starpostnum, starposttime, starpostangle, + mflags2); + + //carry set after mixup. Stupid P_ResetPlayer() takes away some of the stuff we look for... + //but not all of it! So we need to make sure they aren't set wrong or anything. + players[one].powers[pw_carry] = carry2; + players[two].powers[pw_carry] = carry1; + + teleported[one] = true; + teleported[two] = true; + } + else + { + fixed_t position[MAXPLAYERS][3]; + angle_t anglepos[MAXPLAYERS]; + INT32 pindex[MAXPLAYERS], counter = 0, teleportfrom = 0; + + // Zoom tube stuff + mobj_t *transtracer[MAXPLAYERS]; //tracer + //pflags_t transflag[MAXPLAYERS]; //cyan pink white pink cyan + UINT16 transcarry[MAXPLAYERS]; //player carry + INT32 transspeed[MAXPLAYERS]; //player speed + + // Star post stuff + INT16 spposition[MAXPLAYERS][3]; + INT32 starpostnum[MAXPLAYERS]; + tic_t starposttime[MAXPLAYERS]; + angle_t starpostangle[MAXPLAYERS]; + + INT32 flags2[MAXPLAYERS]; + + for (i = 0; i < MAXPLAYERS; i++) + { + position[i][0] = position[i][1] = position[i][2] = anglepos[i] = pindex[i] = -1; + teleported[i] = false; + } + + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && players[i].playerstate == PST_LIVE + && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE) + { + if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators + continue; + + position[counter][0] = players[i].mo->x; + position[counter][1] = players[i].mo->y; + position[counter][2] = players[i].mo->z; + pindex[counter] = i; + anglepos[counter] = players[i].mo->angle; + players[i].mo->momx = players[i].mo->momy = players[i].mo->momz = + players[i].rmomx = players[i].rmomy = 1; + players[i].cmomx = players[i].cmomy = 0; + + transcarry[counter] = (players[i].powers[pw_carry] == CR_PLAYER ? CR_NONE : players[i].powers[pw_carry]); + transspeed[counter] = players[i].speed; + transtracer[counter] = players[i].mo->tracer; + + spposition[counter][0] = players[i].starpostx; + spposition[counter][1] = players[i].starposty; + spposition[counter][2] = players[i].starpostz; + starpostnum[counter] = players[i].starpostnum; + starposttime[counter] = players[i].starposttime; + starpostangle[counter] = players[i].starpostangle; + + flags2[counter] = players[i].mo->flags2; + + counter++; + } + } + + counter = 0; + + // Mix them up! + for (;;) + { + if (counter > 255) // fail-safe to avoid endless loop + break; + prandom = P_RandomByte(); + prandom %= numplayers; // I love modular arithmetic, don't you? + if (prandom) // Make sure it's not a useless mix + break; + counter++; + } + + counter = 0; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && players[i].playerstate == PST_LIVE + && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE) + { + if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators + continue; + + teleportfrom = (counter + prandom) % numplayers; + + //speed and tracer come before... + players[i].speed = transspeed[teleportfrom]; + P_SetTarget(&players[i].mo->tracer, transtracer[teleportfrom]); + + P_MixUp(players[i].mo, position[teleportfrom][0], position[teleportfrom][1], position[teleportfrom][2], anglepos[teleportfrom], + spposition[teleportfrom][0], spposition[teleportfrom][1], spposition[teleportfrom][2], + starpostnum[teleportfrom], starposttime[teleportfrom], starpostangle[teleportfrom], + flags2[teleportfrom]); + + //...carry after. same reasoning. + players[i].powers[pw_carry] = transcarry[teleportfrom]; + + teleported[i] = true; + counter++; + } + } + } + + for (i = 0; i < MAXPLAYERS; i++) + { + if (teleported[i]) + { + if (playeringame[i] && players[i].playerstate == PST_LIVE + && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE) + { + if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators + continue; + + P_SetThingPosition(players[i].mo); + +#ifdef ESLOPE + players[i].mo->floorz = P_GetFloorZ(players[i].mo, players[i].mo->subsector->sector, players[i].mo->x, players[i].mo->y, NULL); + players[i].mo->ceilingz = P_GetCeilingZ(players[i].mo, players[i].mo->subsector->sector, players[i].mo->x, players[i].mo->y, NULL); +#else + players[i].mo->floorz = players[i].mo->subsector->sector->floorheight; + players[i].mo->ceilingz = players[i].mo->subsector->sector->ceilingheight; +#endif + + P_CheckPosition(players[i].mo, players[i].mo->x, players[i].mo->y); + } + } + } + + // Play the 'bowrwoosh!' sound + S_StartSound(NULL, sfx_mixup); +} + +// Function: A_RecyclePowers +// +// Description: Take all player's powers, and swap 'em. +// +// var1 = unused +// var2 = unused +// +void A_RecyclePowers(mobj_t *actor) +{ + INT32 i, j, k, numplayers = 0; + +#ifdef WEIGHTEDRECYCLER + UINT8 beneficiary = 255; +#endif + UINT8 playerslist[MAXPLAYERS]; + UINT8 postscramble[MAXPLAYERS]; + + UINT16 powers[MAXPLAYERS][NUMPOWERS]; + INT32 weapons[MAXPLAYERS]; + INT32 weaponheld[MAXPLAYERS]; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RecyclePowers", actor)) + return; +#endif + +#if !defined(WEIGHTEDRECYCLER) && !defined(HAVE_BLUA) + // actor is used in all scenarios but this one, funny enough + (void)actor; +#endif + + if (!multiplayer) + { + S_StartSound(actor, sfx_lose); + return; + } + + numplayers = 0; + + // Count the number of players in the game + for (i = 0, j = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE + && !players[i].exiting && !((netgame || multiplayer) && players[i].spectator)) + { +#ifndef WEIGHTEDRECYCLER + if (players[i].powers[pw_super]) + continue; // Ignore super players +#endif + + numplayers++; + postscramble[j] = playerslist[j] = (UINT8)i; + +#ifdef WEIGHTEDRECYCLER + // The guy who started the recycle gets the best result + if (actor && actor->target && actor->target->player && &players[i] == actor->target->player) + beneficiary = (UINT8)i; +#endif + + // Save powers + for (k = 0; k < NUMPOWERS; k++) + powers[i][k] = players[i].powers[k]; + //1.1: ring weapons too + weapons[i] = players[i].ringweapons; + weaponheld[i] = players[i].currentweapon; + + j++; + } + } + + if (numplayers <= 1) + { + S_StartSound(actor, sfx_lose); + return; //nobody to touch! + } + + //shuffle the post scramble list, whee! + // hardcoded 0-1 to 1-0 for two players + if (numplayers == 2) + { + postscramble[0] = playerslist[1]; + postscramble[1] = playerslist[0]; + } + else + for (j = 0; j < numplayers; j++) + { + UINT8 tempint; + + i = j + ((P_RandomByte() + leveltime) % (numplayers - j)); + tempint = postscramble[j]; + postscramble[j] = postscramble[i]; + postscramble[i] = tempint; + } + +#ifdef WEIGHTEDRECYCLER + //the joys of qsort... + if (beneficiary != 255) { + qsort(playerslist, numplayers, sizeof(UINT8), P_RecycleCompare); + + // now, make sure the benificiary is in the best slot + // swap out whatever poor sap was going to get the best items + for (i = 0; i < numplayers; i++) + { + if (postscramble[i] == beneficiary) + { + postscramble[i] = postscramble[0]; + postscramble[0] = beneficiary; + break; + } + } + } +#endif + + // now assign! + for (i = 0; i < numplayers; i++) + { + UINT8 send_pl = playerslist[i]; + UINT8 recv_pl = postscramble[i]; + + // debugF + CONS_Debug(DBG_GAMELOGIC, "sending player %hu's items to %hu\n", (UINT16)send_pl, (UINT16)recv_pl); + + for (j = 0; j < NUMPOWERS; j++) + { + if (j == pw_flashing || j == pw_underwater || j == pw_spacetime || j == pw_carry + || j == pw_tailsfly || j == pw_extralife || j == pw_nocontrol || j == pw_super) + continue; + players[recv_pl].powers[j] = powers[send_pl][j]; + } + + //1.1: weapon rings too + players[recv_pl].ringweapons = weapons[send_pl]; + players[recv_pl].currentweapon = weaponheld[send_pl]; + + P_SpawnShieldOrb(&players[recv_pl]); + if (P_IsLocalPlayer(&players[recv_pl])) + P_RestoreMusic(&players[recv_pl]); + P_FlashPal(&players[recv_pl], PAL_RECYCLE, 10); + } + + S_StartSound(NULL, sfx_gravch); //heh, the sound effect I used is already in +} + +// Function: A_Boss1Chase +// +// Description: Like A_Chase, but for Boss 1. +// +// var1 = unused +// var2 = unused +// +void A_Boss1Chase(mobj_t *actor) +{ + INT32 delta; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss1Chase", actor)) + return; +#endif + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { + // look for a new target + if (P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + P_SetMobjStateNF(actor, actor->info->spawnstate); + return; + } + + if (actor->reactiontime) + actor->reactiontime--; + + // turn towards movement direction if not there yet + if (actor->movedir < NUMDIRS) + { + actor->angle &= (7<<29); + delta = actor->angle - (actor->movedir << 29); + + if (delta > 0) + actor->angle -= ANGLE_45; + else if (delta < 0) + actor->angle += ANGLE_45; + } + + // do not attack twice in a row + if (actor->flags2 & MF2_JUSTATTACKED) + { + actor->flags2 &= ~MF2_JUSTATTACKED; + P_NewChaseDir(actor); + return; + } + + if (actor->movecount) + goto nomissile; + + if (!P_CheckMissileRange(actor)) + goto nomissile; + + if (actor->reactiontime <= 0) + { + if (actor->health > actor->info->damage) + { + if (P_RandomChance(FRACUNIT/2)) + P_SetMobjState(actor, actor->info->missilestate); + else + P_SetMobjState(actor, actor->info->meleestate); + } + else + { + P_LinedefExecute(LE_PINCHPHASE, actor, NULL); + P_SetMobjState(actor, actor->info->raisestate); + } + + actor->flags2 |= MF2_JUSTATTACKED; + actor->reactiontime = actor->info->reactiontime; + return; + } + + // ? +nomissile: + // possibly choose another target + if (multiplayer && P_RandomChance(FRACUNIT/128)) + { + if (P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + } + + if (actor->flags & MF_FLOAT && !(actor->flags2 & MF2_SKULLFLY)) + { // Float up/down to your target's position. Stay above them, but not out of jump range. + fixed_t target_min = actor->target->floorz+FixedMul(64*FRACUNIT, actor->scale); + if (target_min < actor->target->z - actor->height) + target_min = actor->target->z - actor->height; + if (target_min < actor->floorz+FixedMul(33*FRACUNIT, actor->scale)) + target_min = actor->floorz+FixedMul(33*FRACUNIT, actor->scale); + if (actor->z > target_min+FixedMul(16*FRACUNIT, actor->scale)) + actor->momz = FixedMul((-actor->info->speed<<(FRACBITS-1)), actor->scale); + else if (actor->z < target_min) + actor->momz = FixedMul(actor->info->speed<<(FRACBITS-1), actor->scale); + else + actor->momz = FixedMul(actor->momz,7*FRACUNIT/8); + } + + // chase towards player + if (P_AproxDistance(actor->target->x-actor->x, actor->target->y-actor->y) > actor->radius+actor->target->radius) + { + if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) + P_NewChaseDir(actor); + } + // too close, don't want to chase. + else if (--actor->movecount < 0) + { + // A mini-A_FaceTarget based on P_NewChaseDir. + // Yes, it really is this simple when you get down to it. + fixed_t deltax, deltay; + + deltax = actor->target->x - actor->x; + deltay = actor->target->y - actor->y; + + actor->movedir = diags[((deltay < 0)<<1) + (deltax > 0)]; + actor->movecount = P_RandomByte() & 15; + } +} + +// Function: A_Boss2Chase +// +// Description: Really doesn't 'chase', but rather goes in a circle. +// +// var1 = unused +// var2 = unused +// +void A_Boss2Chase(mobj_t *actor) +{ + fixed_t radius; + boolean reverse = false; + INT32 speedvar; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss2Chase", actor)) + return; +#endif + + if (actor->health <= 0) + return; + + // Startup randomness + if (actor->reactiontime <= -666) + actor->reactiontime = 2*TICRATE + P_RandomByte(); + + // When reactiontime hits zero, he will go the other way + if (--actor->reactiontime <= 0) + { + reverse = true; + actor->reactiontime = 2*TICRATE + P_RandomByte(); + } + + P_SetTarget(&actor->target, P_GetClosestAxis(actor)); + + if (!actor->target) // This should NEVER happen. + { + CONS_Debug(DBG_GAMELOGIC, "Boss2 has no target!\n"); + A_BossDeath(actor); + return; + } + + radius = actor->target->radius; + + if (reverse) + { + actor->watertop = -actor->watertop; + actor->extravalue1 = 18; + if (actor->flags2 & MF2_AMBUSH) + actor->extravalue1 -= (actor->info->spawnhealth - actor->health)*2; + actor->extravalue2 = actor->extravalue1; + } + + // Turnaround + if (actor->extravalue1 > 0) + { + --actor->extravalue1; + + // Set base angle + { + const angle_t fa = (actor->target->angle + FixedAngle(actor->watertop))>>ANGLETOFINESHIFT; + const fixed_t fc = FixedMul(FINECOSINE(fa),radius); + const fixed_t fs = FixedMul(FINESINE(fa),radius); + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x + fc, actor->target->y + fs); + } + + // Now turn you around! + // Note that the start position is the final position, we move it back around + // to intermediary positions... + actor->angle -= FixedAngle(FixedMul(FixedDiv(180<extravalue2<extravalue1<flags2 & MF2_AMBUSH) + speedvar = actor->health; + else + speedvar = actor->info->spawnhealth; + + actor->target->angle += // Don't use FixedAngleC! + FixedAngle(FixedDiv(FixedMul(actor->watertop, (actor->info->spawnhealth*(FRACUNIT/4)*3)), speedvar*FRACUNIT)); + + P_UnsetThingPosition(actor); + { + const angle_t fa = actor->target->angle>>ANGLETOFINESHIFT; + const fixed_t fc = FixedMul(FINECOSINE(fa),radius); + const fixed_t fs = FixedMul(FINESINE(fa),radius); + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x + fc, actor->target->y + fs); + actor->x = actor->target->x + fc; + actor->y = actor->target->y + fs; + } + P_SetThingPosition(actor); + + // Spray goo once every second + if (leveltime % (speedvar*15/10)-1 == 0) + { + const fixed_t ns = FixedMul(3 * FRACUNIT, actor->scale); + mobj_t *goop; + fixed_t fz = actor->z+actor->height+FixedMul(24*FRACUNIT, actor->scale); + angle_t fa; + // actor->movedir is used to determine the last + // direction goo was sprayed in. There are 8 possible + // directions to spray. (45-degree increments) + + actor->movedir++; + actor->movedir %= NUMDIRS; + fa = (actor->movedir*FINEANGLES/8) & FINEMASK; + + goop = P_SpawnMobj(actor->x, actor->y, fz, actor->info->painchance); + goop->momx = FixedMul(FINECOSINE(fa),ns); + goop->momy = FixedMul(FINESINE(fa),ns); + goop->momz = FixedMul(4*FRACUNIT, actor->scale); + goop->fuse = 10*TICRATE; + + if (actor->info->attacksound) + S_StartAttackSound(actor, actor->info->attacksound); + + if (P_RandomChance(FRACUNIT/2)) + { + goop->momx *= 2; + goop->momy *= 2; + } + else if (P_RandomChance(129*FRACUNIT/256)) + { + goop->momx *= 3; + goop->momy *= 3; + } + + actor->flags2 |= MF2_JUSTATTACKED; + } + } +} + +// Function: A_Boss2Pogo +// +// Description: Pogo part of Boss 2 AI. +// +// var1 = unused +// var2 = unused +// +void A_Boss2Pogo(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss2Pogo", actor)) + return; +#endif + if (actor->z <= actor->floorz + FixedMul(8*FRACUNIT, actor->scale) && actor->momz <= 0) + { + if (actor->state != &states[actor->info->raisestate]) + P_SetMobjState(actor, actor->info->raisestate); + // Pogo Mode + } + else if (actor->momz < 0 && actor->reactiontime) + { + const fixed_t ns = FixedMul(3 * FRACUNIT, actor->scale); + mobj_t *goop; + fixed_t fz = actor->z+actor->height+FixedMul(24*FRACUNIT, actor->scale); + angle_t fa; + INT32 i; + // spray in all 8 directions! + for (i = 0; i < 8; i++) + { + actor->movedir++; + actor->movedir %= NUMDIRS; + fa = (actor->movedir*FINEANGLES/8) & FINEMASK; + + goop = P_SpawnMobj(actor->x, actor->y, fz, actor->info->painchance); + goop->momx = FixedMul(FINECOSINE(fa),ns); + goop->momy = FixedMul(FINESINE(fa),ns); + goop->momz = FixedMul(4*FRACUNIT, actor->scale); + + goop->fuse = 10*TICRATE; + } + actor->reactiontime = 0; // we already shot goop, so don't do it again! + if (actor->info->attacksound) + S_StartAttackSound(actor, actor->info->attacksound); + actor->flags2 |= MF2_JUSTATTACKED; + } +} + +// Function: A_Boss2TakeDamage +// +// Description: Special function for Boss 2 so you can't just sit and destroy him. +// +// var1 = Invincibility duration +// var2 = unused +// +void A_Boss2TakeDamage(mobj_t *actor) +{ + INT32 locvar1 = var1; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss2TakeDamage", actor)) + return; +#endif + A_Pain(actor); + actor->reactiontime = 1; // turn around + if (locvar1 == 0) // old A_Invincibilerize behavior + actor->movecount = TICRATE; + else + actor->movecount = locvar1; // become flashing invulnerable for this long. +} + +// Function: A_Boss7Chase +// +// Description: Like A_Chase, but for Black Eggman +// +// var1 = unused +// var2 = unused +// +void A_Boss7Chase(mobj_t *actor) +{ + INT32 delta; + INT32 i; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss7Chase", actor)) + return; +#endif + + if (actor->z != actor->floorz) + return; + + // Self-adjust if stuck on the edge + if (actor->tracer) + { + if (P_AproxDistance(actor->x - actor->tracer->x, actor->y - actor->tracer->y) > 128*FRACUNIT - actor->radius) + P_InstaThrust(actor, R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y), FRACUNIT); + } + + if (actor->flags2 & MF2_FRET) + { + P_SetMobjState(actor, S_BLACKEGG_DESTROYPLAT1); + S_StartSound(0, sfx_s3k53); + actor->flags2 &= ~MF2_FRET; + return; + } + + // turn towards movement direction if not there yet + if (actor->movedir < NUMDIRS) + { + actor->angle &= (7<<29); + delta = actor->angle - (actor->movedir << 29); + + if (delta > 0) + actor->angle -= ANGLE_45; + else if (delta < 0) + actor->angle += ANGLE_45; + } + + // Is a player on top of us? + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + + if (!players[i].mo) + continue; + + if (players[i].mo->health <= 0) + continue; + + if (P_AproxDistance(players[i].mo->x - actor->x, players[i].mo->y - actor->y) > actor->radius) + continue; + + if (players[i].mo->z > actor->z + actor->height - 2*FRACUNIT + && players[i].mo->z < actor->z + actor->height + 32*FRACUNIT) + { + // Punch him! + P_SetMobjState(actor, actor->info->meleestate); + S_StartSound(0, sfx_begrnd); // warning sound + return; + } + } + + if (actor->health <= actor->info->damage + && actor->target + && actor->target->player + && (actor->target->player->powers[pw_carry] == CR_GENERIC)) + { + A_FaceTarget(actor); + P_SetMobjState(actor, S_BLACKEGG_SHOOT1); + actor->movecount = TICRATE + P_RandomByte()/2; + return; + } + + if (actor->reactiontime) + actor->reactiontime--; + + if (actor->reactiontime <= 0 && actor->z == actor->floorz) + { + // Here, we'll call P_RandomByte() and decide what kind of attack to do + switch(actor->threshold) + { + case 0: // Lob cannon balls + if (actor->z < 1056*FRACUNIT) + { + A_FaceTarget(actor); + P_SetMobjState(actor, actor->info->xdeathstate); + actor->movecount = 7*TICRATE + P_RandomByte(); + break; + } + actor->threshold++; + /* FALLTHRU */ + case 1: // Chaingun Goop + A_FaceTarget(actor); + P_SetMobjState(actor, S_BLACKEGG_SHOOT1); + + if (actor->health > actor->info->damage) + actor->movecount = TICRATE + P_RandomByte()/3; + else + actor->movecount = TICRATE + P_RandomByte()/2; + break; + case 2: // Homing Missile + A_FaceTarget(actor); + P_SetMobjState(actor, actor->info->missilestate); + S_StartSound(0, sfx_beflap); + break; + } + + actor->threshold++; + actor->threshold %= 3; + return; + } + + // possibly choose another target + if (multiplayer && (actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) + && P_BossTargetPlayer(actor, false)) + return; // got a new target + + if (leveltime & 1) + { + // chase towards player + if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) + P_NewChaseDir(actor); + } +} + +// Function: A_GoopSplat +// +// Description: Black Eggman goop hits a target and sticks around for awhile. +// +// var1 = unused +// var2 = unused +// +void A_GoopSplat(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_GoopSplat", actor)) + return; +#endif + P_UnsetThingPosition(actor); + if (sector_list) + { + P_DelSeclist(sector_list); + sector_list = NULL; + } + actor->flags = MF_SPECIAL; // Not a typo + P_SetThingPosition(actor); +} + +// Function: A_Boss2PogoSFX +// +// Description: Pogoing for Boss 2 +// +// var1 = pogo jump strength +// var2 = idle pogo speed +// +void A_Boss2PogoSFX(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss2PogoSFX", actor)) + return; +#endif + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { + // look for a new target + if (P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + return; + } + + // Boing! + if (P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) < FixedMul(256*FRACUNIT, actor->scale)) + { + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + P_InstaThrust(actor, actor->angle, FixedMul(actor->info->speed, actor->scale)); + // pogo on player + } + else + { + UINT8 prandom = P_RandomByte(); + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom); + P_InstaThrust(actor, actor->angle, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale)); + } + if (actor->info->activesound) S_StartSound(actor, actor->info->activesound); + actor->momz = FixedMul(locvar1, actor->scale); // Bounce up in air + actor->reactiontime = 1; +} + +// Function: A_Boss2PogoTarget +// +// Description: Pogoing for Boss 2, tries to actually land on the player directly. +// +// var1 = pogo jump strength +// var2 = idle pogo speed +// +void A_Boss2PogoTarget(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss2PogoTarget", actor)) + return; +#endif + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE) || (actor->target->player && actor->target->player->powers[pw_flashing]) + || P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) >= FixedMul(512*FRACUNIT, actor->scale)) + { + // look for a new target + if (P_LookForPlayers(actor, true, false, 512*FRACUNIT)) + ; // got a new target + else if (P_LookForPlayers(actor, true, false, 0)) + ; // got a new target + else + return; + } + + // Target hit, retreat! + if (actor->target->player->powers[pw_flashing] > TICRATE || actor->flags2 & MF2_FRET) + { + UINT8 prandom = P_RandomByte(); + actor->z++; // unstick from the floor + actor->momz = FixedMul(locvar1, actor->scale); // Bounce up in air + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom); // Pick a direction, and randomize it. + P_InstaThrust(actor, actor->angle+ANGLE_180, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale)); // Move at wandering speed + } + // Try to land on top of the player. + else if (P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) < FixedMul(512*FRACUNIT, actor->scale)) + { + fixed_t airtime, gravityadd, zoffs; + + // check gravity in the sector (for later math) + P_CheckGravity(actor, true); + gravityadd = actor->momz; + + actor->z++; // unstick from the floor + actor->momz = FixedMul(locvar1 + (locvar1>>2), actor->scale); // Bounce up in air + + /*badmath = 0; + airtime = 0; + do { + badmath += momz; + momz += gravityadd; + airtime++; + } while(badmath > 0); + airtime = 2*airtime<momz<<1, gravityadd)<<1; // going from 0 to 0 is much simpler + zoffs = (P_GetPlayerHeight(actor->target->player)>>1) + (actor->target->floorz - actor->floorz); // offset by the difference in floor height plus half the player height, + airtime = FixedDiv((-actor->momz - FixedSqrt(FixedMul(actor->momz,actor->momz)+zoffs)), gravityadd)<<1; // to try and land on their head rather than on their feet + + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + P_InstaThrust(actor, actor->angle, FixedDiv(P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y), airtime)); + } + // Wander semi-randomly towards the player to get closer. + else + { + UINT8 prandom = P_RandomByte(); + actor->z++; // unstick from the floor + actor->momz = FixedMul(locvar1, actor->scale); // Bounce up in air + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom); // Pick a direction, and randomize it. + P_InstaThrust(actor, actor->angle, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale)); // Move at wandering speed + } + // Boing! + if (actor->info->activesound) S_StartSound(actor, actor->info->activesound); + + if (actor->info->missilestate) // spawn the pogo stick collision box + { + mobj_t *pogo = P_SpawnMobj(actor->x, actor->y, actor->z - mobjinfo[actor->info->missilestate].height, (mobjtype_t)actor->info->missilestate); + pogo->target = actor; + } + + actor->reactiontime = 1; +} + +// Function: A_EggmanBox +// +// Description: Harms the player +// +// var1 = unused +// var2 = unused +// +void A_EggmanBox(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_EggmanBox", actor)) + return; +#endif + if (!actor->target || !actor->target->player) + { + CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); + return; + } + + P_DamageMobj(actor->target, actor, actor, 1, 0); // Ow! +} + +// Function: A_TurretFire +// +// Description: Initiates turret fire. +// +// var1 = object # to repeatedly fire +// var2 = distance threshold +// +void A_TurretFire(mobj_t *actor) +{ + INT32 count = 0; + fixed_t dist; + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_TurretFire", actor)) + return; +#endif + + if (locvar2) + dist = FixedMul(locvar2*FRACUNIT, actor->scale); + else + dist = FixedMul(2048*FRACUNIT, actor->scale); + + if (!locvar1) + locvar1 = MT_TURRETLASER; + + while (P_SupermanLook4Players(actor) && count < MAXPLAYERS) + { + if (P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) < dist) + { + actor->flags2 |= MF2_FIRING; + actor->extravalue1 = locvar1; + break; + } + + count++; + } +} + +// Function: A_SuperTurretFire +// +// Description: Initiates turret fire that even stops Super Sonic. +// +// var1 = object # to repeatedly fire +// var2 = distance threshold +// +void A_SuperTurretFire(mobj_t *actor) +{ + INT32 count = 0; + fixed_t dist; + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SuperTurretFire", actor)) + return; +#endif + + if (locvar2) + dist = FixedMul(locvar2*FRACUNIT, actor->scale); + else + dist = FixedMul(2048*FRACUNIT, actor->scale); + + if (!locvar1) + locvar1 = MT_TURRETLASER; + + while (P_SupermanLook4Players(actor) && count < MAXPLAYERS) + { + if (P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) < dist) + { + actor->flags2 |= MF2_FIRING; + actor->flags2 |= MF2_SUPERFIRE; + actor->extravalue1 = locvar1; + break; + } + + count++; + } +} + +// Function: A_TurretStop +// +// Description: Stops the turret fire. +// +// var1 = Don't play activesound? +// var2 = unused +// +void A_TurretStop(mobj_t *actor) +{ + INT32 locvar1 = var1; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_TurretStop", actor)) + return; +#endif + + actor->flags2 &= ~MF2_FIRING; + actor->flags2 &= ~MF2_SUPERFIRE; + + if (actor->target && actor->info->activesound && !locvar1) + S_StartSound(actor, actor->info->activesound); +} + +// Function: A_SparkFollow +// +// Description: Used by the hyper sparks to rotate around their target. +// +// var1 = unused +// var2 = unused +// +void A_SparkFollow(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SparkFollow", actor)) + return; +#endif + + if ((!actor->target || (actor->target->health <= 0)) + || (actor->target->player && !actor->target->player->powers[pw_super])) + { + P_RemoveMobj(actor); + return; + } + + actor->angle += FixedAngle(actor->info->damage*FRACUNIT); + P_UnsetThingPosition(actor); + { + const angle_t fa = actor->angle>>ANGLETOFINESHIFT; + actor->x = actor->target->x + FixedMul(FINECOSINE(fa),FixedMul(actor->info->speed, actor->scale)); + actor->y = actor->target->y + FixedMul(FINESINE(fa),FixedMul(actor->info->speed, actor->scale)); + if (actor->target->eflags & MFE_VERTICALFLIP) + actor->z = actor->target->z + actor->target->height - FixedDiv(actor->target->height,3*FRACUNIT); + else + actor->z = actor->target->z + FixedDiv(actor->target->height,3*FRACUNIT) - actor->height; + } + P_SetThingPosition(actor); +} + +// Function: A_BuzzFly +// +// Description: Makes an object slowly fly after a player, in the manner of a Buzz. +// +// var1 = sfx to play +// var2 = length of sfx, set to threshold if played +// +void A_BuzzFly(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_BuzzFly", actor)) + return; +#endif + if (actor->flags2 & MF2_AMBUSH) + return; + + if (actor->reactiontime) + actor->reactiontime--; + + // modify target threshold + if (actor->threshold) + { + if (!actor->target || actor->target->health <= 0) + actor->threshold = 0; + else + actor->threshold--; + } + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { + // look for a new target + if (P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + actor->momz = actor->momy = actor->momx = 0; + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + + // turn towards movement direction if not there yet + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + + if (actor->target->health <= 0 || (!actor->threshold && !P_CheckSight(actor, actor->target))) + { + if ((multiplayer || netgame) && P_LookForPlayers(actor, true, false, FixedMul(3072*FRACUNIT, actor->scale))) + return; // got a new target + + actor->momx = actor->momy = actor->momz = 0; + P_SetMobjState(actor, actor->info->spawnstate); // Go back to looking around + return; + } + + // If the player is over 3072 fracunits away, then look for another player + if (P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), + actor->target->z - actor->z) > FixedMul(3072*FRACUNIT, actor->scale)) + { + if (multiplayer || netgame) + P_LookForPlayers(actor, true, false, FixedMul(3072*FRACUNIT, actor->scale)); // maybe get a new target + + return; + } + + // chase towards player + { + INT32 dist, realspeed; + const fixed_t mf = 5*(FRACUNIT/4); + + if (ultimatemode) + realspeed = FixedMul(FixedMul(actor->info->speed,mf), actor->scale); + else + realspeed = FixedMul(actor->info->speed, actor->scale); + + dist = P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, + actor->target->y - actor->y), actor->target->z - actor->z); + + if (dist < 1) + dist = 1; + + actor->momx = FixedMul(FixedDiv(actor->target->x - actor->x, dist), realspeed); + actor->momy = FixedMul(FixedDiv(actor->target->y - actor->y, dist), realspeed); + actor->momz = FixedMul(FixedDiv(actor->target->z - actor->z, dist), realspeed); + + if (actor->z+actor->momz >= actor->waterbottom && actor->watertop > actor->floorz + && actor->z+actor->momz > actor->watertop - FixedMul(256*FRACUNIT, actor->scale) + && actor->z+actor->momz <= actor->watertop) + { + actor->momz = 0; + actor->z = actor->watertop; + } + } + + if (locvar1 != sfx_None && !actor->threshold) + { + S_StartSound(actor, locvar1); + actor->threshold = locvar2; + } +} + +// Function: A_GuardChase +// +// Description: Modified A_Chase for Egg Guard +// +// var1 = unused +// var2 = unused +// +void A_GuardChase(mobj_t *actor) +{ + INT32 delta; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_GuardChase", actor)) + return; +#endif + + if (actor->reactiontime) + actor->reactiontime--; + + if (actor->threshold != 42) // In formation... + { + fixed_t speed; + + if (!actor->tracer || !actor->tracer->health) + { + P_SetTarget(&actor->tracer, NULL); + actor->threshold = 42; + P_SetMobjState(actor, actor->info->painstate); + actor->flags |= MF_SPECIAL|MF_SHOOTABLE; + return; + } + + speed = actor->extravalue1*actor->scale; + + if (actor->flags2 & MF2_AMBUSH) + speed <<= 1; + + if (speed + && !P_TryMove(actor, + actor->x + P_ReturnThrustX(actor, actor->angle, speed), + actor->y + P_ReturnThrustY(actor, actor->angle, speed), + false) + && speed > 0) // can't be the same check as previous so that P_TryMove gets to happen. + { + if (actor->spawnpoint && ((actor->spawnpoint->options & (MTF_EXTRA|MTF_OBJECTSPECIAL)) == MTF_OBJECTSPECIAL)) + actor->angle += ANGLE_90; + else if (actor->spawnpoint && ((actor->spawnpoint->options & (MTF_EXTRA|MTF_OBJECTSPECIAL)) == MTF_EXTRA)) + actor->angle -= ANGLE_90; + else + actor->angle += ANGLE_180; + } + + if (actor->extravalue1 < actor->info->speed) + actor->extravalue1++; + } + else // Break ranks! + { + // turn towards movement direction if not there yet + if (actor->movedir < NUMDIRS) + { + actor->angle &= (7<<29); + delta = actor->angle - (actor->movedir << 29); + + if (delta > 0) + actor->angle -= ANGLE_45; + else if (delta < 0) + actor->angle += ANGLE_45; + } + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { + // look for a new target + if (P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + P_SetMobjStateNF(actor, actor->info->spawnstate); + return; + } + + // possibly choose another target + if (multiplayer && (actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) + && P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + // chase towards player + if (--actor->movecount < 0 || !P_Move(actor, (actor->flags2 & MF2_AMBUSH) ? actor->info->speed * 2 : actor->info->speed)) + { + P_NewChaseDir(actor); + actor->movecount += 5; // Increase tics before change in direction allowed. + } + } + + // Now that we've moved, its time for our shield to move! + // Otherwise it'll never act as a proper overlay. + if (actor->tracer && actor->tracer->state + && actor->tracer->state->action.acp1) + { + var1 = actor->tracer->state->var1, var2 = actor->tracer->state->var2; + actor->tracer->state->action.acp1(actor->tracer); + } +} + +// Function: A_EggShield +// +// Description: Modified A_Chase for Egg Guard's shield +// +// var1 = unused +// var2 = unused +// +void A_EggShield(mobj_t *actor) +{ + INT32 i; + player_t *player; + fixed_t blockdist; + fixed_t newx, newy; + fixed_t movex, movey; + angle_t angle; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_EggShield", actor)) + return; +#endif + + if (!actor->target || !actor->target->health) + { + P_RemoveMobj(actor); + return; + } + + newx = actor->target->x + P_ReturnThrustX(actor, actor->target->angle, FixedMul(FRACUNIT, actor->scale)); + newy = actor->target->y + P_ReturnThrustY(actor, actor->target->angle, FixedMul(FRACUNIT, actor->scale)); + + movex = newx - actor->x; + movey = newy - actor->y; + + actor->angle = actor->target->angle; + if (actor->target->eflags & MFE_VERTICALFLIP) + { + actor->eflags |= MFE_VERTICALFLIP; + actor->z = actor->target->z + actor->target->height - actor->height; + } + else + actor->z = actor->target->z; + + actor->destscale = actor->target->destscale; + P_SetScale(actor, actor->target->scale); + + actor->floorz = actor->target->floorz; + actor->ceilingz = actor->target->ceilingz; + + if (!movex && !movey) + return; + + P_UnsetThingPosition(actor); + actor->x = newx; + actor->y = newy; + P_SetThingPosition(actor); + + // Search for players to push + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + + player = &players[i]; + + if (!player->mo) + continue; + + if (player->mo->z > actor->z + actor->height) + continue; + + if (player->mo->z + player->mo->height < actor->z) + continue; + + blockdist = actor->radius + player->mo->radius; + + if (abs(actor->x - player->mo->x) >= blockdist || abs(actor->y - player->mo->y) >= blockdist) + continue; // didn't hit it + + angle = R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y) - actor->angle; + + if (angle > ANGLE_90 && angle < ANGLE_270) + continue; + + // Blocked by the shield + player->mo->momx += movex; + player->mo->momy += movey; + return; + } +} + + +// Function: A_SetReactionTime +// +// Description: Sets the object's reaction time. +// +// var1 = 1 (use value in var2); 0 (use info table value) +// var2 = if var1 = 1, then value to set +// +void A_SetReactionTime(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetReactionTime", actor)) + return; +#endif + if (var1) + actor->reactiontime = var2; + else + actor->reactiontime = actor->info->reactiontime; +} + +// Function: A_Boss1Spikeballs +// +// Description: Boss 1 spikeball spawning loop. +// +// var1 = ball number +// var2 = total balls +// +void A_Boss1Spikeballs(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *ball; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss1Spikeballs", actor)) + return; +#endif + + ball = P_SpawnMobj(actor->x, actor->y, actor->z, MT_EGGMOBILE_BALL); + P_SetTarget(&ball->target, actor); + ball->movedir = FixedAngle(FixedMul(FixedDiv(locvar1<threshold = ball->radius + actor->radius + ball->info->painchance; + + S_StartSound(ball, ball->info->seesound); + var1 = ball->state->var1, var2 = ball->state->var2; + ball->state->action.acp1(ball); +} + +// Function: A_Boss3TakeDamage +// +// Description: Called when Boss 3 takes damage. +// +// var1 = movecount value +// var2 = unused +// +void A_Boss3TakeDamage(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss3TakeDamage", actor)) + return; +#endif + actor->movecount = var1; + + if (actor->target && actor->target->spawnpoint) + actor->threshold = actor->target->spawnpoint->extrainfo; +} + +// Function: A_Boss3Path +// +// Description: Does pathfinding along Boss 3's nodes. +// +// var1 = unused +// var2 = unused +// +void A_Boss3Path(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss3Path", actor)) + return; +#endif + + if (actor->tracer && actor->tracer->health && actor->tracer->movecount) + actor->movecount |= 1; + else if (actor->movecount & 1) + actor->movecount = 0; + + if (actor->movecount & 2) // We've reached a firing point? + { + // Wait here and pretend to be angry or something. + actor->momx = 0; + actor->momy = 0; + actor->momz = 0; + P_SetTarget(&actor->target, actor->tracer->target); + var1 = 0, var2 = 0; + A_FaceTarget(actor); + if (actor->tracer->state == &states[actor->tracer->info->missilestate]) + P_SetMobjState(actor, actor->info->missilestate); + return; + } + else if (actor->threshold >= 0) // Traveling mode + { + thinker_t *th; + mobj_t *mo2; + fixed_t dist, dist2; + fixed_t speed; + + P_SetTarget(&actor->target, NULL); + + // scan the thinkers + // to find a point that matches + // the number + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo2 = (mobj_t *)th; + if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && mo2->spawnpoint->angle == actor->threshold) + { + P_SetTarget(&actor->target, mo2); + break; + } + } + + if (!actor->target) // Should NEVER happen + { + CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 Dummy was unable to find specified waypoint: %d\n", actor->threshold); + return; + } + + dist = P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), actor->target->z - actor->z); + + if (dist < 1) + dist = 1; + + if (actor->tracer && ((actor->tracer->movedir) + || (actor->tracer->health <= actor->tracer->info->damage))) + speed = actor->info->speed * 2; + else + speed = actor->info->speed; + + actor->momx = FixedMul(FixedDiv(actor->target->x - actor->x, dist), speed); + actor->momy = FixedMul(FixedDiv(actor->target->y - actor->y, dist), speed); + actor->momz = FixedMul(FixedDiv(actor->target->z - actor->z, dist), speed); + + if (actor->momx != 0 || actor->momy != 0) + actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); + + dist2 = P_AproxDistance(P_AproxDistance(actor->target->x - (actor->x + actor->momx), actor->target->y - (actor->y + actor->momy)), actor->target->z - (actor->z + actor->momz)); + + if (dist2 < 1) + dist2 = 1; + + if ((dist >> FRACBITS) <= (dist2 >> FRACBITS)) + { + // If further away, set XYZ of mobj to waypoint location + P_UnsetThingPosition(actor); + actor->x = actor->target->x; + actor->y = actor->target->y; + actor->z = actor->target->z; + actor->momx = actor->momy = actor->momz = 0; + P_SetThingPosition(actor); + + if (actor->threshold == 0) + { + P_RemoveMobj(actor); // Cycle completed. Dummy removed. + return; + } + + // Set to next waypoint in sequence + if (actor->target->spawnpoint) + { + // From the center point, choose one of the five paths + if (actor->target->spawnpoint->angle == 0) + { + P_RemoveMobj(actor); // Cycle completed. Dummy removed. + return; + } + else + actor->threshold = actor->target->spawnpoint->extrainfo; + + // If the deaf flag is set, go into firing mode + if (actor->target->spawnpoint->options & MTF_AMBUSH) + actor->movecount |= 2; + } + else // This should never happen, as well + CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 Dummy waypoint has no spawnpoint associated with it.\n"); + } + } +} + +// Function: A_LinedefExecute +// +// Description: Object's location is used to set the calling sector. The tag used is var1. Optionally, if var2 is set, the actor's angle (multiplied by var2) is added to the tag number as well. +// +// var1 = tag +// var2 = add angle to tag (optional) +// +void A_LinedefExecute(mobj_t *actor) +{ + INT32 tagnum; + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_LinedefExecute", actor)) + return; +#endif + + tagnum = locvar1; + // state numbers option is no more, custom states cannot be guaranteed to stay the same number anymore, now that they can be defined by names instead + + if (locvar2) + tagnum += locvar2*(AngleFixed(actor->angle)>>FRACBITS); + + CONS_Debug(DBG_GAMELOGIC, "A_LinedefExecute: Running mobjtype %d's sector with tag %d\n", actor->type, tagnum); + + // tag 32768 displayed in map editors is actually tag -32768, tag 32769 is -32767, 65535 is -1 etc. + P_LinedefExecute((INT16)tagnum, actor, actor->subsector->sector); +} + +// Function: A_PlaySeeSound +// +// Description: Plays the object's seesound. +// +// var1 = unused +// var2 = unused +// +void A_PlaySeeSound(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_PlaySeeSound", actor)) + return; +#endif + if (actor->info->seesound) + S_StartScreamSound(actor, actor->info->seesound); +} + +// Function: A_PlayAttackSound +// +// Description: Plays the object's attacksound. +// +// var1 = unused +// var2 = unused +// +void A_PlayAttackSound(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_PlayAttackSound", actor)) + return; +#endif + if (actor->info->attacksound) + S_StartAttackSound(actor, actor->info->attacksound); +} + +// Function: A_PlayActiveSound +// +// Description: Plays the object's activesound. +// +// var1 = unused +// var2 = unused +// +void A_PlayActiveSound(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_PlayActiveSound", actor)) + return; +#endif + if (actor->info->activesound) + S_StartSound(actor, actor->info->activesound); +} + +// Function: A_SmokeTrailer +// +// Description: Adds smoke trails to an object. +// +// var1 = object # to spawn as smoke +// var2 = unused +// +void A_SmokeTrailer(mobj_t *actor) +{ + mobj_t *th; + INT32 locvar1 = var1; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SmokeTrailer", actor)) + return; +#endif + + if (leveltime % 4) + return; + + // add the smoke behind the rocket + if (actor->eflags & MFE_VERTICALFLIP) + { + th = P_SpawnMobj(actor->x-actor->momx, actor->y-actor->momy, actor->z + actor->height - FixedMul(mobjinfo[locvar1].height, actor->scale), locvar1); + th->flags2 |= MF2_OBJECTFLIP; + } + else + th = P_SpawnMobj(actor->x-actor->momx, actor->y-actor->momy, actor->z, locvar1); + P_SetObjectMomZ(th, FRACUNIT, false); + th->destscale = actor->scale; + P_SetScale(th, actor->scale); + th->tics -= P_RandomByte() & 3; + if (th->tics < 1) + th->tics = 1; +} + +// Function: A_SpawnObjectAbsolute +// +// Description: Spawns an object at an absolute position +// +// var1: +// var1 >> 16 = x +// var1 & 65535 = y +// var2: +// var2 >> 16 = z +// var2 & 65535 = type +// +void A_SpawnObjectAbsolute(mobj_t *actor) +{ + INT16 x, y, z; // Want to be sure we can use negative values + mobjtype_t type; + mobj_t *mo; + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SpawnObjectAbsolute", actor)) + return; +#endif + + x = (INT16)(locvar1>>16); + y = (INT16)(locvar1&65535); + z = (INT16)(locvar2>>16); + type = (mobjtype_t)(locvar2&65535); + + mo = P_SpawnMobj(x<angle = actor->angle; + + if (actor->eflags & MFE_VERTICALFLIP) + mo->flags2 |= MF2_OBJECTFLIP; +} + +// Function: A_SpawnObjectRelative +// +// Description: Spawns an object relative to the location of the actor +// +// var1: +// var1 >> 16 = x +// var1 & 65535 = y +// var2: +// var2 >> 16 = z +// var2 & 65535 = type +// +void A_SpawnObjectRelative(mobj_t *actor) +{ + INT16 x, y, z; // Want to be sure we can use negative values + mobjtype_t type; + mobj_t *mo; + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SpawnObjectRelative", actor)) + return; +#endif + + CONS_Debug(DBG_GAMELOGIC, "A_SpawnObjectRelative called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); + + x = (INT16)(locvar1>>16); + y = (INT16)(locvar1&65535); + z = (INT16)(locvar2>>16); + type = (mobjtype_t)(locvar2&65535); + + // Spawn objects correctly in reverse gravity. + // NOTE: Doing actor->z + actor->height is the bottom of the object while the object has reverse gravity. - Flame + mo = P_SpawnMobj(actor->x + FixedMul(x<scale), + actor->y + FixedMul(y<scale), + (actor->eflags & MFE_VERTICALFLIP) ? ((actor->z + actor->height - mobjinfo[type].height) - FixedMul(z<scale)) : (actor->z + FixedMul(z<scale)), type); + + // Spawn objects with an angle matching the spawner's, rather than spawning Eastwards - Monster Iestyn + mo->angle = actor->angle; + + if (actor->eflags & MFE_VERTICALFLIP) + mo->flags2 |= MF2_OBJECTFLIP; + +} + +// Function: A_ChangeAngleRelative +// +// Description: Changes the angle to a random relative value between the min and max. Set min and max to the same value to eliminate randomness +// +// var1 = min +// var2 = max +// +void A_ChangeAngleRelative(mobj_t *actor) +{ + // Oh god, the old code /sucked/. Changed this and the absolute version to get a random range using amin and amax instead of + // getting a random angle from the _entire_ spectrum and then clipping. While we're at it, do the angle conversion to the result + // rather than the ranges, so <0 and >360 work as possible values. -Red + INT32 locvar1 = var1; + INT32 locvar2 = var2; + //angle_t angle = (P_RandomByte()+1)<<24; + const fixed_t amin = locvar1*FRACUNIT; + const fixed_t amax = locvar2*FRACUNIT; + //const angle_t amin = FixedAngle(locvar1*FRACUNIT); + //const angle_t amax = FixedAngle(locvar2*FRACUNIT); +#ifdef HAVE_BLUA + if (LUA_CallAction("A_ChangeAngleRelative", actor)) + return; +#endif + +#ifdef PARANOIA + if (amin > amax) + I_Error("A_ChangeAngleRelative: var1 is greater then var2"); +#endif +/* + if (angle < amin) + angle = amin; + if (angle > amax) + angle = amax;*/ + + actor->angle += FixedAngle(P_RandomRange(amin, amax)); +} + +// Function: A_ChangeAngleAbsolute +// +// Description: Changes the angle to a random absolute value between the min and max. Set min and max to the same value to eliminate randomness +// +// var1 = min +// var2 = max +// +void A_ChangeAngleAbsolute(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + //angle_t angle = (P_RandomByte()+1)<<24; + const fixed_t amin = locvar1*FRACUNIT; + const fixed_t amax = locvar2*FRACUNIT; + //const angle_t amin = FixedAngle(locvar1*FRACUNIT); + //const angle_t amax = FixedAngle(locvar2*FRACUNIT); +#ifdef HAVE_BLUA + if (LUA_CallAction("A_ChangeAngleAbsolute", actor)) + return; +#endif + +#ifdef PARANOIA + if (amin > amax) + I_Error("A_ChangeAngleAbsolute: var1 is greater then var2"); +#endif +/* + if (angle < amin) + angle = amin; + if (angle > amax) + angle = amax;*/ + + actor->angle = FixedAngle(P_RandomRange(amin, amax)); +} + +// Function: A_PlaySound +// +// Description: Plays a sound +// +// var1 = sound # to play +// var2: +// 0 = Play sound without an origin +// 1 = Play sound using calling object as origin +// +void A_PlaySound(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_PlaySound", actor)) + return; +#endif + + S_StartSound(locvar2 ? actor : NULL, locvar1); +} + +// Function: A_FindTarget +// +// Description: Finds the nearest/furthest mobj of the specified type and sets actor->target to it. +// +// var1 = mobj type +// var2 = if (0) nearest; else furthest; +// +void A_FindTarget(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *targetedmobj = NULL; + thinker_t *th; + mobj_t *mo2; + fixed_t dist1 = 0, dist2 = 0; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FindTarget", actor)) + return; +#endif + + CONS_Debug(DBG_GAMELOGIC, "A_FindTarget called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); + + // scan the thinkers + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type == (mobjtype_t)locvar1) + { + if (mo2->player && (mo2->player->spectator || mo2->player->pflags & PF_INVIS)) + continue; // Ignore spectators + if ((mo2->player || mo2->flags & MF_ENEMY) && mo2->health <= 0) + continue; // Ignore dead things + if (targetedmobj == NULL) + { + targetedmobj = mo2; + dist2 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); + } + else + { + dist1 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); + + if ((!locvar2 && dist1 < dist2) || (locvar2 && dist1 > dist2)) + { + targetedmobj = mo2; + dist2 = dist1; + } + } + } + } + + if (!targetedmobj) + { + CONS_Debug(DBG_GAMELOGIC, "A_FindTarget: Unable to find the specified object to target.\n"); + return; // Oops, nothing found.. + } + + CONS_Debug(DBG_GAMELOGIC, "A_FindTarget: Found a target.\n"); + + P_SetTarget(&actor->target, targetedmobj); +} + +// Function: A_FindTracer +// +// Description: Finds the nearest/furthest mobj of the specified type and sets actor->tracer to it. +// +// var1 = mobj type +// var2 = if (0) nearest; else furthest; +// +void A_FindTracer(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *targetedmobj = NULL; + thinker_t *th; + mobj_t *mo2; + fixed_t dist1 = 0, dist2 = 0; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FindTracer", actor)) + return; +#endif + + CONS_Debug(DBG_GAMELOGIC, "A_FindTracer called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); + + // scan the thinkers + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type == (mobjtype_t)locvar1) + { + if (mo2->player && (mo2->player->spectator || mo2->player->pflags & PF_INVIS)) + continue; // Ignore spectators + if ((mo2->player || mo2->flags & MF_ENEMY) && mo2->health <= 0) + continue; // Ignore dead things + if (targetedmobj == NULL) + { + targetedmobj = mo2; + dist2 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); + } + else + { + dist1 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); + + if ((!locvar2 && dist1 < dist2) || (locvar2 && dist1 > dist2)) + { + targetedmobj = mo2; + dist2 = dist1; + } + } + } + } + + if (!targetedmobj) + { + CONS_Debug(DBG_GAMELOGIC, "A_FindTracer: Unable to find the specified object to target.\n"); + return; // Oops, nothing found.. + } + + CONS_Debug(DBG_GAMELOGIC, "A_FindTracer: Found a target.\n"); + + P_SetTarget(&actor->tracer, targetedmobj); +} + +// Function: A_SetTics +// +// Description: Sets the animation tics of an object +// +// var1 = tics to set to +// var2 = if this is set, and no var1 is supplied, the mobj's threshold value will be used. +// +void A_SetTics(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetTics", actor)) + return; +#endif + + if (locvar1) + actor->tics = locvar1; + else if (locvar2) + actor->tics = actor->threshold; +} + +// Function: A_SetRandomTics +// +// Description: Sets the animation tics of an object to a random value +// +// var1 = lower bound +// var2 = upper bound +// +void A_SetRandomTics(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetRandomTics", actor)) + return; +#endif + + actor->tics = P_RandomRange(locvar1, locvar2); +} + +// Function: A_ChangeColorRelative +// +// Description: Changes the color of an object +// +// var1 = if (var1 > 0), find target and add its color value to yours +// var2 = if (var1 = 0), color value to add +// +void A_ChangeColorRelative(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_ChangeColorRelative", actor)) + return; +#endif + + if (locvar1) + { + // Have you ever seen anything so hideous? + if (actor->target) + actor->color = (UINT8)(actor->color + actor->target->color); + } + else + actor->color = (UINT8)(actor->color + locvar2); +} + +// Function: A_ChangeColorAbsolute +// +// Description: Changes the color of an object by an absolute value. Note: 0 is default colormap. +// +// var1 = if (var1 > 0), set your color to your target's color +// var2 = if (var1 = 0), color value to set to +// +void A_ChangeColorAbsolute(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_ChangeColorAbsolute", actor)) + return; +#endif + + if (locvar1) + { + if (actor->target) + actor->color = actor->target->color; + } + else + actor->color = (UINT8)locvar2; +} + +// Function: A_MoveRelative +// +// Description: Moves an object (wrapper for P_Thrust) +// +// var1 = angle +// var2 = force +// +void A_MoveRelative(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_MoveRelative", actor)) + return; +#endif + + P_Thrust(actor, actor->angle+FixedAngle(locvar1*FRACUNIT), FixedMul(locvar2*FRACUNIT, actor->scale)); +} + +// Function: A_MoveAbsolute +// +// Description: Moves an object (wrapper for P_InstaThrust) +// +// var1 = angle +// var2 = force +// +void A_MoveAbsolute(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_MoveAbsolute", actor)) + return; +#endif + + P_InstaThrust(actor, FixedAngle(locvar1*FRACUNIT), FixedMul(locvar2*FRACUNIT, actor->scale)); +} + +// Function: A_Thrust +// +// Description: Pushes the object horizontally at its current angle. +// +// var1 = amount of force +// var2 = If 1, xy momentum is lost. If 0, xy momentum is kept +// +void A_Thrust(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Thrust", actor)) + return; +#endif + + if (!locvar1) + CONS_Debug(DBG_GAMELOGIC, "A_Thrust: Var1 not specified!\n"); + + if (locvar2) + P_InstaThrust(actor, actor->angle, FixedMul(locvar1*FRACUNIT, actor->scale)); + else + P_Thrust(actor, actor->angle, FixedMul(locvar1*FRACUNIT, actor->scale)); +} + +// Function: A_ZThrust +// +// Description: Pushes the object up or down. +// +// var1 = amount of force +// var2: +// lower 16 bits = If 1, xy momentum is lost. If 0, xy momentum is kept +// upper 16 bits = If 1, z momentum is lost. If 0, z momentum is kept +// +void A_ZThrust(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_ZThrust", actor)) + return; +#endif + + if (!locvar1) + CONS_Debug(DBG_GAMELOGIC, "A_ZThrust: Var1 not specified!\n"); + + if (locvar2 & 65535) + actor->momx = actor->momy = 0; + + if (actor->eflags & MFE_VERTICALFLIP) + actor->z--; + else + actor->z++; + + P_SetObjectMomZ(actor, locvar1*FRACUNIT, !(locvar2 >> 16)); +} + +// Function: A_SetTargetsTarget +// +// Description: Sets your target to the object who your target is targeting. Yikes! If it happens to be NULL, you're just out of luck. +// +// var1: (Your target) +// 0 = target +// 1 = tracer +// var2: (Your target's target) +// 0 = target/tracer's target +// 1 = target/tracer's tracer +// +void A_SetTargetsTarget(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *oldtarg = NULL, *newtarg = NULL; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetTargetsTarget", actor)) + return; +#endif + + // actor's target + if (locvar1) // or tracer + oldtarg = actor->tracer; + else + oldtarg = actor->target; + + if (P_MobjWasRemoved(oldtarg)) + return; + + // actor's target's target! + if (locvar2) // or tracer + newtarg = oldtarg->tracer; + else + newtarg = oldtarg->target; + + if (P_MobjWasRemoved(newtarg)) + return; + + // set actor's new target + if (locvar1) // or tracer + P_SetTarget(&actor->tracer, newtarg); + else + P_SetTarget(&actor->target, newtarg); +} + +// Function: A_SetObjectFlags +// +// Description: Sets the flags of an object +// +// var1 = flag value to set +// var2: +// if var2 == 2, add the flag to the current flags +// else if var2 == 1, remove the flag from the current flags +// else if var2 == 0, set the flags to the exact value +// +void A_SetObjectFlags(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + boolean unlinkthings = false; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetObjectFlags", actor)) + return; +#endif + + if (locvar2 == 2) + locvar1 = actor->flags | locvar1; + else if (locvar2 == 1) + locvar1 = actor->flags & ~locvar1; + + if ((UINT32)(locvar1 & (MF_NOBLOCKMAP|MF_NOSECTOR)) != (actor->flags & (MF_NOBLOCKMAP|MF_NOSECTOR))) // Blockmap/sector status has changed, so reset the links + unlinkthings = true; + + if (unlinkthings) { + P_UnsetThingPosition(actor); + if (sector_list) + { + P_DelSeclist(sector_list); + sector_list = NULL; + } + } + + actor->flags = locvar1; + + if (unlinkthings) + P_SetThingPosition(actor); +} + +// Function: A_SetObjectFlags2 +// +// Description: Sets the flags2 of an object +// +// var1 = flag value to set +// var2: +// if var2 == 2, add the flag to the current flags +// else if var2 == 1, remove the flag from the current flags +// else if var2 == 0, set the flags to the exact value +// +void A_SetObjectFlags2(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetObjectFlags2", actor)) + return; +#endif + + if (locvar2 == 2) + actor->flags2 |= locvar1; + else if (locvar2 == 1) + actor->flags2 &= ~locvar1; + else + actor->flags2 = locvar1; +} + +// Function: A_BossJetFume +// +// Description: Spawns jet fumes/other attachment miscellany for the boss. To only be used when he is spawned. +// +// var1: +// 0 - Triple jet fume pattern +// 1 - Boss 3's propeller +// 2 - Metal Sonic jet fume +// 3 - Boss 4 jet flame +// var2 = unused +// +void A_BossJetFume(mobj_t *actor) +{ + mobj_t *filler; + INT32 locvar1 = var1; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_BossJetFume", actor)) + return; +#endif + + if (locvar1 == 0) // Boss1 jet fumes + { + fixed_t jetx, jety, jetz; + + jetx = actor->x + P_ReturnThrustX(actor, actor->angle, -FixedMul(64*FRACUNIT, actor->scale)); + jety = actor->y + P_ReturnThrustY(actor, actor->angle, -FixedMul(64*FRACUNIT, actor->scale)); + if (actor->eflags & MFE_VERTICALFLIP) + jetz = actor->z + actor->height - FixedMul(38*FRACUNIT + mobjinfo[MT_JETFUME1].height, actor->scale); + else + jetz = actor->z + FixedMul(38*FRACUNIT, actor->scale); + + filler = P_SpawnMobj(jetx, jety, jetz, MT_JETFUME1); + P_SetTarget(&filler->target, actor); + filler->destscale = actor->scale; + P_SetScale(filler, filler->destscale); + if (actor->eflags & MFE_VERTICALFLIP) + filler->flags2 |= MF2_OBJECTFLIP; + filler->fuse = 56; + + if (actor->eflags & MFE_VERTICALFLIP) + jetz = actor->z + actor->height - FixedMul(12*FRACUNIT + mobjinfo[MT_JETFUME1].height, actor->scale); + else + jetz = actor->z + FixedMul(12*FRACUNIT, actor->scale); + + filler = P_SpawnMobj(jetx + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(24*FRACUNIT, actor->scale)), + jety + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(24*FRACUNIT, actor->scale)), + jetz, MT_JETFUME1); + P_SetTarget(&filler->target, actor); + filler->destscale = actor->scale; + P_SetScale(filler, filler->destscale); + if (actor->eflags & MFE_VERTICALFLIP) + filler->flags2 |= MF2_OBJECTFLIP; + filler->fuse = 57; + + filler = P_SpawnMobj(jetx + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(24*FRACUNIT, actor->scale)), + jety + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(24*FRACUNIT, actor->scale)), + jetz, MT_JETFUME1); + P_SetTarget(&filler->target, actor); + filler->destscale = actor->scale; + P_SetScale(filler, filler->destscale); + if (actor->eflags & MFE_VERTICALFLIP) + filler->flags2 |= MF2_OBJECTFLIP; + filler->fuse = 58; + + P_SetTarget(&actor->tracer, filler); + } + else if (locvar1 == 1) // Boss 3 propeller + { + fixed_t jetx, jety, jetz; + + jetx = actor->x + P_ReturnThrustX(actor, actor->angle, -FixedMul(60*FRACUNIT, actor->scale)); + jety = actor->y + P_ReturnThrustY(actor, actor->angle, -FixedMul(60*FRACUNIT, actor->scale)); + if (actor->eflags & MFE_VERTICALFLIP) + jetz = actor->z + actor->height - FixedMul(17*FRACUNIT + mobjinfo[MT_PROPELLER].height, actor->scale); + else + jetz = actor->z + FixedMul(17*FRACUNIT, actor->scale); + + filler = P_SpawnMobj(jetx, jety, jetz, MT_PROPELLER); + P_SetTarget(&filler->target, actor); + filler->destscale = actor->scale; + P_SetScale(filler, filler->destscale); + if (actor->eflags & MFE_VERTICALFLIP) + filler->flags2 |= MF2_OBJECTFLIP; + filler->angle = actor->angle - ANGLE_180; + + P_SetTarget(&actor->tracer, filler); + } + else if (locvar1 == 2) // Metal Sonic jet fumes + { + filler = P_SpawnMobj(actor->x, actor->y, actor->z, MT_JETFUME1); + P_SetTarget(&filler->target, actor); + filler->fuse = 59; + P_SetTarget(&actor->tracer, filler); + filler->destscale = actor->scale/2; + P_SetScale(filler, filler->destscale); + if (actor->eflags & MFE_VERTICALFLIP) + filler->flags2 |= MF2_OBJECTFLIP; + } + else if (locvar1 == 3) // Boss 4 jet flame + { + fixed_t jetz; + if (actor->eflags & MFE_VERTICALFLIP) + jetz = actor->z + actor->height + FixedMul(50*FRACUNIT - mobjinfo[MT_JETFLAME].height, actor->scale); + else + jetz = actor->z - FixedMul(50*FRACUNIT, actor->scale); + filler = P_SpawnMobj(actor->x, actor->y, jetz, MT_JETFLAME); + P_SetTarget(&filler->target, actor); + // Boss 4 already uses its tracer for other things + filler->destscale = actor->scale; + P_SetScale(filler, filler->destscale); + if (actor->eflags & MFE_VERTICALFLIP) + filler->flags2 |= MF2_OBJECTFLIP; + } +} + +// Function: A_RandomState +// +// Description: Chooses one of the two state numbers supplied randomly. +// +// var1 = state number 1 +// var2 = state number 2 +// +void A_RandomState(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RandomState", actor)) + return; +#endif + + P_SetMobjState(actor, P_RandomChance(FRACUNIT/2) ? locvar1 : locvar2); +} + +// Function: A_RandomStateRange +// +// Description: Chooses a random state within the range supplied. +// +// var1 = Minimum state number to choose. +// var2 = Maximum state number to use. +// +void A_RandomStateRange(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RandomStateRange", actor)) + return; +#endif + + P_SetMobjState(actor, P_RandomRange(locvar1, locvar2)); +} + +// Function: A_DualAction +// +// Description: Calls two actions. Be careful, if you reference the same state this action is called from, you can create an infinite loop. +// +// var1 = state # to use 1st action from +// var2 = state # to use 2nd action from +// +void A_DualAction(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_DualAction", actor)) + return; +#endif + + CONS_Debug(DBG_GAMELOGIC, "A_DualAction called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); + + var1 = states[locvar1].var1; + var2 = states[locvar1].var2; +#ifdef HAVE_BLUA + astate = &states[locvar1]; +#endif + + CONS_Debug(DBG_GAMELOGIC, "A_DualAction: Calling First Action (state %d)...\n", locvar1); + states[locvar1].action.acp1(actor); + + var1 = states[locvar2].var1; + var2 = states[locvar2].var2; +#ifdef HAVE_BLUA + astate = &states[locvar2]; +#endif + + CONS_Debug(DBG_GAMELOGIC, "A_DualAction: Calling Second Action (state %d)...\n", locvar2); + states[locvar2].action.acp1(actor); +} + +// Function: A_RemoteAction +// +// Description: var1 is the remote object. var2 is the state reference for calling the action called on var1. var1 becomes the actor's target, the action (var2) is called on var1. actor's target is restored +// +// var1 = remote object (-2 uses tracer, -1 uses target) +// var2 = state reference for calling an action +// +void A_RemoteAction(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *originaltarget = actor->target; // Hold on to the target for later. +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RemoteAction", actor)) + return; +#endif + + // If >=0, find the closest target. + if (locvar1 >= 0) + { + ///* DO A_FINDTARGET STUFF */// + mobj_t *targetedmobj = NULL; + thinker_t *th; + mobj_t *mo2; + fixed_t dist1 = 0, dist2 = 0; + + // scan the thinkers + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type == (mobjtype_t)locvar1) + { + if (targetedmobj == NULL) + { + targetedmobj = mo2; + dist2 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); + } + else + { + dist1 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); + + if ((locvar2 && dist1 < dist2) || (!locvar2 && dist1 > dist2)) + { + targetedmobj = mo2; + dist2 = dist1; + } + } + } + } + + if (!targetedmobj) + { + CONS_Debug(DBG_GAMELOGIC, "A_RemoteAction: Unable to find the specified object to target.\n"); + return; // Oops, nothing found.. + } + + CONS_Debug(DBG_GAMELOGIC, "A_RemoteAction: Found a target.\n"); + + P_SetTarget(&actor->target, targetedmobj); + + ///* END A_FINDTARGET STUFF */// + } + + // If -2, use the tracer as the target + else if (locvar1 == -2) + P_SetTarget(&actor->target, actor->tracer); + // if -1 or anything else, just use the target. + + if (actor->target) + { + // Steal the var1 and var2 from "locvar2" + var1 = states[locvar2].var1; + var2 = states[locvar2].var2; +#ifdef HAVE_BLUA + astate = &states[locvar2]; +#endif + + CONS_Debug(DBG_GAMELOGIC, "A_RemoteAction: Calling action on %p\n" + "var1 is %d\nvar2 is %d\n", actor->target, var1, var2); + states[locvar2].action.acp1(actor->target); + } + + P_SetTarget(&actor->target, originaltarget); // Restore the original target. +} + +// Function: A_ToggleFlameJet +// +// Description: Turns a flame jet on and off. +// +// var1 = unused +// var2 = unused +// +void A_ToggleFlameJet(mobj_t* actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_ToggleFlameJet", actor)) + return; +#endif + // threshold - off delay + // movecount - on timer + + if (actor->flags2 & MF2_FIRING) + { + actor->flags2 &= ~MF2_FIRING; + + if (actor->threshold) + actor->tics = actor->threshold; + } + else + { + actor->flags2 |= MF2_FIRING; + + if (actor->movecount) + actor->tics = actor->movecount; + } +} + +// Function: A_OrbitNights +// +// Description: Used by Chaos Emeralds to orbit around Nights (aka Super Sonic.) +// +// var1 = Angle adjustment (aka orbit speed) +// var2 = Lower four bits: height offset, Upper 4 bits = set if object is Nightopian Helper +// +void A_OrbitNights(mobj_t* actor) +{ + INT32 ofs = (var2 & 0xFFFF); + boolean ishelper = (var2 & 0xFFFF0000); +#ifdef HAVE_BLUA + if (LUA_CallAction("A_OrbitNights", actor)) + return; +#endif + + if (!actor->target + || (actor->target->player && + // if NiGHTS special stage and not NiGHTSmode. + (((maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && !(actor->target->player->powers[pw_carry] == CR_NIGHTSMODE)) + // Also remove this object if they no longer have a NiGHTS helper + || (ishelper && !actor->target->player->powers[pw_nights_helper])))) + { + P_RemoveMobj(actor); + return; + } + else + { + actor->extravalue1 += var1; + P_UnsetThingPosition(actor); + { + const angle_t fa = (angle_t)actor->extravalue1 >> ANGLETOFINESHIFT; + const angle_t ofa = ((angle_t)actor->extravalue1 + (ofs*ANG1)) >> ANGLETOFINESHIFT; + + const fixed_t fc = FixedMul(FINECOSINE(fa),FixedMul(32*FRACUNIT, actor->scale)); + const fixed_t fh = FixedMul(FINECOSINE(ofa),FixedMul(20*FRACUNIT, actor->scale)); + const fixed_t fs = FixedMul(FINESINE(fa),FixedMul(32*FRACUNIT, actor->scale)); + + actor->x = actor->target->x + fc; + actor->y = actor->target->y + fs; + actor->z = actor->target->z + fh + FixedMul(16*FRACUNIT, actor->scale); + + // Semi-lazy hack + actor->angle = (angle_t)actor->extravalue1 + ANGLE_90; + } + P_SetThingPosition(actor); + + if (ishelper && actor->target->player) // Flash a helper that's about to be removed. + { + if ((actor->target->player->powers[pw_nights_helper] < TICRATE) + && (actor->target->player->powers[pw_nights_helper] & 1)) + actor->flags2 |= MF2_DONTDRAW; + else + actor->flags2 &= ~MF2_DONTDRAW; + } + } +} + +// Function: A_GhostMe +// +// Description: Spawns a "ghost" mobj of this actor, ala spindash trails and the minus's digging "trails" +// +// var1 = duration in tics +// var2 = unused +// +void A_GhostMe(mobj_t *actor) +{ + INT32 locvar1 = var1; + mobj_t *ghost; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_GhostMe", actor)) + return; +#endif + ghost = P_SpawnGhostMobj(actor); + if (ghost && locvar1 > 0) + ghost->fuse = locvar1; +} + +// Function: A_SetObjectState +// +// Description: Changes the state of an object's target/tracer. +// +// var1 = state number +// var2: +// 0 = target +// 1 = tracer +// +void A_SetObjectState(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *target; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetObjectState", actor)) + return; +#endif + + if ((!locvar2 && !actor->target) || (locvar2 && !actor->tracer)) + { + if (cv_debug) + CONS_Printf("A_SetObjectState: No target to change state!\n"); + return; + } + + if (!locvar2) // target + target = actor->target; + else // tracer + target = actor->tracer; + + if (target->health > 0) + { + if (!target->player) + P_SetMobjState(target, locvar1); + else + P_SetPlayerMobjState(target, locvar1); + } +} + +// Function: A_SetObjectTypeState +// +// Description: Changes the state of all active objects of a certain type in a certain range of the actor. +// +// var1 = state number +// var2: +// lower 16 bits = type +// upper 16 bits = range (if == 0, across whole map) +// +void A_SetObjectTypeState(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + const UINT16 loc2lw = (UINT16)(locvar2 & 65535); + const UINT16 loc2up = (UINT16)(locvar2 >> 16); + + thinker_t *th; + mobj_t *mo2; + fixed_t dist = 0; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetObjectTypeState", actor)) + return; +#endif + + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type == (mobjtype_t)loc2lw) + { + dist = P_AproxDistance(mo2->x - actor->x, mo2->y - actor->y); + + if (mo2->health > 0) + { + if (loc2up == 0) + P_SetMobjState(mo2, locvar1); + else + { + if (dist <= FixedMul(loc2up*FRACUNIT, actor->scale)) + P_SetMobjState(mo2, locvar1); + } + } + } + } +} + +// Function: A_KnockBack +// +// Description: Knocks back the object's target at its current speed. +// +// var1: +// 0 = target +// 1 = tracer +// var2 = unused +// +void A_KnockBack(mobj_t *actor) +{ + INT32 locvar1 = var1; + mobj_t *target; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_KnockBack", actor)) + return; +#endif + + if (!locvar1) + target = actor->target; + else + target = actor->tracer; + + if (!target) + { + if(cv_debug) + CONS_Printf("A_KnockBack: No target!\n"); + return; + } + + target->momx *= -1; + target->momy *= -1; +} + +// Function: A_PushAway +// +// Description: Pushes an object's target away from the calling object. +// +// var1 = amount of force +// var2: +// lower 16 bits = If 1, xy momentum is lost. If 0, xy momentum is kept +// upper 16 bits = 0 - target, 1 - tracer +// +void A_PushAway(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *target; // target + angle_t an; // actor to target angle +#ifdef HAVE_BLUA + if (LUA_CallAction("A_PushAway", actor)) + return; +#endif + + if ((!(locvar2 >> 16) && !actor->target) || ((locvar2 >> 16) && !actor->tracer)) + return; + + if (!locvar1) + CONS_Printf("A_Thrust: Var1 not specified!\n"); + + if (!(locvar2 >> 16)) // target + target = actor->target; + else // tracer + target = actor->tracer; + + an = R_PointToAngle2(actor->x, actor->y, target->x, target->y); + + if (locvar2 & 65535) + P_InstaThrust(target, an, FixedMul(locvar1*FRACUNIT, actor->scale)); + else + P_Thrust(target, an, FixedMul(locvar1*FRACUNIT, actor->scale)); +} + +// Function: A_RingDrain +// +// Description: Drain targeted player's rings. +// +// var1 = ammount of drained rings +// var2 = unused +// +void A_RingDrain(mobj_t *actor) +{ + INT32 locvar1 = var1; + player_t *player; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RingDrain", actor)) + return; +#endif + + if (!actor->target || !actor->target->player) + { + if(cv_debug) + CONS_Printf("A_RingDrain: No player targeted!\n"); + return; + } + + player = actor->target->player; + P_GivePlayerRings(player, -min(locvar1, player->rings)); +} + +// Function: A_SplitShot +// +// Description: Shoots 2 missiles that hit next to the player. +// +// var1 = target x-y-offset +// var2: +// lower 16 bits = missile type +// upper 16 bits = height offset +// +void A_SplitShot(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + const UINT16 loc2lw = (UINT16)(locvar2 & 65535); + const UINT16 loc2up = (UINT16)(locvar2 >> 16); + const fixed_t offs = (fixed_t)(locvar1*FRACUNIT); + const fixed_t hoffs = (fixed_t)(loc2up*FRACUNIT); +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SplitShot", actor)) + return; +#endif + + A_FaceTarget(actor); + { + const angle_t an = (actor->angle + ANGLE_90) >> ANGLETOFINESHIFT; + const fixed_t fasin = FINESINE(an); + const fixed_t facos = FINECOSINE(an); + fixed_t xs = FixedMul(facos,FixedMul(offs, actor->scale)); + fixed_t ys = FixedMul(fasin,FixedMul(offs, actor->scale)); + fixed_t z; + + if (actor->eflags & MFE_VERTICALFLIP) + z = actor->z + actor->height - FixedMul(hoffs, actor->scale); + else + z = actor->z + FixedMul(hoffs, actor->scale); + + P_SpawnPointMissile(actor, actor->target->x+xs, actor->target->y+ys, actor->target->z, loc2lw, actor->x, actor->y, z); + P_SpawnPointMissile(actor, actor->target->x-xs, actor->target->y-ys, actor->target->z, loc2lw, actor->x, actor->y, z); + } +} + +// Function: A_MissileSplit +// +// Description: If the object is a missile it will create a new missile with an alternate flight path owned by the one who shot the former missile. +// +// var1 = splitting missile type +// var2 = splitting angle +// +void A_MissileSplit(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_MissileSplit", actor)) + return; +#endif + if (actor->eflags & MFE_VERTICALFLIP) + P_SpawnAlteredDirectionMissile(actor, locvar1, actor->x, actor->y, actor->z+actor->height, locvar2); + else + P_SpawnAlteredDirectionMissile(actor, locvar1, actor->x, actor->y, actor->z, locvar2); +} + +// Function: A_MultiShot +// +// Description: Shoots objects horizontally that spread evenly in all directions. +// +// var1: +// lower 16 bits = number of missiles +// upper 16 bits = missile type # +// var2 = height offset +// +void A_MultiShot(mobj_t *actor) +{ + fixed_t z, xr, yr; + INT32 locvar1 = var1; + INT32 locvar2 = var2; + const UINT16 loc1lw = (UINT16)(locvar1 & 65535); + const UINT16 loc1up = (UINT16)(locvar1 >> 16); + INT32 count = 0; + fixed_t ad; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_MultiShot", actor)) + return; +#endif + + if (actor->target) + A_FaceTarget(actor); + + if(loc1lw > 90) + ad = FixedMul(90*FRACUNIT, actor->scale); + else + ad = FixedMul(loc1lw*FRACUNIT, actor->scale); + + if (actor->eflags & MFE_VERTICALFLIP) + z = actor->z + actor->height - FixedMul(48*FRACUNIT + locvar2*FRACUNIT, actor->scale); + else + z = actor->z + FixedMul(48*FRACUNIT + locvar2*FRACUNIT, actor->scale); + xr = FixedMul((P_SignedRandom()/3)<scale); // please note p_mobj.c's P_Rand() abuse + yr = FixedMul((P_SignedRandom()/3)<scale); // of rand(), RAND_MAX and signness mess + + while(count <= loc1lw && loc1lw >= 1) + { + const angle_t fa = FixedAngleC(count*FRACUNIT*360, ad)>>ANGLETOFINESHIFT; + const fixed_t rc = FINECOSINE(fa); + const fixed_t rs = FINESINE(fa); + const fixed_t xrc = FixedMul(xr, rc); + const fixed_t yrs = FixedMul(yr, rs); + const fixed_t xrs = FixedMul(xr, rs); + const fixed_t yrc = FixedMul(yr, rc); + + P_SpawnPointMissile(actor, xrc-yrs+actor->x, xrs+yrc+actor->y, z, loc1up, actor->x, actor->y, z); + count++; + } + + if (!(actor->flags & MF_BOSS)) + { + if (ultimatemode) + actor->reactiontime = actor->info->reactiontime*TICRATE; + else + actor->reactiontime = actor->info->reactiontime*TICRATE*2; + } +} + +// Function: A_InstaLoop +// +// Description: Makes the object move along a 2d (view angle, z) polygon. +// +// var1: +// lower 16 bits = current step +// upper 16 bits = maximum step # +// var2 = force +// +void A_InstaLoop(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + fixed_t force = max(locvar2, 1)*FRACUNIT; // defaults to 1 if var2 < 1 + const UINT16 loc1lw = (UINT16)(locvar1 & 65535); + const UINT16 loc1up = (UINT16)(locvar1 >> 16); + const angle_t fa = FixedAngleC(loc1lw*FRACUNIT*360, loc1up*FRACUNIT)>>ANGLETOFINESHIFT; + const fixed_t ac = FINECOSINE(fa); + const fixed_t as = FINESINE(fa); +#ifdef HAVE_BLUA + if (LUA_CallAction("A_InstaLoop", actor)) + return; +#endif + + P_InstaThrust(actor, actor->angle, FixedMul(ac, FixedMul(force, actor->scale))); + P_SetObjectMomZ(actor, FixedMul(as, force), false); +} + +// Function: A_Custom3DRotate +// +// Description: Rotates the actor around its target in 3 dimensions. +// +// var1: +// lower 16 bits = radius in fracunits +// upper 16 bits = vertical offset +// var2: +// lower 16 bits = vertical rotation speed in 1/10 fracunits per tic +// upper 16 bits = horizontal rotation speed in 1/10 fracunits per tic +// +void A_Custom3DRotate(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + const UINT16 loc1lw = (UINT16)(locvar1 & 65535); + const UINT16 loc1up = (UINT16)(locvar1 >> 16); + const UINT16 loc2lw = (UINT16)(locvar2 & 65535); + const UINT16 loc2up = (UINT16)(locvar2 >> 16); + + const fixed_t radius = FixedMul(loc1lw*FRACUNIT, actor->scale); + const fixed_t hOff = FixedMul(loc1up*FRACUNIT, actor->scale); + const fixed_t hspeed = FixedMul(loc2up*FRACUNIT/10, actor->scale); + const fixed_t vspeed = FixedMul(loc2lw*FRACUNIT/10, actor->scale); +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Custom3DRotate", actor)) + return; +#endif + + if (actor->target->health == 0) + { + P_RemoveMobj(actor); + return; + } + + if (!actor->target) // This should NEVER happen. + { + if (cv_debug) + CONS_Printf("Error: Object has no target\n"); + P_RemoveMobj(actor); + return; + } + if (hspeed==0 && vspeed==0) + { + CONS_Printf("Error: A_Custom3DRotate: Object has no speed.\n"); + return; + } + + actor->angle += FixedAngle(hspeed); + actor->movedir += FixedAngle(vspeed); + P_UnsetThingPosition(actor); + { + const angle_t fa = actor->angle>>ANGLETOFINESHIFT; + + if (vspeed == 0 && hspeed != 0) + { + actor->x = actor->target->x + FixedMul(FINECOSINE(fa),radius); + actor->y = actor->target->y + FixedMul(FINESINE(fa),radius); + actor->z = actor->target->z + actor->target->height/2 - actor->height/2 + hOff; + } + else + { + const angle_t md = actor->movedir>>ANGLETOFINESHIFT; + actor->x = actor->target->x + FixedMul(FixedMul(FINESINE(md),FINECOSINE(fa)),radius); + actor->y = actor->target->y + FixedMul(FixedMul(FINESINE(md),FINESINE(fa)),radius); + actor->z = actor->target->z + FixedMul(FINECOSINE(md),radius) + actor->target->height/2 - actor->height/2 + hOff; + } + } + P_SetThingPosition(actor); +} + +// Function: A_SearchForPlayers +// +// Description: Checks if the actor has targeted a vulnerable player. If not a new player will be searched all around. If no players are available the object can call a specific state. (Useful for not moving enemies) +// +// var1: +// if var1 == 0, if necessary call state with same state number as var2 +// else, do not call a specific state if no players are available +// var2 = state number +// +void A_SearchForPlayers(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SearchForPlayers", actor)) + return; +#endif + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { + // look for a new target + if (P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + if(locvar1==0) + { + P_SetMobjStateNF(actor, locvar2); + return; + } + } +} + +// Function: A_CheckRandom +// +// Description: Calls a state by chance. +// +// var1: +// lower 16 bits = denominator +// upper 16 bits = numerator (defaults to 1 if zero) +// var2 = state number +// +void A_CheckRandom(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + fixed_t chance = FRACUNIT; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckRandom", actor)) + return; +#endif + if ((locvar1 & 0xFFFF) == 0) + return; + + // The PRNG doesn't suck anymore, OK? + if (locvar1 >> 16) + chance *= (locvar1 >> 16); + chance /= (locvar1 & 0xFFFF); + + if (P_RandomChance(chance)) + P_SetMobjState(actor, locvar2); +} + +// Function: A_CheckTargetRings +// +// Description: Calls a state depending on the ammount of rings currently owned by targeted players. +// +// var1 = if player rings >= var1 call state +// var2 = state number +// +void A_CheckTargetRings(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckTargetRings", actor)) + return; +#endif + + if (!(actor->target) || !(actor->target->player)) + return; + + if (actor->target->player->rings >= locvar1) + P_SetMobjState(actor, locvar2); +} + +// Function: A_CheckRings +// +// Description: Calls a state depending on the ammount of rings currently owned by all players. +// +// var1 = if player rings >= var1 call state +// var2 = state number +// +void A_CheckRings(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + INT32 i, cntr = 0; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckRings", actor)) + return; +#endif + + for (i = 0; i < MAXPLAYERS; i++) + cntr += players[i].rings; + + if (cntr >= locvar1) + P_SetMobjState(actor, locvar2); +} + +// Function: A_CheckTotalRings +// +// Description: Calls a state depending on the maximum ammount of rings owned by all players during this try. +// +// var1 = if total player rings >= var1 call state +// var2 = state number +// +void A_CheckTotalRings(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + INT32 i, cntr = 0; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckTotalRings", actor)) + return; +#endif + + for (i = 0; i < MAXPLAYERS; i++) + cntr += players[i].totalring; + + if (cntr >= locvar1) + P_SetMobjState(actor, locvar2); +} + +// Function: A_CheckHealth +// +// Description: Calls a state depending on the object's current health. +// +// var1 = if health <= var1 call state +// var2 = state number +// +void A_CheckHealth(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckHealth", actor)) + return; +#endif + + if (actor->health <= locvar1) + P_SetMobjState(actor, locvar2); +} + +// Function: A_CheckRange +// +// Description: Calls a state if the object's target is in range. +// +// var1: +// lower 16 bits = range +// upper 16 bits = 0 - target, 1 - tracer +// var2 = state number +// +void A_CheckRange(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + fixed_t dist; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckRange", actor)) + return; +#endif + + if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer)) + return; + + if (!(locvar1 >> 16)) //target + dist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); + else //tracer + dist = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y); + + if (dist <= FixedMul((locvar1 & 65535)*FRACUNIT, actor->scale)) + P_SetMobjState(actor, locvar2); +} + +// Function: A_CheckHeight +// +// Description: Calls a state if the object and it's target have a height offset <= var1 compared to each other. +// +// var1: +// lower 16 bits = height offset +// upper 16 bits = 0 - target, 1 - tracer +// var2 = state number +// +void A_CheckHeight(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + fixed_t height; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckHeight", actor)) + return; +#endif + + if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer)) + return; + + if (!(locvar1 >> 16)) // target + height = abs(actor->target->z - actor->z); + else // tracer + height = abs(actor->tracer->z - actor->z); + + if (height <= FixedMul((locvar1 & 65535)*FRACUNIT, actor->scale)) + P_SetMobjState(actor, locvar2); +} + +// Function: A_CheckTrueRange +// +// Description: Calls a state if the object's target is in true range. (Checks height, too.) +// +// var1: +// lower 16 bits = range +// upper 16 bits = 0 - target, 1 - tracer +// var2 = state number +// +void A_CheckTrueRange(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + fixed_t height; // vertical range + fixed_t dist; // horizontal range + fixed_t l; // true range +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckTrueRange", actor)) + return; +#endif + + if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer)) + return; + + if (!(locvar1 >> 16)) // target + { + height = actor->target->z - actor->z; + dist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); + + } + else // tracer + { + height = actor->tracer->z - actor->z; + dist = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y); + } + + l = P_AproxDistance(dist, height); + + if (l <= FixedMul((locvar1 & 65535)*FRACUNIT, actor->scale)) + P_SetMobjState(actor, locvar2); + +} + +// Function: A_CheckThingCount +// +// Description: Calls a state depending on the number of active things in range. +// +// var1: +// lower 16 bits = number of things +// upper 16 bits = thing type +// var2: +// lower 16 bits = state to call +// upper 16 bits = range (if == 0, check whole map) +// +void A_CheckThingCount(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + const UINT16 loc1lw = (UINT16)(locvar1 & 65535); + const UINT16 loc1up = (UINT16)(locvar1 >> 16); + const UINT16 loc2lw = (UINT16)(locvar2 & 65535); + const UINT16 loc2up = (UINT16)(locvar2 >> 16); + + INT32 count = 0; + thinker_t *th; + mobj_t *mo2; + fixed_t dist = 0; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckThingCount", actor)) + return; +#endif + + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type == (mobjtype_t)loc1up) + { + dist = P_AproxDistance(mo2->x - actor->x, mo2->y - actor->y); + + if (loc2up == 0) + count++; + else + { + if (dist <= FixedMul(loc2up*FRACUNIT, actor->scale)) + count++; + } + } + } + + if(loc1lw <= count) + P_SetMobjState(actor, loc2lw); +} + +// Function: A_CheckAmbush +// +// Description: Calls a state if the actor is behind its targeted player. +// +// var1: +// 0 = target +// 1 = tracer +// var2 = state number +// +void A_CheckAmbush(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + angle_t at; // angle target is currently facing + angle_t atp; // actor to target angle + angle_t an; // angle between at and atp + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckAmbush", actor)) + return; +#endif + + if ((!locvar1 && !actor->target) || (locvar1 && !actor->tracer)) + return; + + if (!locvar1) // target + { + at = actor->target->angle; + atp = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + } + else // tracer + { + at = actor->tracer->angle; + atp = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); + } + + an = atp - at; + + if (an > ANGLE_180) // flip angle if bigger than 180 + an = InvAngle(an); + + if (an < ANGLE_90+ANGLE_22h) // within an angle of 112.5 from each other? + P_SetMobjState(actor, locvar2); +} + +// Function: A_CheckCustomValue +// +// Description: Calls a state depending on the object's custom value. +// +// var1 = if custom value >= var1, call state +// var2 = state number +// +void A_CheckCustomValue(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckCustomValue", actor)) + return; +#endif + + if (actor->cusval >= locvar1) + P_SetMobjState(actor, locvar2); +} + +// Function: A_CheckCusValMemo +// +// Description: Calls a state depending on the object's custom memory value. +// +// var1 = if memory value >= var1, call state +// var2 = state number +// +void A_CheckCusValMemo(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckCusValMemo", actor)) + return; +#endif + + if (actor->cvmem >= locvar1) + P_SetMobjState(actor, locvar2); +} + +// Function: A_SetCustomValue +// +// Description: Changes the custom value of an object. +// +// var1 = manipulating value +// var2: +// if var2 == 5, multiply the custom value by var1 +// else if var2 == 4, divide the custom value by var1 +// else if var2 == 3, apply modulo var1 to the custom value +// else if var2 == 2, add var1 to the custom value +// else if var2 == 1, substract var1 from the custom value +// else if var2 == 0, replace the custom value with var1 +// +void A_SetCustomValue(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetCustomValue", actor)) + return; +#endif + + if (cv_debug) + CONS_Printf("Init custom value is %d\n", actor->cusval); + + if (locvar1 == 0 && locvar2 == 4) + return; // DON'T DIVIDE BY ZERO + + // no need for a "temp" value here, just modify the cusval directly + if (locvar2 == 5) // multiply + actor->cusval *= locvar1; + else if (locvar2 == 4) // divide + actor->cusval /= locvar1; + else if (locvar2 == 3) // modulo + actor->cusval %= locvar1; + else if (locvar2 == 2) // add + actor->cusval += locvar1; + else if (locvar2 == 1) // subtract + actor->cusval -= locvar1; + else // replace + actor->cusval = locvar1; + + if(cv_debug) + CONS_Printf("New custom value is %d\n", actor->cusval); +} + +// Function: A_UseCusValMemo +// +// Description: Memorizes or recalls a current custom value. +// +// var1: +// if var1 == 1, manipulate memory value +// else, recall memory value replacing the custom value +// var2: +// if var2 == 5, mem = mem*cv || cv = cv*mem +// else if var2 == 4, mem = mem/cv || cv = cv/mem +// else if var2 == 3, mem = mem%cv || cv = cv%mem +// else if var2 == 2, mem += cv || cv += mem +// else if var2 == 1, mem -= cv || cv -= mem +// else mem = cv || cv = mem +// +void A_UseCusValMemo(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + INT32 temp = actor->cusval; // value being manipulated + INT32 tempM = actor->cvmem; // value used to manipulate temp with +#ifdef HAVE_BLUA + if (LUA_CallAction("A_UseCusValMemo", actor)) + return; +#endif + + if (locvar1 == 1) // cvmem being changed using cusval + { + temp = actor->cvmem; + tempM = actor->cusval; + } + else // cusval being changed with cvmem + { + temp = actor->cusval; + tempM = actor->cvmem; + } + + if (tempM == 0 && locvar2 == 4) + return; // DON'T DIVIDE BY ZERO + + // now get new value for cusval/cvmem using the other + if (locvar2 == 5) // multiply + temp *= tempM; + else if (locvar2 == 4) // divide + temp /= tempM; + else if (locvar2 == 3) // modulo + temp %= tempM; + else if (locvar2 == 2) // add + temp += tempM; + else if (locvar2 == 1) // subtract + temp -= tempM; + else // replace + temp = tempM; + + // finally, give cusval/cvmem the new value! + if (locvar1 == 1) + actor->cvmem = temp; + else + actor->cusval = temp; +} + +// Function: A_RelayCustomValue +// +// Description: Manipulates the custom value of the object's target/tracer. +// +// var1: +// lower 16 bits: +// if var1 == 0, use own custom value +// else, use var1 value +// upper 16 bits = 0 - target, 1 - tracer +// var2: +// if var2 == 5, multiply the target's custom value by var1 +// else if var2 == 4, divide the target's custom value by var1 +// else if var2 == 3, apply modulo var1 to the target's custom value +// else if var2 == 2, add var1 to the target's custom value +// else if var2 == 1, substract var1 from the target's custom value +// else if var2 == 0, replace the target's custom value with var1 +// +void A_RelayCustomValue(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + INT32 temp; // reference value - var1 lower 16 bits changes this + INT32 tempT; // target's value - changed to tracer if var1 upper 16 bits set, then modified to become final value +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RelayCustomValue", actor)) + return; +#endif + + if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer)) + return; + + // reference custom value + if ((locvar1 & 65535) == 0) + temp = actor->cusval; // your own custom value + else + temp = (locvar1 & 65535); // var1 value + + if (!(locvar1 >> 16)) // target's custom value + tempT = actor->target->cusval; + else // tracer's custom value + tempT = actor->tracer->cusval; + + if (temp == 0 && locvar2 == 4) + return; // DON'T DIVIDE BY ZERO + + // now get new cusval using target's and the reference + if (locvar2 == 5) // multiply + tempT *= temp; + else if (locvar2 == 4) // divide + tempT /= temp; + else if (locvar2 == 3) // modulo + tempT %= temp; + else if (locvar2 == 2) // add + tempT += temp; + else if (locvar2 == 1) // subtract + tempT -= temp; + else // replace + tempT = temp; + + // finally, give target/tracer the new cusval! + if (!(locvar1 >> 16)) // target + actor->target->cusval = tempT; + else // tracer + actor->tracer->cusval = tempT; +} + +// Function: A_CusValAction +// +// Description: Calls an action from a reference state applying custom value parameters. +// +// var1 = state # to use action from +// var2: +// if var2 == 5, only replace new action's var2 with memory value +// else if var2 == 4, only replace new action's var1 with memory value +// else if var2 == 3, replace new action's var2 with custom value and var1 with memory value +// else if var2 == 2, replace new action's var1 with custom value and var2 with memory value +// else if var2 == 1, only replace new action's var2 with custom value +// else if var2 == 0, only replace new action's var1 with custom value +// +void A_CusValAction(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CusValAction", actor)) + return; +#endif + + if (locvar2 == 5) + { + var1 = states[locvar1].var1; + var2 = (INT32)actor->cvmem; + } + else if (locvar2 == 4) + { + var1 = (INT32)actor->cvmem; + var2 = states[locvar1].var2; + } + else if (locvar2 == 3) + { + var1 = (INT32)actor->cvmem; + var2 = (INT32)actor->cusval; + } + else if (locvar2 == 2) + { + var1 = (INT32)actor->cusval; + var2 = (INT32)actor->cvmem; + } + else if (locvar2 == 1) + { + var1 = states[locvar1].var1; + var2 = (INT32)actor->cusval; + } + else + { + var1 = (INT32)actor->cusval; + var2 = states[locvar1].var2; + } + +#ifdef HAVE_BLUA + astate = &states[locvar1]; +#endif + states[locvar1].action.acp1(actor); +} + +// Function: A_ForceStop +// +// Description: Actor immediately stops its current movement. +// +// var1: +// if var1 == 0, stop x-y-z-movement +// else, stop x-y-movement only +// var2 = unused +// +void A_ForceStop(mobj_t *actor) +{ + INT32 locvar1 = var1; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_ForceStop", actor)) + return; +#endif + + actor->momx = actor->momy = 0; + if (locvar1 == 0) + actor->momz = 0; +} + +// Function: A_ForceWin +// +// Description: Makes all players win the level. +// +// var1 = unused +// var2 = unused +// +void A_ForceWin(mobj_t *actor) +{ + INT32 i; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_ForceWin", actor)) + return; +#else + (void)actor; +#endif + + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && ((players[i].mo && players[i].mo->health) + || ((netgame || multiplayer) && (players[i].lives || players[i].continues)))) + break; + } + + if (i == MAXPLAYERS) + return; + + for (i = 0; i < MAXPLAYERS; i++) + P_DoPlayerExit(&players[i]); +} + +// Function: A_SpikeRetract +// +// Description: Toggles actor solid flag. +// +// var1: +// if var1 == 0, actor no collide +// else, actor solid +// var2 = unused +// +void A_SpikeRetract(mobj_t *actor) +{ + INT32 locvar1 = var1; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SpikeRetract", actor)) + return; +#endif + + if (actor->flags & MF_NOBLOCKMAP) + return; + + if (locvar1 == 0) + { + actor->flags &= ~MF_SOLID; + actor->flags |= MF_NOCLIPTHING; + } + else + { + actor->flags |= MF_SOLID; + actor->flags &= ~MF_NOCLIPTHING; + } + if (actor->flags & MF_SOLID) + P_CheckPosition(actor, actor->x, actor->y); +} + +// Function: A_InfoState +// +// Description: Set mobj state to one predefined in mobjinfo. +// +// var1: +// if var1 == 0, set actor to spawnstate +// else if var1 == 1, set actor to seestate +// else if var1 == 2, set actor to meleestate +// else if var1 == 3, set actor to missilestate +// else if var1 == 4, set actor to deathstate +// else if var1 == 5, set actor to xdeathstate +// else if var1 == 6, set actor to raisestate +// var2 = unused +// +void A_InfoState(mobj_t *actor) +{ + INT32 locvar1 = var1; + switch (locvar1) + { + case 0: + if (actor->state != &states[actor->info->spawnstate]) + P_SetMobjState(actor, actor->info->spawnstate); + break; + case 1: + if (actor->state != &states[actor->info->seestate]) + P_SetMobjState(actor, actor->info->seestate); + break; + case 2: + if (actor->state != &states[actor->info->meleestate]) + P_SetMobjState(actor, actor->info->meleestate); + break; + case 3: + if (actor->state != &states[actor->info->missilestate]) + P_SetMobjState(actor, actor->info->missilestate); + break; + case 4: + if (actor->state != &states[actor->info->deathstate]) + P_SetMobjState(actor, actor->info->deathstate); + break; + case 5: + if (actor->state != &states[actor->info->xdeathstate]) + P_SetMobjState(actor, actor->info->xdeathstate); + break; + case 6: + if (actor->state != &states[actor->info->raisestate]) + P_SetMobjState(actor, actor->info->raisestate); + break; + default: + break; + } +} + +// Function: A_Repeat +// +// Description: Returns to state var2 until animation has been used var1 times, then continues to nextstate. +// +// var1 = repeat count +// var2 = state to return to if extravalue2 > 0 +// +void A_Repeat(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Repeat", actor)) + return; +#endif + + if (locvar1 && (!actor->extravalue2 || actor->extravalue2 > locvar1)) + actor->extravalue2 = locvar1; + + if (--actor->extravalue2 > 0) + P_SetMobjState(actor, locvar2); +} + +// Function: A_SetScale +// +// Description: Changes the scale of the actor or its target/tracer +// +// var1 = new scale (1*FRACUNIT = 100%) +// var2: +// upper 16 bits: 0 = actor, 1 = target, 2 = tracer +// lower 16 bits: 0 = instant change, 1 = smooth change +// +void A_SetScale(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *target; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetScale", actor)) + return; +#endif + + if (locvar1 <= 0) + { + if(cv_debug) + CONS_Printf("A_SetScale: Valid scale not specified!\n"); + return; + } + + if ((locvar2>>16) == 1) + target = actor->target; + else if ((locvar2>>16) == 2) + target = actor->tracer; + else // default to yourself! + target = actor; + + if (!target) + { + if(cv_debug) + CONS_Printf("A_SetScale: No target!\n"); + return; + } + + target->destscale = locvar1; // destination scale + if (!(locvar2 & 65535)) + P_SetScale(target, locvar1); // this instantly changes current scale to var1 if used, if not destscale will alter scale to var1 anyway +} + +// Function: A_RemoteDamage +// +// Description: Damages, kills or even removes either the actor or its target/tracer. Actor acts as the inflictor/source unless harming itself +// +// var1 = Mobj affected: 0 - actor, 1 - target, 2 - tracer +// var2 = Action: 0 - Damage, 1 - Kill, 2 - Remove +// +void A_RemoteDamage(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *target; // we MUST have a target + mobj_t *source = NULL; // on the other hand we don't necessarily need a source +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RemoteDamage", actor)) + return; +#endif + if (locvar1 == 1) + target = actor->target; + else if (locvar1 == 2) + target = actor->tracer; + else // default to yourself! + target = actor; + + if (locvar1 == 1 || locvar1 == 2) + source = actor; + + if (!target) + { + if(cv_debug) + CONS_Printf("A_RemoteDamage: No target!\n"); + return; + } + + if (locvar2 == 1) // Kill mobj! + { + if (target->player) // players die using P_DamageMobj instead for some reason + P_DamageMobj(target, source, source, 1, DMG_INSTAKILL); + else + P_KillMobj(target, source, source, 0); + } + else if (locvar2 == 2) // Remove mobj! + { + if (target->player) //don't remove players! + return; + + P_RemoveMobj(target); + } + else // default: Damage mobj! + P_DamageMobj(target, source, source, 1, 0); +} + +// Function: A_HomingChase +// +// Description: Actor chases directly towards its destination object +// +// var1 = speed multiple +// var2 = destination: 0 = target, 1 = tracer +// +void A_HomingChase(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *dest; + fixed_t dist; + fixed_t speedmul; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_HomingChase", actor)) + return; +#endif + + if (locvar2 == 1) + dest = actor->tracer; + else //default + dest = actor->target; + + if (!dest || !dest->health) + return; + + actor->angle = R_PointToAngle2(actor->x, actor->y, dest->x, dest->y); + + dist = P_AproxDistance(P_AproxDistance(dest->x - actor->x, dest->y - actor->y), dest->z - actor->z); + + if (dist < 1) + dist = 1; + + speedmul = FixedMul(locvar1, actor->scale); + + actor->momx = FixedMul(FixedDiv(dest->x - actor->x, dist), speedmul); + actor->momy = FixedMul(FixedDiv(dest->y - actor->y, dist), speedmul); + actor->momz = FixedMul(FixedDiv(dest->z - actor->z, dist), speedmul); +} + +// Function: A_TrapShot +// +// Description: Fires a missile in a particular direction and angle rather than AT something, Trapgoyle-style! +// +// var1: +// lower 16 bits = object # to fire +// upper 16 bits = front offset +// var2: +// lower 15 bits = vertical angle variable +// 16th bit: +// - 0: use vertical angle variable as vertical angle in degrees +// - 1: mimic P_SpawnXYZMissile +// use z of actor minus z of missile as vertical distance to cover during momz calculation +// use vertical angle variable as horizontal distance to cover during momz calculation +// upper 16 bits = height offset +// +void A_TrapShot(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + boolean oldstyle = (locvar2 & 32768) ? true : false; + mobjtype_t type = (mobjtype_t)(locvar1 & 65535); + mobj_t *missile; + INT16 frontoff = (INT16)(locvar1 >> 16); + INT16 vertoff = (INT16)(locvar2 >> 16); + fixed_t x, y, z; + fixed_t speed; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_TrapShot", actor)) + return; +#endif + + x = actor->x + P_ReturnThrustX(actor, actor->angle, FixedMul(frontoff*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle, FixedMul(frontoff*FRACUNIT, actor->scale)); + + if (actor->eflags & MFE_VERTICALFLIP) + z = actor->z + actor->height - FixedMul(vertoff*FRACUNIT, actor->scale) - FixedMul(mobjinfo[type].height, actor->scale); + else + z = actor->z + FixedMul(vertoff*FRACUNIT, actor->scale); + + CONS_Debug(DBG_GAMELOGIC, "A_TrapShot: missile no. = %d, front offset = %d, vertical angle = %d, z offset = %d\n", + type, frontoff, (INT16)(locvar2 & 65535), vertoff); + + missile = P_SpawnMobj(x, y, z, type); + + if (actor->eflags & MFE_VERTICALFLIP) + missile->flags2 |= MF2_OBJECTFLIP; + + missile->destscale = actor->scale; + P_SetScale(missile, actor->scale); + + if (missile->info->seesound) + S_StartSound(missile, missile->info->seesound); + + P_SetTarget(&missile->target, actor); + missile->angle = actor->angle; + + speed = FixedMul(missile->info->speed, missile->scale); + + if (oldstyle) + { + missile->momx = FixedMul(FINECOSINE(missile->angle>>ANGLETOFINESHIFT), speed); + missile->momy = FixedMul(FINESINE(missile->angle>>ANGLETOFINESHIFT), speed); + // The below line basically mimics P_SpawnXYZMissile's momz calculation. + missile->momz = (actor->z + ((actor->eflags & MFE_VERTICALFLIP) ? actor->height : 0) - z) / ((fixed_t)(locvar2 & 32767)*FRACUNIT / speed); + P_CheckMissileSpawn(missile); + } + else + { + angle_t vertang = FixedAngle(((INT16)(locvar2 & 32767))*FRACUNIT); + if (actor->eflags & MFE_VERTICALFLIP) + vertang = InvAngle(vertang); // flip firing angle + missile->momx = FixedMul(FINECOSINE(vertang>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(missile->angle>>ANGLETOFINESHIFT), speed)); + missile->momy = FixedMul(FINECOSINE(vertang>>ANGLETOFINESHIFT), FixedMul(FINESINE(missile->angle>>ANGLETOFINESHIFT), speed)); + missile->momz = FixedMul(FINESINE(vertang>>ANGLETOFINESHIFT), speed); + } +} + +// Function: A_VileTarget +// +// Description: Spawns an object directly on the target, and sets this object as the actor's tracer. +// Originally used by Archviles to summon a pillar of hellfire, hence the name. +// +// var1 = mobj to spawn +// var2 = If 0, target only the actor's target. Else, target every player, period. +// +void A_VileTarget(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *fog; + mobjtype_t fogtype; + INT32 i; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_VileTarget", actor)) + return; +#endif + + if (!actor->target) + return; + + A_FaceTarget(actor); + + // Determine object to spawn + if (locvar1 <= 0 || locvar1 >= NUMMOBJTYPES) + fogtype = MT_CYBRAKDEMON_TARGET_RETICULE; + else + fogtype = (mobjtype_t)locvar1; + + if (!locvar2) + { + fog = P_SpawnMobj(actor->target->x, + actor->target->y, + actor->target->z + ((actor->target->eflags & MFE_VERTICALFLIP) ? actor->target->height - mobjinfo[fogtype].height : 0), + fogtype); + if (actor->target->eflags & MFE_VERTICALFLIP) + { + fog->eflags |= MFE_VERTICALFLIP; + fog->flags2 |= MF2_OBJECTFLIP; + } + fog->destscale = actor->target->scale; + P_SetScale(fog, fog->destscale); + + P_SetTarget(&actor->tracer, fog); + P_SetTarget(&fog->target, actor); + P_SetTarget(&fog->tracer, actor->target); + A_VileFire(fog); + } + else + { + // Our "Archvile" here is actually Oprah. "YOU GET A TARGET! YOU GET A TARGET! YOU ALL GET A TARGET!" + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + + if (!players[i].mo) + continue; + + if (!players[i].mo->health) + continue; + + fog = P_SpawnMobj(players[i].mo->x, + players[i].mo->y, + players[i].mo->z + ((players[i].mo->eflags & MFE_VERTICALFLIP) ? players[i].mo->height - mobjinfo[fogtype].height : 0), + fogtype); + if (players[i].mo->eflags & MFE_VERTICALFLIP) + { + fog->eflags |= MFE_VERTICALFLIP; + fog->flags2 |= MF2_OBJECTFLIP; + } + fog->destscale = players[i].mo->scale; + P_SetScale(fog, fog->destscale); + + if (players[i].mo == actor->target) // We only care to track the fog targeting who we REALLY hate right now + P_SetTarget(&actor->tracer, fog); + P_SetTarget(&fog->target, actor); + P_SetTarget(&fog->tracer, players[i].mo); + A_VileFire(fog); + } + } +} + +// Function: A_VileAttack +// +// Description: Instantly hurts the actor's target, if it's in the actor's line of sight. +// Originally used by Archviles to cause explosions where their hellfire pillars were, hence the name. +// +// var1 = sound to play +// var2: +// Lower 16 bits = optional explosion object +// Upper 16 bits = If 0, attack only the actor's target. Else, attack all the players. All of them. +// +void A_VileAttack(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + sfxenum_t soundtoplay; + mobjtype_t explosionType = MT_NULL; + mobj_t *fire; + INT32 i; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_VileAttack", actor)) + return; +#endif + + if (!actor->target) + return; + + A_FaceTarget(actor); + + if (locvar1 <= 0 || locvar1 >= NUMSFX) + soundtoplay = sfx_brakrx; + else + soundtoplay = (sfxenum_t)locvar1; + + if ((locvar2 & 0xFFFF) > 0 && (locvar2 & 0xFFFF) <= NUMMOBJTYPES) + { + explosionType = (mobjtype_t)(locvar2 & 0xFFFF); + } + + if (!(locvar2 & 0xFFFF0000)) { + if (!P_CheckSight(actor, actor->target)) + return; + + S_StartSound(actor, soundtoplay); + P_DamageMobj(actor->target, actor, actor, 1, 0); + //actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; // How id did it + actor->target->momz += FixedMul(10*FRACUNIT, actor->scale)*P_MobjFlip(actor->target); // How we're doing it + if (explosionType != MT_NULL) + { + P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, explosionType); + } + + // Extra attack. This was for additional damage in Doom. Doesn't really belong in SRB2, but the heck with it, it's here anyway. + fire = actor->tracer; + + if (!fire) + return; + + // move the fire between the vile and the player + //fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]); + //fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]); + P_TeleportMove(fire, + actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), + actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), + fire->z); + P_RadiusAttack(fire, actor, 70*FRACUNIT, 0); + } + else + { + // Oprahvile strikes again, but this time, she brings HOT PAIN + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + + if (!players[i].mo) + continue; + + if (!players[i].mo->health) + continue; + + if (!P_CheckSight(actor, players[i].mo)) + continue; + + S_StartSound(actor, soundtoplay); + P_DamageMobj(players[i].mo, actor, actor, 1, 0); + //actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; // How id did it + players[i].mo->momz += FixedMul(10*FRACUNIT, actor->scale)*P_MobjFlip(players[i].mo); // How we're doing it + if (explosionType != MT_NULL) + { + P_SpawnMobj(players[i].mo->x, players[i].mo->y, players[i].mo->z, explosionType); + } + + // Extra attack. This was for additional damage in Doom. Doesn't really belong in SRB2, but the heck with it, it's here anyway. + // However, it ONLY applies to the actor's target. Nobody else matters! + if (actor->target != players[i].mo) + continue; + + fire = actor->tracer; + + if (!fire) + continue; + + // move the fire between the vile and the player + //fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]); + //fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]); + P_TeleportMove(fire, + actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), + actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), + fire->z); + P_RadiusAttack(fire, actor, 70*FRACUNIT, 0); + } + } + +} + +// Function: A_VileFire +// +// Description: Kind of like A_CapeChase; keeps this object in front of its tracer, unless its target can't see it. +// Originally used by Archviles to keep their hellfire pillars on top of the player, hence the name (although it was just "A_Fire" there; added "Vile" to make it more specific). +// Added some functionality to optionally draw a line directly to the enemy doing the targetting. Y'know, to hammer things in a bit. +// +// var1 = sound to play +// var2: +// Lower 16 bits = mobj to spawn (0 doesn't spawn a line at all) +// Upper 16 bits = # to spawn (default is 8) +// +void A_VileFire(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *dest; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_VileFire", actor)) + return; +#endif + + dest = actor->tracer; + if (!dest) + return; + + // don't move it if the vile lost sight + if (!P_CheckSight(actor->target, dest)) + return; + + // keep to same scale and gravity as tracer ALWAYS + actor->destscale = dest->scale; + P_SetScale(actor, actor->destscale); + if (dest->eflags & MFE_VERTICALFLIP) + { + actor->eflags |= MFE_VERTICALFLIP; + actor->flags2 |= MF2_OBJECTFLIP; + } + else + { + actor->eflags &= ~MFE_VERTICALFLIP; + actor->flags2 &= ~MF2_OBJECTFLIP; + } + + P_UnsetThingPosition(actor); + actor->x = dest->x + P_ReturnThrustX(actor, dest->angle, FixedMul(24*FRACUNIT, actor->scale)); + actor->y = dest->y + P_ReturnThrustY(actor, dest->angle, FixedMul(24*FRACUNIT, actor->scale)); + actor->z = dest->z + ((actor->eflags & MFE_VERTICALFLIP) ? dest->height-actor->height : 0); + P_SetThingPosition(actor); + + // Play sound, if one's specified + if (locvar1 > 0 && locvar1 < NUMSFX) + S_StartSound(actor, (sfxenum_t)locvar1); + + // Now draw the line to the actor's target + if (locvar2 & 0xFFFF) + { + mobjtype_t lineMobj; + UINT16 numLineMobjs; + fixed_t distX; + fixed_t distY; + fixed_t distZ; + UINT16 i; + + lineMobj = (mobjtype_t)(locvar2 & 0xFFFF); + numLineMobjs = (UINT16)(locvar2 >> 16); + if (numLineMobjs == 0) { + numLineMobjs = 8; + } + + // Get distance for each step + distX = (actor->target->x - actor->x) / numLineMobjs; + distY = (actor->target->y - actor->y) / numLineMobjs; + distZ = ((actor->target->z + FixedMul(actor->target->height/2, actor->target->scale)) - (actor->z + FixedMul(actor->height/2, actor->scale))) / numLineMobjs; + + for (i = 1; i <= numLineMobjs; i++) + { + P_SpawnMobj(actor->x + (distX * i), actor->y + (distY * i), actor->z + (distZ * i) + FixedMul(actor->height/2, actor->scale), lineMobj); + } + } +} + +// Function: A_BrakChase +// +// Description: Chase after your target, but speed and attack are tied to health. +// +// Every time this is called, generate a random number from a 1/4 to 3/4 of mobj's spawn health. +// If health is above that value, use missilestate to attack. +// If health is at or below that value, use meleestate to attack (default to missile state if not available). +// +// Likewise, state will linearly speed up as health goes down. +// Upper bound will be the frame's normal length. +// Lower bound defaults to 1 tic (technically 0, but we round up), unless a lower bound is specified in var1. +// +// var1 = lower-bound of frame length, in tics +// var2 = optional sound to play +// +void A_BrakChase(mobj_t *actor) +{ + INT32 delta; + INT32 lowerbound; + INT32 newtics; + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_BrakChase", actor)) + return; +#endif + + // Set new tics NOW, in case the state changes while we're doing this and we try applying this to the painstate or something silly + if (actor->tics > 1 && locvar1 < actor->tics) // Not much point, otherwise + { + if (locvar1 < 0) + lowerbound = 0; + else + lowerbound = locvar1; + + newtics = (((actor->tics - lowerbound) * actor->health) / actor->info->spawnhealth) + lowerbound; + if (newtics < 1) + newtics = 1; + + actor->tics = newtics; + } + + if (actor->reactiontime) + { + actor->reactiontime--; + if (actor->reactiontime == 0 && actor->type == MT_CYBRAKDEMON) + S_StartSound(0, sfx_bewar1 + P_RandomKey(4)); + } + + // modify target threshold + if (actor->threshold) + { + if (!actor->target || actor->target->health <= 0) + actor->threshold = 0; + else + actor->threshold--; + } + + // turn towards movement direction if not there yet + if (actor->movedir < NUMDIRS) + { + actor->angle &= (7<<29); + delta = actor->angle - (actor->movedir << 29); + + if (delta > 0) + actor->angle -= ANGLE_45; + else if (delta < 0) + actor->angle += ANGLE_45; + } + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { + // look for a new target + if (P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + P_SetMobjStateNF(actor, actor->info->spawnstate); + return; + } + + // do not attack twice in a row + if (actor->flags2 & MF2_JUSTATTACKED) + { + actor->flags2 &= ~MF2_JUSTATTACKED; + P_NewChaseDir(actor); + return; + } + + // Check if we can attack + if (P_CheckMissileRange(actor) && !actor->movecount) + { + // Check if we should use "melee" attack first. (Yes, this still runs outside of melee range. Quiet, you.) + if (actor->info->meleestate + && actor->health <= P_RandomRange(actor->info->spawnhealth/4, (actor->info->spawnhealth * 3)/4)) // Guaranteed true if <= 1/4 health, guaranteed false if > 3/4 health + { + if (actor->info->attacksound) + S_StartAttackSound(actor, actor->info->attacksound); + + P_SetMobjState(actor, actor->info->meleestate); + actor->flags2 |= MF2_JUSTATTACKED; + return; + } + // Else, check for missile attack. + else if (actor->info->missilestate) + { + P_SetMobjState(actor, actor->info->missilestate); + actor->flags2 |= MF2_JUSTATTACKED; + return; + } + } + + // possibly choose another target + if (multiplayer && !actor->threshold && (actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) + && P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + // chase towards player + if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) + P_NewChaseDir(actor); + + // Optionally play a sound effect + if (locvar2 > 0 && locvar2 < NUMSFX) + S_StartSound(actor, (sfxenum_t)locvar2); + + // make active sound + if (actor->type != MT_CYBRAKDEMON && actor->info->activesound && P_RandomChance(3*FRACUNIT/256)) + { + S_StartSound(actor, actor->info->activesound); + } +} + +// Function: A_BrakFireShot +// +// Description: Shoot an object at your target, offset to match where Brak's gun is. +// Also, sets Brak's reaction time; behaves normally otherwise. +// +// var1 = object # to shoot +// var2 = unused +// +void A_BrakFireShot(mobj_t *actor) +{ + fixed_t x, y, z; + INT32 locvar1 = var1; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_BrakFireShot", actor)) + return; +#endif + if (!actor->target) + return; + + A_FaceTarget(actor); + + x = actor->x + + P_ReturnThrustX(actor, actor->angle, FixedMul(64*FRACUNIT, actor->scale)) + + P_ReturnThrustX(actor, actor->angle+ANGLE_270, FixedMul(32*FRACUNIT, actor->scale)); + y = actor->y + + P_ReturnThrustY(actor, actor->angle, FixedMul(64*FRACUNIT, actor->scale)) + + P_ReturnThrustY(actor, actor->angle+ANGLE_270, FixedMul(32*FRACUNIT, actor->scale)); + if (actor->eflags & MFE_VERTICALFLIP) + z = actor->z + actor->height - FixedMul(144*FRACUNIT, actor->scale); + else + z = actor->z + FixedMul(144*FRACUNIT, actor->scale); + + P_SpawnXYZMissile(actor, actor->target, locvar1, x, y, z); + + if (!(actor->flags & MF_BOSS)) + { + if (ultimatemode) + actor->reactiontime = actor->info->reactiontime*TICRATE; + else + actor->reactiontime = actor->info->reactiontime*TICRATE*2; + } +} + +// Function: A_BrakLobShot +// +// Description: Lobs an object at the floor about a third of the way toward your target. +// Implication is it'll bounce the rest of the way. +// (You can also just aim straight at the target, but whatever) +// Formula grabbed from http://en.wikipedia.org/wiki/Trajectory_of_a_projectile#Angle_required_to_hit_coordinate_.28x.2Cy.29 +// +// var1 = object # to lob +// var2: +// Lower 16 bits: height offset to shoot from, from the actor's bottom (none that "airtime" malarky) +// Upper 16 bits: if 0, aim 1/3 of the way. Else, aim directly at target. +// + +void A_BrakLobShot(mobj_t *actor) +{ + fixed_t v; // Velocity to shoot object + fixed_t a1, a2, aToUse; // Velocity squared + fixed_t g; // Gravity + fixed_t x; // Horizontal difference + INT32 x_int; // x! But in integer form! + fixed_t y; // Vertical difference (yes that's normally z in SRB2 shut up) + INT32 y_int; // y! But in integer form! + INT32 intHypotenuse; // x^2 + y^2. Frequently overflows fixed point, hence why we need integers proper. + fixed_t fixedHypotenuse; // However, we can work around that and still get a fixed-point number. + angle_t theta; // Angle of attack + mobjtype_t typeOfShot; + mobj_t *shot; // Object to shoot + fixed_t newTargetX; // If not aiming directly + fixed_t newTargetY; // If not aiming directly + INT32 locvar1 = var1; + INT32 locvar2 = var2 & 0x0000FFFF; + INT32 aimDirect = var2 & 0xFFFF0000; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_BrakLobShot", actor)) + return; +#endif + + if (!actor->target) + return; // Don't even bother if we've got nothing to aim at. + + // Look up actor's current gravity situation + if (actor->subsector->sector->gravity) + g = FixedMul(gravity,(FixedDiv(*actor->subsector->sector->gravity>>FRACBITS, 1000))); + else + g = gravity; + + // Look up distance between actor and its target + x = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); + if (!aimDirect) + { + // Distance should actually be a third of the way over + x = FixedDiv(x, 3<x + P_ReturnThrustX(actor, actor->angle, x); + newTargetY = actor->y + P_ReturnThrustY(actor, actor->angle, x); + x = P_AproxDistance(newTargetX - actor->x, newTargetY - actor->y); + // Look up height difference between actor and the ground 1/3 of the way to its target + y = P_FloorzAtPos(newTargetX, newTargetY, actor->target->z, actor->target->height) - (actor->z + FixedMul(locvar2*FRACUNIT, actor->scale)); + } + else + { + // Look up height difference between actor and its target + y = actor->target->z - (actor->z + FixedMul(locvar2*FRACUNIT, actor->scale)); + } + + // Get x^2 + y^2. Have to do it in a roundabout manner, because this overflows fixed_t way too easily otherwise. + x_int = x>>FRACBITS; + y_int = y>>FRACBITS; + intHypotenuse = (x_int*x_int) + (y_int*y_int); + fixedHypotenuse = FixedSqrt(intHypotenuse) *256; + + // a = g(y+/-sqrt(x^2+y^2)). a1 can be +, a2 can be -. + a1 = FixedMul(g,y+fixedHypotenuse); + a2 = FixedMul(g,y-fixedHypotenuse); + + // Determine which one isn't actually an imaginary number (or the smaller of the two, if both are real), and use that for v. + if (a1 < 0 || a2 < 0) + { + if (a1 < 0 && a2 < 0) + { + //Somehow, v^2 is negative in both cases. v is therefore imaginary and something is horribly wrong. Abort! + return; + } + // Just find which one's NOT negative, and use that + aToUse = max(a1,a2); + } + else + { + // Both are positive; use whichever's smaller so it can decay faster + aToUse = min(a1,a2); + } + v = FixedSqrt(aToUse); + // Okay, so we know the velocity. Let's actually find theta. + // We can cut the "+/- sqrt" part out entirely, since v was calculated specifically for it to equal zero. So: + //theta = tantoangle[FixedDiv(aToUse,FixedMul(g,x)) >> DBITS]; + theta = tantoangle[SlopeDiv(aToUse,FixedMul(g,x))]; + + // Okay, complicated math done. Let's fire our object already, sheesh. + A_FaceTarget(actor); + if (locvar1 <= 0 || locvar1 >= NUMMOBJTYPES) + typeOfShot = MT_CANNONBALL; + else typeOfShot = (mobjtype_t)locvar1; + shot = P_SpawnMobj(actor->x, actor->y, actor->z + FixedMul(locvar2*FRACUNIT, actor->scale), typeOfShot); + if (shot->info->seesound) + S_StartSound(shot, shot->info->seesound); + P_SetTarget(&shot->target, actor); // where it came from + + shot->angle = actor->angle; + + // Horizontal axes first. First parameter is initial horizontal impulse, second is to correct its angle. + shot->momx = FixedMul(FixedMul(v, FINECOSINE(theta >> ANGLETOFINESHIFT)), FINECOSINE(shot->angle >> ANGLETOFINESHIFT)); + shot->momy = FixedMul(FixedMul(v, FINECOSINE(theta >> ANGLETOFINESHIFT)), FINESINE(shot->angle >> ANGLETOFINESHIFT)); + // Then the vertical axis. No angle-correction needed here. + shot->momz = FixedMul(v, FINESINE(theta >> ANGLETOFINESHIFT)); + // I hope that's all that's needed, ugh +} + +// Function: A_NapalmScatter +// +// Description: Scatters a specific number of projectiles around in a circle. +// Intended for use with objects that are affected by gravity; would be kind of silly otherwise. +// +// var1: +// Lower 16 bits: object # to lob (TODO: come up with a default) +// Upper 16 bits: Number to lob (default 8) +// var2: +// Lower 16 bits: distance to toss them (No default - 0 does just that - but negatives will revert to 128) +// Upper 16 bits: airtime in tics (default 16) +// +void A_NapalmScatter(mobj_t *actor) +{ + mobjtype_t typeOfShot = var1 & 0x0000FFFF; // Type + INT32 numToShoot = (var1 & 0xFFFF0000) >> 16; // How many + fixed_t distance = (var2 & 0x0000FFFF) << FRACBITS; // How far + fixed_t airtime = var2 & 0xFFFF0000; // How long until impact (assuming no obstacles) + fixed_t vx; // Horizontal momentum + fixed_t vy; // Vertical momentum + fixed_t g; // Gravity + INT32 i; // for-loop cursor + mobj_t *mo; // each and every spawned napalm burst + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_NapalmScatter", actor)) + return; +#endif + + // Some quick sanity-checking + if (typeOfShot >= NUMMOBJTYPES) // I'd add a <0 check, too, but 0x0000FFFF isn't negative in this case + typeOfShot = MT_NULL; + if (numToShoot <= 0) // Presumably you forgot to set var1 up; else, why are you calling this to shoot nothing? + numToShoot = 8; + else if (numToShoot > 8192) // If you seriously need this many objects spawned, stop and ask yourself "Why am I doing this?" + numToShoot = 8192; + if (distance < 0) // Presumably you thought this was an unsigned integer, you naive fool + distance = 32767<subsector->sector->gravity) + g = FixedMul(gravity,(FixedDiv(*actor->subsector->sector->gravity>>FRACBITS, 1000))); + else + g = gravity; + + // vy = (g*(airtime-1))/2 + vy = FixedMul(g,(airtime-(1<>1; + // vx = distance/airtime + vx = FixedDiv(distance, airtime); + + for (i = 0; ix, actor->y, actor->z, typeOfShot); + P_SetTarget(&mo->target, actor->target); // Transfer target so Brak doesn't hit himself like an idiot + + mo->angle = fa << ANGLETOFINESHIFT; + mo->momx = FixedMul(FINECOSINE(fa),vx); + mo->momy = FixedMul(FINESINE(fa),vx); + mo->momz = vy; + } +} + +// Function: A_SpawnFreshCopy +// +// Description: Spawns a copy of the mobj. x, y, z, angle, scale, target and tracer carry over; everything else starts anew. +// Mostly writing this because I want to do multiple actions to pass these along in a single frame instead of several. +// +// var1 = unused +// var2 = unused +// +void A_SpawnFreshCopy(mobj_t *actor) +{ + mobj_t *newObject; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SpawnFreshCopy", actor)) + return; +#endif + + newObject = P_SpawnMobjFromMobj(actor, 0, 0, 0, actor->type); + newObject->flags2 = actor->flags2 & MF2_AMBUSH; + newObject->angle = actor->angle; + newObject->color = actor->color; + P_SetTarget(&newObject->target, actor->target); + P_SetTarget(&newObject->tracer, actor->tracer); + + if (newObject->info->seesound) + S_StartSound(newObject, newObject->info->seesound); +} + +// Internal Flicky spawning function. +mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz, boolean lookforplayers) +{ + mobj_t *flicky; + + if (!flickytype) + { + if (!mapheaderinfo[gamemap-1] || !mapheaderinfo[gamemap-1]->numFlickies) // No mapheader, no shoes, no service. + return NULL; + else + { + INT32 prandom = P_RandomKey(mapheaderinfo[gamemap-1]->numFlickies); + flickytype = mapheaderinfo[gamemap-1]->flickies[prandom]; + } + } + + flicky = P_SpawnMobjFromMobj(actor, 0, 0, 0, flickytype); + flicky->angle = actor->angle; + + if (flickytype == MT_SEED) + flicky->z += P_MobjFlip(actor)*(actor->height - flicky->height)/2; + + if (actor->eflags & MFE_UNDERWATER) + momz = FixedDiv(momz, FixedSqrt(3*FRACUNIT)); + + P_SetObjectMomZ(flicky, momz, false); + flicky->movedir = (P_RandomChance(FRACUNIT/2) ? -1 : 1); + flicky->fuse = P_RandomRange(595, 700); // originally 300, 350 + flicky->threshold = 0; + + if (lookforplayers) + P_LookForPlayers(flicky, true, false, 0); + + return flicky; +} + +// Function: A_FlickySpawn +// +// Description: Flicky spawning function. +// +// var1: +// lower 16 bits: if 0, spawns random flicky based on level header. Else, spawns the designated thing type. +// upper 16 bits: if 0, no sound is played. Else, A_Scream is called. +// var2 = upwards thrust for spawned flicky. If zero, default value is provided. +// +void A_FlickySpawn(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickySpawn", actor)) + return; +#endif + + if (locvar1 >> 16) { + A_Scream(actor); // A shortcut for the truly lazy. + locvar1 &= 65535; + } + + P_InternalFlickySpawn(actor, locvar1, ((locvar2) ? locvar2 : 8*FRACUNIT), true); +} + +// Internal Flicky color setting +void P_InternalFlickySetColor(mobj_t *actor, UINT8 extrainfo) +{ + UINT8 flickycolors[] = { + SKINCOLOR_RED, + SKINCOLOR_CYAN, + SKINCOLOR_BLUE, + SKINCOLOR_VAPOR, + SKINCOLOR_PURPLE, + SKINCOLOR_BUBBLEGUM, + SKINCOLOR_NEON, + SKINCOLOR_BLACK, + SKINCOLOR_BEIGE, + SKINCOLOR_LAVENDER, + SKINCOLOR_RUBY, + SKINCOLOR_SALMON, + SKINCOLOR_SUNSET, + SKINCOLOR_ORANGE, + SKINCOLOR_YELLOW, + }; + + if (extrainfo == 0) + // until we can customize flicky colors by level header, just stick to SRB2's defaults + actor->color = flickycolors[P_RandomKey(2)]; //flickycolors[P_RandomKey(sizeof(flickycolors))]; + else + actor->color = flickycolors[min(extrainfo-1, 14)]; // sizeof(flickycolors)-1 +} + +// Function: A_FlickyCenter +// +// Description: Place flickies in-level. +// +// var1: +// Lower 16 bits = if 0, spawns random flicky based on level header. Else, spawns the designated thing type. +// Bits 17-20 = Flicky color, up to 15. Applies to fish. +// Bit 21 = Flag MF_SLIDEME (see below) +// Bit 22 = Flag MF_GRENADEBOUNCE (see below) +// Bit 23 = Flag MF_NOCLIPTHING (see below) +// +// If actor is placed from a spawnpoint (map Thing), the Thing's properties take precedence. +// +// var2 = maximum default distance away from spawn the flickies are allowed to travel. If angle != 0, then that's the radius. +// +// If MTF_EXTRA (MF_SLIDEME): is flagged, Flickies move aimlessly. Else, orbit around the target. +// If MTF_OBJECTSPECIAL (MF_GRENADEBOUNCE): Flickies stand in-place without gravity (unless they hop, then gravity is applied.) +// If MTF_AMBUSH (MF_NOCLIPTHING): is flagged, Flickies hop. +// +void A_FlickyCenter(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + UINT16 flickytype = (locvar1 & 0xFFFF); + UINT8 flickycolor = ((locvar1 >> 16) & 0xFF); + UINT8 flickyflags = ((locvar1 >> 20) & 0xF); +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickyCenter", actor)) + return; +#endif + + if (!actor->tracer) + { + mobj_t *flicky = P_InternalFlickySpawn(actor, locvar1, 1, false); + P_SetTarget(&flicky->target, actor); + P_SetTarget(&actor->tracer, flicky); + + if (actor->spawnpoint) + { + actor->flags &= ~(MF_SLIDEME|MF_GRENADEBOUNCE|MF_NOCLIPTHING); + actor->flags |= ( + ((actor->spawnpoint->options & MTF_EXTRA) ? MF_SLIDEME : 0) + | ((actor->spawnpoint->options & MTF_OBJECTSPECIAL) ? MF_GRENADEBOUNCE : 0) + | ((actor->spawnpoint->options & MTF_AMBUSH) ? MF_NOCLIPTHING : 0) + ); + actor->extravalue1 = actor->spawnpoint->angle ? abs(actor->spawnpoint->angle) * FRACUNIT + : locvar2 ? abs(locvar2) : 384 * FRACUNIT; + actor->extravalue2 = actor->spawnpoint->extrainfo; + actor->friction = actor->spawnpoint->x*FRACUNIT; + actor->movefactor = actor->spawnpoint->y*FRACUNIT; + actor->watertop = actor->spawnpoint->z*FRACUNIT; + } + else + { + actor->flags &= ~(MF_SLIDEME|MF_GRENADEBOUNCE|MF_NOCLIPTHING); + actor->flags |= ( + ((flickyflags & 1) ? MF_SLIDEME : 0) + | ((flickyflags & 2) ? MF_GRENADEBOUNCE : 0) + | ((flickyflags & 4) ? MF_NOCLIPTHING : 0) + ); + actor->extravalue1 = abs(locvar2); + actor->extravalue2 = flickycolor; + actor->friction = actor->x; + actor->movefactor = actor->y; + actor->watertop = actor->z; + locvar1 = flickytype; + } + + if (actor->flags & MF_GRENADEBOUNCE) // in-place + actor->tracer->fuse = 0; + else if (actor->flags & MF_SLIDEME) // aimless + { + actor->tracer->fuse = 0; // less than 2*TICRATE means move aimlessly. + actor->tracer->angle = P_RandomKey(180)*ANG2; + } + else //orbit + actor->tracer->fuse = FRACUNIT; + + if (locvar1 == MT_FLICKY_08) + P_InternalFlickySetColor(actor->tracer, actor->extravalue2); + + actor->extravalue2 = 0; + } + + if (!(actor->flags & MF_SLIDEME) && !(actor->flags & MF_GRENADEBOUNCE)) + { + fixed_t originx = actor->friction; + fixed_t originy = actor->movefactor; + fixed_t originz = actor->watertop; + + actor->tracer->fuse = FRACUNIT; + + // Impose default home radius if flicky orbits around player + if (!actor->extravalue1) + actor->extravalue1 = locvar2 ? abs(locvar2) : 384 * FRACUNIT; + + P_LookForPlayers(actor, true, false, actor->extravalue1); + + if (actor->target && P_AproxDistance(actor->target->x - originx, actor->target->y - originy) < actor->extravalue1) + { + actor->extravalue2 = 1; + P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z); + } + else if(actor->extravalue2) + { + actor->extravalue2 = 0; + P_TeleportMove(actor, originx, originy, originz); + } + } +} + +// Internal Flicky bubbling function. +void P_InternalFlickyBubble(mobj_t *actor) +{ + if (actor->eflags & MFE_UNDERWATER) + { + mobj_t *overlay; + + if (!((actor->z + 3*actor->height/2) < actor->watertop) || !mobjinfo[actor->type].raisestate || actor->tracer) + return; + + overlay = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY); + P_SetMobjStateNF(overlay, mobjinfo[actor->type].raisestate); + P_SetTarget(&actor->tracer, overlay); + P_SetTarget(&overlay->target, actor); + return; + } + + if (!actor->tracer || P_MobjWasRemoved(actor->tracer)) + return; + + P_RemoveMobj(actor->tracer); + P_SetTarget(&actor->tracer, NULL); +} + +// Function: A_FlickyAim +// +// Description: Flicky aiming function. +// +// var1 = how far around the target (in angle constants) the flicky should look +// var2 = distance from target to aim for +// +void A_FlickyAim(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + boolean flickyhitwall = false; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickyAim", actor)) + return; +#endif + + if ((actor->momx == actor->momy && actor->momy == 0) + || (actor->target && P_IsFlickyCenter(actor->target->type) + && actor->target->extravalue1 && (actor->target->flags & MF_SLIDEME) + && P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) >= actor->target->extravalue1)) + flickyhitwall = true; + + P_InternalFlickyBubble(actor); + P_InstaThrust(actor, 0, 0); + + if (!actor->target) + { + P_LookForPlayers(actor, true, false, 0); + actor->angle = P_RandomKey(36)*ANG10; + return; + } + + if (actor->fuse > 2*TICRATE) + { + angle_t posvar; + fixed_t chasevar, chasex, chasey; + + if (flickyhitwall) + actor->movedir *= -1; + + posvar = ((R_PointToAngle2(actor->target->x, actor->target->y, actor->x, actor->y) + actor->movedir*locvar1) >> ANGLETOFINESHIFT) & FINEMASK; + chasevar = FixedSqrt(max(FRACUNIT, P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y) - locvar2)) + locvar2; + + chasex = actor->target->x + FixedMul(FINECOSINE(posvar), chasevar); + chasey = actor->target->y + FixedMul(FINESINE(posvar), chasevar); + + if (P_AproxDistance(chasex - actor->x, chasey - actor->y)) + actor->angle = R_PointToAngle2(actor->x, actor->y, chasex, chasey); + } + else if (flickyhitwall) + { + if (actor->target && P_IsFlickyCenter(actor->target->type)) + actor->angle = R_PointToAngle2(actor->target->x, actor->target->y, actor->x, actor->y) + P_RandomRange(112, 248) * ANG1; + else + actor->angle += P_RandomRange(112, 248)*ANG1; + actor->threshold = 0; + } +} + +//Internal Flicky flying function. Also usuable as an underwater swim thrust. +void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fixed_t chasez) +{ + angle_t vertangle; + + flyspeed = FixedMul(flyspeed, actor->scale); + actor->flags |= MF_NOGRAVITY; + + var1 = ANG30; + var2 = 32*FRACUNIT; + A_FlickyAim(actor); + + chasez *= 8; + if (!actor->target || !(actor->fuse > 2*TICRATE)) + chasez += ((actor->eflags & MFE_VERTICALFLIP) ? actor->ceilingz - 24*FRACUNIT : actor->floorz + 24*FRACUNIT); + else + { + fixed_t add = actor->target->z + (actor->target->height - actor->height)/2; + if (add > (actor->ceilingz - 24*actor->scale - actor->height)) + add = actor->ceilingz - 24*actor->scale - actor->height; + else if (add < (actor->floorz + 24*actor->scale)) + add = actor->floorz + 24*actor->scale; + chasez += add; + } + + if (!targetdist) + targetdist = 16*FRACUNIT; //Default! + + if (actor->target && abs(chasez - actor->z) > targetdist) + targetdist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); + + if (actor->target + && P_IsFlickyCenter(actor->target->type) + && (actor->target->flags & MF_SLIDEME)) + vertangle = 0; + else + vertangle = (R_PointToAngle2(0, actor->z, targetdist, chasez) >> ANGLETOFINESHIFT) & FINEMASK; + + P_InstaThrust(actor, actor->angle, FixedMul(FINECOSINE(vertangle), flyspeed)); + actor->momz = FixedMul(FINESINE(vertangle), flyspeed); +} + +// Function: A_FlickyFly +// +// Description: Flicky flying function. +// +// var1 = how fast to fly +// var2 = how far ahead the target should be considered +// +void A_FlickyFly(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickyFly", actor)) + return; +#endif + P_InternalFlickyFly(actor, locvar1, locvar2, + FINECOSINE((((actor->fuse % 36) * ANG10) >> ANGLETOFINESHIFT) & FINEMASK) + ); +} + +// Function: A_FlickySoar +// +// Description: Flicky soaring function - specific to puffin. +// +// var1 = how fast to fly +// var2 = how far ahead the target should be considered +// +void A_FlickySoar(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickySoar", actor)) + return; +#endif + P_InternalFlickyFly(actor, locvar1, locvar2, + 2*(FRACUNIT/2 - abs(FINECOSINE((((actor->fuse % 144) * 5*ANG1/2) >> ANGLETOFINESHIFT) & FINEMASK))) + ); + + if (P_MobjFlip(actor)*actor->momz > 0 && actor->frame == 1 && actor->sprite == SPR_FL10) + actor->frame = 3; +} + +//Function: A_FlickyCoast +// +// Description: Flicky swim-coasting function. +// +// var1 = speed to change state upon reaching +// var2 = state to change to upon slowing down +// the spawnstate of the mobj = state to change to when above water +// +void A_FlickyCoast(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickyCoast", actor)) + return; +#endif + if (actor->eflags & MFE_UNDERWATER) + { + actor->momx = (11*actor->momx)/12; + actor->momy = (11*actor->momy)/12; + actor->momz = (11*actor->momz)/12; + + if (P_AproxDistance(P_AproxDistance(actor->momx, actor->momy), actor->momz) < locvar1) + P_SetMobjState(actor, locvar2); + + return; + } + + actor->flags &= ~MF_NOGRAVITY; + P_SetMobjState(actor, mobjinfo[actor->type].spawnstate); +} + +// Internal Flicky hopping function. +void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angle) +{ + if (((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) + || ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz))) + { + if (momz) + { + if (actor->eflags & MFE_UNDERWATER) + momz = FixedDiv(momz, FixedSqrt(3*FRACUNIT)); + P_SetObjectMomZ(actor, momz, false); + } + P_InstaThrust(actor, angle, FixedMul(momh, actor->scale)); + } +} + +// Function: A_FlickyHop +// +// Description: Flicky hopping function. +// +// var1 = vertical thrust +// var2 = horizontal thrust +// +void A_FlickyHop(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickyHop", actor)) + return; +#endif + P_InternalFlickyHop(actor, locvar1, locvar2, actor->angle); +} + +// Function: A_FlickyFlounder +// +// Description: Flicky floundering function. +// +// var1 = intended vertical thrust +// var2 = intended horizontal thrust +// +void A_FlickyFlounder(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + angle_t hopangle; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickyFlounder", actor)) + return; +#endif + locvar1 *= (P_RandomKey(2) + 1); + locvar2 *= (P_RandomKey(2) + 1); + hopangle = (actor->angle + (P_RandomKey(9) - 4)*ANG2); + P_InternalFlickyHop(actor, locvar1, locvar2, hopangle); +} + +// Function: A_FlickyCheck +// +// Description: Flicky airtime check function. +// +// var1 = state to change to upon touching the floor +// var2 = state to change to upon falling +// the meleestate of the mobj = state to change to when underwater +// +void A_FlickyCheck(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickyCheck", actor)) + return; +#endif + if (actor->target + && P_IsFlickyCenter(actor->target->type) + && (actor->target->flags & MF_GRENADEBOUNCE)) + { + if (!(actor->target->flags & MF_NOCLIPTHING)) // no hopping + { + actor->momz = 0; + actor->flags |= MF_NOGRAVITY; + } + actor->flags |= MF_NOCLIP | MF_NOBLOCKMAP | MF_SCENERY; + P_SetMobjState(actor, mobjinfo[actor->type].seestate); + } + else if (locvar2 && P_MobjFlip(actor)*actor->momz < 1) + P_SetMobjState(actor, locvar2); + else if (locvar1 && ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) + || ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz))) + P_SetMobjState(actor, locvar1); + else if (mobjinfo[actor->type].meleestate && (actor->eflags & MFE_UNDERWATER)) + P_SetMobjState(actor, mobjinfo[actor->type].meleestate); + P_InternalFlickyBubble(actor); +} + +// Function: A_FlickyHeightCheck +// +// Description: Flicky height check function. +// +// var1 = state to change to when falling below height relative to target +// var2 = height relative to target to change state at +// +void A_FlickyHeightCheck(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickyHeightCheck", actor)) + return; +#endif + if (actor->target + && P_IsFlickyCenter(actor->target->type) + && (actor->target->flags & MF_GRENADEBOUNCE)) + { + if (!(actor->target->flags & MF_NOCLIPTHING)) // no hopping + { + actor->momz = 0; + actor->flags |= MF_NOGRAVITY; + } + actor->flags |= MF_NOCLIP | MF_NOBLOCKMAP | MF_SCENERY; + P_SetMobjState(actor, mobjinfo[actor->type].seestate); + } + else if (locvar1 && actor->target && P_MobjFlip(actor)*actor->momz < 1 + && ((P_MobjFlip(actor)*((actor->z + actor->height/2) - (actor->target->z + actor->target->height/2)) < locvar2) + || (actor->z - actor->height < actor->floorz) || (actor->z + 2*actor->height > actor->ceilingz))) + P_SetMobjState(actor, locvar1); + P_InternalFlickyBubble(actor); +} + +// Function: A_FlickyFlutter +// +// Description: Flicky fluttering function - specific to chicken. +// +// var1 = state to change to upon touching the floor +// var2 = state to change to upon falling +// the meleestate of the mobj = state to change to when underwater +// +void A_FlickyFlutter(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickyFlutter", actor)) + return; +#endif + var1 = locvar1; + var2 = locvar2; + A_FlickyCheck(actor); + + var1 = ANG30; + var2 = 32*FRACUNIT; + A_FlickyAim(actor); + + P_InstaThrust(actor, actor->angle, 2*actor->scale); + if (P_MobjFlip(actor)*actor->momz < -FRACUNIT/2) + actor->momz = -P_MobjFlip(actor)*actor->scale/2; +} + +#undef FLICKYHITWALL + +// Function: A_FlameParticle +// +// Description: Creates the mobj's painchance at a random position around the object's radius. +// +// var1 = unused +// var2 = unused +// +void A_FlameParticle(mobj_t *actor) +{ + mobjtype_t type = (mobjtype_t)(mobjinfo[actor->type].painchance); + fixed_t rad, hei; + mobj_t *particle; + //INT32 locvar1 = var1; + //INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlameParticle", actor)) + return; +#endif + + if (!type) + return; + + rad = actor->radius>>FRACBITS; + hei = actor->height>>FRACBITS; + particle = P_SpawnMobjFromMobj(actor, + P_RandomRange(rad, -rad)<frame = actor->frame; + + if (!(locvar1 & 1)) + { + fade->fuse = 15; + fade->flags2 |= MF2_BOSSNOTRAP; + } + else + fade->fuse = 20; + + if (!(locvar1 & 2)) + P_SetTarget(&actor->tracer, fade); +} + +// Function: A_Boss5Jump +// +// Description: Makes an object jump in an arc to land on their tracer precicely. +// Adapted from A_BrakLobShot, see there for explanation. +// +// var1 = unused +// var2 = unused +// +void A_Boss5Jump(mobj_t *actor) +{ + fixed_t v; // Velocity to jump at + fixed_t a1, a2, aToUse; // Velocity squared + fixed_t g; // Gravity + fixed_t x; // Horizontal difference + INT32 x_int; // x! But in integer form! + fixed_t y; // Vertical difference (yes that's normally z in SRB2 shut up) + INT32 y_int; // y! But in integer form! + INT32 intHypotenuse; // x^2 + y^2. Frequently overflows fixed point, hence why we need integers proper. + fixed_t fixedHypotenuse; // However, we can work around that and still get a fixed-point number. + angle_t theta; // Angle of attack + // INT32 locvar1 = var1; + // INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss5Jump", actor)) + return; +#endif + + if (!actor->tracer) + return; // Don't even bother if we've got nothing to aim at. + + // Look up actor's current gravity situation + if (actor->subsector->sector->gravity) + g = FixedMul(gravity,(FixedDiv(*actor->subsector->sector->gravity>>FRACBITS, 1000))); + else + g = gravity; + + // Look up distance between actor and its tracer + x = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y); + // Look up height difference between actor and its tracer + y = actor->tracer->z - actor->z; + + // Get x^2 + y^2. Have to do it in a roundabout manner, because this overflows fixed_t way too easily otherwise. + x_int = x>>FRACBITS; + y_int = y>>FRACBITS; + intHypotenuse = (x_int*x_int) + (y_int*y_int); + fixedHypotenuse = FixedSqrt(intHypotenuse) *256; + + // a = g(y+/-sqrt(x^2+y^2)). a1 can be +, a2 can be -. + a1 = FixedMul(g,y+fixedHypotenuse); + a2 = FixedMul(g,y-fixedHypotenuse); + + // Determine which one isn't actually an imaginary number (or the smaller of the two, if both are real), and use that for v. + if (a1 < 0 || a2 < 0) + { + if (a1 < 0 && a2 < 0) + { + //Somehow, v^2 is negative in both cases. v is therefore imaginary and something is horribly wrong. Abort! + return; + } + // Just find which one's NOT negative, and use that + aToUse = max(a1,a2); + } + else + { + // Both are positive; use whichever's smaller so it can decay faster + aToUse = min(a1,a2); + } + v = FixedSqrt(aToUse); + // Okay, so we know the velocity. Let's actually find theta. + // We can cut the "+/- sqrt" part out entirely, since v was calculated specifically for it to equal zero. So: + //theta = tantoangle[FixedDiv(aToUse,FixedMul(g,x)) >> DBITS]; + theta = tantoangle[SlopeDiv(aToUse,FixedMul(g,x))]; + + // Okay, complicated math done. Let's make this object jump already. + A_FaceTracer(actor); + + if (actor->eflags & MFE_VERTICALFLIP) + actor->z--; + else + actor->z++; + + // Horizontal axes first. First parameter is initial horizontal impulse, second is to correct its angle. + fixedHypotenuse = FixedMul(v, FINECOSINE(theta >> ANGLETOFINESHIFT)); // variable reuse + actor->momx = FixedMul(fixedHypotenuse, FINECOSINE(actor->angle >> ANGLETOFINESHIFT)); + actor->momy = FixedMul(fixedHypotenuse, FINESINE(actor->angle >> ANGLETOFINESHIFT)); + // Then the vertical axis. No angle-correction needed here. + actor->momz = FixedMul(v, FINESINE(theta >> ANGLETOFINESHIFT)); + // I hope that's all that's needed, ugh +} + +// Function: A_LightBeamReset +// Description: Resets momentum and position for DSZ's projecting light beams +// +// var1 = unused +// var2 = unused +// +void A_LightBeamReset(mobj_t *actor) +{ + // INT32 locvar1 = var1; + // INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_LightBeamReset", actor)) + return; +#endif + + actor->destscale = FRACUNIT + P_SignedRandom()*FRACUNIT/256; + P_SetScale(actor, actor->destscale); + + if (!actor->spawnpoint) + return; // this can't work properly welp + + actor->momx = -(P_SignedRandom()*FINESINE(((actor->spawnpoint->angle*ANG1)>>ANGLETOFINESHIFT) & FINEMASK))/128; + actor->momy = (P_SignedRandom()*FINECOSINE(((actor->spawnpoint->angle*ANG1)>>ANGLETOFINESHIFT) & FINEMASK))/128; + actor->momz = (P_SignedRandom()*FRACUNIT)/128; + + P_TeleportMove(actor, + actor->spawnpoint->x*FRACUNIT - (P_SignedRandom()*FINESINE(((actor->spawnpoint->angle*ANG1)>>ANGLETOFINESHIFT) & FINEMASK))/2, + actor->spawnpoint->y*FRACUNIT + (P_SignedRandom()*FINECOSINE(((actor->spawnpoint->angle*ANG1)>>ANGLETOFINESHIFT) & FINEMASK))/2, + actor->spawnpoint->z*FRACUNIT + (P_SignedRandom()*FRACUNIT)/2); +} + +// Function: A_MineExplode +// Description: Handles the explosion of a DSZ mine. +// +// var1 = unused +// var2 = unused +// +void A_MineExplode(mobj_t *actor) +{ + // INT32 locvar1 = var1; + // INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_MineExplode", actor)) + return; +#endif + + A_Scream(actor); + actor->flags = MF_NOGRAVITY|MF_NOCLIP; + + quake.epicenter = NULL; + quake.radius = 512*FRACUNIT; + quake.intensity = 8*FRACUNIT; + quake.time = TICRATE/3; + + P_RadiusAttack(actor, actor->tracer, 192*FRACUNIT, DMG_CANHURTSELF); + P_MobjCheckWater(actor); + + { +#define dist 64 + UINT8 i; + mobjtype_t type = ((actor->eflags & MFE_UNDERWATER) ? MT_UWEXPLODE : MT_BOSSEXPLODE); + S_StartSound(actor, ((actor->eflags & MFE_UNDERWATER) ? sfx_s3k57 : sfx_s3k4e)); + P_SpawnMobj(actor->x, actor->y, actor->z, type); + for (i = 0; i < 16; i++) + { + mobj_t *b = P_SpawnMobj(actor->x+P_RandomRange(-dist, dist)*FRACUNIT, + actor->y+P_RandomRange(-dist, dist)*FRACUNIT, + actor->z+P_RandomRange(((actor->eflags & MFE_UNDERWATER) ? -dist : 0), dist)*FRACUNIT, + type); + fixed_t dx = b->x - actor->x, dy = b->y - actor->y, dz = b->z - actor->z; + fixed_t dm = P_AproxDistance(dz, P_AproxDistance(dy, dx)); + b->momx = FixedDiv(dx, dm)*3; + b->momy = FixedDiv(dy, dm)*3; + b->momz = FixedDiv(dz, dm)*3; + if ((actor->watertop == INT32_MAX) || (b->z + b->height > actor->watertop)) + b->flags &= ~MF_NOGRAVITY; + } +#undef dist + + if (actor->watertop != INT32_MAX) + P_SpawnMobj(actor->x, actor->y, actor->watertop, MT_SPLISH); + } +} + +// Function: A_MineRange +// Description: If the target gets too close, change the state to meleestate. +// +// var1 = Distance to alert at +// var2 = unused +// +void A_MineRange(mobj_t *actor) +{ + fixed_t dm; + INT32 locvar1 = var1; + // INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_MineRange", actor)) + return; +#endif + + if (!actor->target) + return; + + dm = P_AproxDistance(actor->z - actor->target->z, P_AproxDistance(actor->y - actor->target->y, actor->x - actor->target->x)); + if ((dm>>FRACBITS) < locvar1) + P_SetMobjState(actor, actor->info->meleestate); +} + +// Function: A_ConnectToGround +// Description: Create a palm tree trunk/mine chain. +// +// var1 = Object type to connect to ground +// var2 = Object type to place on ground +// +void A_ConnectToGround(mobj_t *actor) +{ + mobj_t *work; + fixed_t workz; + fixed_t workh; + SINT8 dir; + angle_t ang; + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_ConnectToGround", actor)) + return; +#endif + + if (actor->subsector->sector->ffloors) + P_AdjustMobjFloorZ_FFloors(actor, actor->subsector->sector, 2); + + if (actor->flags2 & MF2_OBJECTFLIP) + { + workz = actor->ceilingz - (actor->z + actor->height); + dir = -1; + } + else + { + workz = actor->floorz - actor->z; + dir = 1; + } + + if (locvar2) + { + workh = FixedMul(mobjinfo[locvar2].height, actor->scale); + if (actor->flags2 & MF2_OBJECTFLIP) + workz -= workh; + work = P_SpawnMobjFromMobj(actor, 0, 0, workz, locvar2); + workz += dir*workh; + } + + if (!locvar1) + return; + + if (!(workh = FixedMul(mobjinfo[locvar1].height, actor->scale))) + return; + + if (actor->flags2 & MF2_OBJECTFLIP) + workz -= workh; + + ang = actor->angle + ANGLE_45; + while (dir*workz < 0) + { + work = P_SpawnMobjFromMobj(actor, 0, 0, workz, locvar1); + if (work) + work->angle = ang; + ang += ANGLE_90; + workz += dir*workh; + } + + if (workz != 0) + actor->z += workz; +} + +// Function: A_SpawnParticleRelative +// +// Description: Spawns a particle effect relative to the location of the actor +// +// var1: +// var1 >> 16 = x +// var1 & 65535 = y +// var2: +// var2 >> 16 = z +// var2 & 65535 = state +// +void A_SpawnParticleRelative(mobj_t *actor) +{ + INT16 x, y, z; // Want to be sure we can use negative values + statenum_t state; + mobj_t *mo; + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SpawnParticleRelative", actor)) + return; +#endif + + CONS_Debug(DBG_GAMELOGIC, "A_SpawnParticleRelative called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); + + x = (INT16)(locvar1>>16); + y = (INT16)(locvar1&65535); + z = (INT16)(locvar2>>16); + state = (statenum_t)(locvar2&65535); + + // Spawn objects correctly in reverse gravity. + // NOTE: Doing actor->z + actor->height is the bottom of the object while the object has reverse gravity. - Flame + mo = P_SpawnMobj(actor->x + FixedMul(x<scale), + actor->y + FixedMul(y<scale), + (actor->eflags & MFE_VERTICALFLIP) ? ((actor->z + actor->height - mobjinfo[MT_PARTICLE].height) - FixedMul(z<scale)) : (actor->z + FixedMul(z<scale)), MT_PARTICLE); + + // Spawn objects with an angle matching the spawner's, rather than spawning Eastwards - Monster Iestyn + mo->angle = actor->angle; + + if (actor->eflags & MFE_VERTICALFLIP) + mo->flags2 |= MF2_OBJECTFLIP; + + P_SetMobjState(mo, state); +} + +// Function: A_MultiShotDist +// +// Description: Spawns multiple shots based on player proximity +// +// var1 = same as A_MultiShot +// var2 = same as A_MultiShot +// +void A_MultiShotDist(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_MultiShotDist", actor)) + return; +#endif + + { + UINT8 i; + // Quick! Look through players! + // Don't spawn dust unless a player is relatively close by (var1). + for (i = 0; i < MAXPLAYERS; ++i) + if (playeringame[i] && players[i].mo + && P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (1600<> 16 = mobjtype of child +// var2 & 65535 = vertical momentum +// var2: +// var2 >> 16 = forward offset +// var2 & 65535 = vertical offset +// +void A_WhoCaresIfYourSonIsABee(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + fixed_t foffsetx; + fixed_t foffsety; + mobj_t *son; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_WhoCaresIfYourSonIsABee", actor)) + return; +#endif + + A_FaceTarget(actor); + + if (actor->extravalue1) + actor->extravalue1--; + + if (actor->info->attacksound) + S_StartSound(actor, actor->info->attacksound); + + foffsetx = P_ReturnThrustX(actor, actor->angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale)); + foffsety = P_ReturnThrustY(actor, actor->angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale)); + + if (!(son = P_SpawnMobjFromMobj(actor, foffsetx, foffsety, (locvar2&65535)*FRACUNIT, (mobjtype_t)(locvar1 >> 16)))) + return; + + P_SetObjectMomZ(son, (locvar1 & 65535)<tracer, actor); + P_SetTarget(&son->target, actor->target); +} + +// Function: A_ParentTriesToSleep +// +// Description: If extravalue1 is less than or equal to var1, go to var2. +// +// var1 = state to go to when extravalue1 +// var2 = unused +// +void A_ParentTriesToSleep(mobj_t *actor) +{ + INT32 locvar1 = var1; + //INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_ParentTriesToSleep", actor)) + return; +#endif + + if (actor->extravalue1) + { + if (actor->info->seesound) + S_StartSound(actor, actor->info->seesound); + actor->reactiontime = 0; + P_SetMobjState(actor, locvar1); + } + else if (!actor->reactiontime) + { + actor->reactiontime = 1; + if (actor->info->activesound) // more like INactivesound doy hoy hoy + S_StartSound(actor, actor->info->activesound); + } +} + + +// Function: A_CryingToMomma +// +// Description: If you're a child, let your parent know something's happened to you through extravalue1. Also, prepare to die. +// +// var1 = unused +// var2 = unused +// +void A_CryingToMomma(mobj_t *actor) +{ + //INT32 locvar1 = var1; + //INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CryingToMomma", actor)) + return; +#endif + + if (actor->tracer) + actor->tracer->extravalue1++; + + actor->momx = actor->momy = actor->momz = 0; + + P_UnsetThingPosition(actor); + if (sector_list) + { + P_DelSeclist(sector_list); + sector_list = NULL; + } + actor->flags = MF_NOBLOCKMAP|MF_NOCLIPTHING; + P_SetThingPosition(actor); +} + +// Function: A_CheckFlags2 +// +// Description: If actor->flags2 & var1, goto var2. +// +// var1 = mask +// var2 = state to go +// +void A_CheckFlags2(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckFlags2", actor)) + return; +#endif + + if (actor->flags2 & locvar1) + P_SetMobjState(actor, (statenum_t)locvar2); +}