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