BOOL EV_DoPillar (DPillar::EPillar type, int tag, fixed_t speed, fixed_t height, fixed_t height2, bool crush) { BOOL rtn = false; int secnum = -1; while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0) { sector_t *sec = §ors[secnum]; fixed_t floorheight = P_FloorHeight(sec); fixed_t ceilingheight = P_CeilingHeight(sec); if (sec->floordata || sec->ceilingdata) continue; if (type == DPillar::pillarBuild && floorheight == ceilingheight) continue; if (type == DPillar::pillarOpen && floorheight != ceilingheight) continue; rtn = true; new DPillar (sec, type, speed, height, height2, crush); P_AddMovingCeiling(sec); } return rtn; }
// // TELEPORTATION // // [RH] Changed to look for a destination by ThingID BOOL EV_Teleport (int tid, int side, AActor *thing) { AActor *m; unsigned an; fixed_t oldx; fixed_t oldy; fixed_t oldz; player_t *player; // don't teleport missiles if (thing->flags & MF_MISSILE) return false; // Don't teleport if hit back of line, // so you can get out of teleporter. if (side == 1) return false; // [RH] Find destination based on it's TID rather than // the sector containing it. Also allow for destinations // that remember their vertical position. if (NULL == (m = AActor::FindGoal (NULL, tid, MT_TELEPORTMAN))) if (NULL == (m = AActor::FindGoal (NULL, tid, MT_TELEPORTMAN2))) return false; // killough 5/12/98: exclude voodoo dolls: player = thing->player; if (player && player->mo != thing) player = NULL; oldx = thing->x; oldy = thing->y; oldz = thing->z; fixed_t destz = (m->type == MT_TELEPORTMAN) ? P_FloorHeight(m) : m->z; if (!P_TeleportMove (thing, m->x, m->y, destz, false)) return false; // fraggle: this was changed in final doom, // problem between normal doom2 1.9 and final doom // Note that although chex.exe is based on Final Doom, // it does not have this quirk. if (gamemission < pack_tnt || gamemission == chex) thing->z = thing->floorz; if (player) player->viewz = thing->z + thing->player->viewheight; // spawn teleport fog at source and destination if(serverside && !(player && player->spectator)) { S_Sound (new AActor (oldx, oldy, oldz, MT_TFOG), CHAN_VOICE, "misc/teleport", 1, ATTN_NORM); an = m->angle >> ANGLETOFINESHIFT; // emit sound at new spot S_Sound (new AActor (m->x+20*finecosine[an], m->y+20*finesine[an], thing->z, MT_TFOG), CHAN_VOICE, "misc/teleport", 1, ATTN_NORM); }
// // R_InterpolationTicker // // Records the current height of all moving planes and position of scrolling // textures, which will be used as the previous position during iterpolation. // This should be called once per gametic. // void R_InterpolationTicker() { prev_ceilingheight.clear(); prev_floorheight.clear(); if (gamestate == GS_LEVEL) { for (int i = 0; i < numsectors; i++) { if (sectors[i].ceilingdata) prev_ceilingheight.push_back(std::make_pair(P_CeilingHeight(§ors[i]), i)); if (sectors[i].floordata) prev_floorheight.push_back(std::make_pair(P_FloorHeight(§ors[i]), i)); } } }
// // R_BeginInterpolation // // Saves the current height of all moving planes and position of scrolling // textures, which will be restored by R_EndInterpolation. The height of a // moving plane will be interpolated between the previous height and this // current height. This should be called every time a frame is rendered. // void R_BeginInterpolation(fixed_t amount) { saved_ceilingheight.clear(); saved_floorheight.clear(); if (gamestate == GS_LEVEL) { for (std::vector<fixed_uint_pair>::const_iterator ceiling_it = prev_ceilingheight.begin(); ceiling_it != prev_ceilingheight.end(); ++ceiling_it) { unsigned int secnum = ceiling_it->second; sector_t* sector = §ors[secnum]; fixed_t old_value = ceiling_it->first; fixed_t cur_value = P_CeilingHeight(sector); saved_ceilingheight.push_back(std::make_pair(cur_value, secnum)); fixed_t new_value = old_value + FixedMul(cur_value - old_value, amount); P_SetCeilingHeight(sector, new_value); } for (std::vector<fixed_uint_pair>::const_iterator floor_it = prev_floorheight.begin(); floor_it != prev_floorheight.end(); ++floor_it) { unsigned int secnum = floor_it->second; sector_t* sector = §ors[secnum]; fixed_t old_value = floor_it->first; fixed_t cur_value = P_FloorHeight(sector); saved_floorheight.push_back(std::make_pair(cur_value, secnum)); fixed_t new_value = old_value + FixedMul(cur_value - old_value, amount); P_SetFloorHeight(sector, new_value); } } }
// // R_Subsector // Determine floor/ceiling planes. // Add sprites of things in sector. // Draw one or more line segments. // void R_Subsector (int num) { int count; seg_t* line; subsector_t *sub; sector_t tempsec; // killough 3/7/98: deep water hack int floorlightlevel; // killough 3/16/98: set floor lightlevel int ceilinglightlevel; // killough 4/11/98 #ifdef RANGECHECK if (num>=numsubsectors) I_Error ("R_Subsector: ss %i with numss = %i", num, numsubsectors); #endif sub = &subsectors[num]; frontsector = sub->sector; count = sub->numlines; line = &segs[sub->firstline]; // killough 3/8/98, 4/4/98: Deep water / fake ceiling effect frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false); // killough 4/11/98 basecolormap = frontsector->colormap->maps; ceilingplane = P_CeilingHeight(camera) > viewz || frontsector->ceilingpic == skyflatnum || (frontsector->heightsec && !(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) && frontsector->heightsec->floorpic == skyflatnum) ? R_FindPlane(frontsector->ceilingplane, // killough 3/8/98 frontsector->ceilingpic == skyflatnum && // killough 10/98 frontsector->sky & PL_SKYFLAT ? frontsector->sky : frontsector->ceilingpic, ceilinglightlevel, // killough 4/11/98 frontsector->ceiling_xoffs, // killough 3/7/98 frontsector->ceiling_yoffs + frontsector->base_ceiling_yoffs, frontsector->ceiling_xscale, frontsector->ceiling_yscale, frontsector->ceiling_angle + frontsector->base_ceiling_angle ) : NULL; // killough 3/7/98: Add (x,y) offsets to flats, add deep water check // killough 3/16/98: add floorlightlevel // killough 10/98: add support for skies transferred from sidedefs floorplane = P_FloorHeight(camera) < viewz || // killough 3/7/98 (frontsector->heightsec && !(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) && frontsector->heightsec->ceilingpic == skyflatnum) ? R_FindPlane(frontsector->floorplane, frontsector->floorpic == skyflatnum && // killough 10/98 frontsector->sky & PL_SKYFLAT ? frontsector->sky : frontsector->floorpic, floorlightlevel, // killough 3/16/98 frontsector->floor_xoffs, // killough 3/7/98 frontsector->floor_yoffs + frontsector->base_floor_yoffs, frontsector->floor_xscale, frontsector->floor_yscale, frontsector->floor_angle + frontsector->base_floor_angle ) : NULL; // [RH] set foggy flag foggy = level.fadeto_color[0] || level.fadeto_color[1] || level.fadeto_color[2] || level.fadeto_color[3] || frontsector->colormap->fade; // killough 9/18/98: Fix underwater slowdown, by passing real sector // instead of fake one. Improve sprite lighting by basing sprite // lightlevels on floor & ceiling lightlevels in the surrounding area. R_AddSprites (sub->sector, (floorlightlevel + ceilinglightlevel) / 2, FakeSide); // [RH] Add particles if (r_particles) { for (WORD i = ParticlesInSubsec[num]; i != NO_PARTICLE; i = Particles[i].nextinsubsector) R_ProjectParticle(Particles + i, subsectors[num].sector, FakeSide); } if (sub->poly) { // Render the polyobj in the subsector first int polyCount = sub->poly->numsegs; seg_t **polySeg = sub->poly->segs; while (polyCount--) R_AddLine (*polySeg++); } while (count--) R_AddLine (line++); }
sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, int *floorlightlevel, int *ceilinglightlevel, bool back) { // [RH] allow per-plane lighting if (floorlightlevel != NULL) { *floorlightlevel = sec->floorlightsec == NULL ? sec->lightlevel : sec->floorlightsec->lightlevel; } if (ceilinglightlevel != NULL) { *ceilinglightlevel = sec->ceilinglightsec == NULL ? // killough 4/11/98 sec->lightlevel : sec->ceilinglightsec->lightlevel; } FakeSide = FAKED_Center; if (!sec->heightsec || sec->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) return sec; if (!camera || !camera->subsector || !camera->subsector->sector) return sec; const sector_t* s = sec->heightsec; sector_t *heightsec = camera->subsector->sector->heightsec; bool underwater = r_fakingunderwater || (heightsec && viewz <= P_FloorHeight(viewx, viewy, heightsec)); bool doorunderwater = false; int diffTex = (s->MoreFlags & SECF_CLIPFAKEPLANES); // Replace sector being drawn with a copy to be hacked *tempsec = *sec; // Replace floor and ceiling height with control sector's heights. if (diffTex) { if (CopyPlaneIfValid (&tempsec->floorplane, &s->floorplane, &sec->ceilingplane)) tempsec->floorpic = s->floorpic; else if (s->MoreFlags & SECF_FAKEFLOORONLY) { if (underwater) { tempsec->colormap = s->colormap; if (!(s->MoreFlags & SECF_NOFAKELIGHT)) { tempsec->lightlevel = s->lightlevel; if (floorlightlevel != NULL) { *floorlightlevel = s->floorlightsec == NULL ? s->lightlevel : s->floorlightsec->lightlevel; } if (ceilinglightlevel != NULL) { *ceilinglightlevel = s->ceilinglightsec == NULL ? s->lightlevel : s->ceilinglightsec->lightlevel; } } FakeSide = FAKED_BelowFloor; return tempsec; } return sec; } } else { tempsec->floorplane = s->floorplane; } if (!(s->MoreFlags & SECF_FAKEFLOORONLY)) { if (diffTex) { if (CopyPlaneIfValid (&tempsec->ceilingplane, &s->ceilingplane, &sec->floorplane)) tempsec->ceilingpic = s->ceilingpic; } else { tempsec->ceilingplane = s->ceilingplane; } } fixed_t refceilz = P_CeilingHeight(viewx, viewy, s); fixed_t orgceilz = P_CeilingHeight(viewx, viewy, sec); // [RH] Allow viewing underwater areas through doors/windows that // are underwater but not in a water sector themselves. // Only works if you cannot see the top surface of any deep water // sectors at the same time. if (back && !r_fakingunderwater && curline->frontsector->heightsec == NULL) { fixed_t fcz1 = P_CeilingHeight(curline->v1->x, curline->v1->y, frontsector); fixed_t fcz2 = P_CeilingHeight(curline->v2->x, curline->v2->y, frontsector); if (fcz1 <= P_FloorHeight(curline->v1->x, curline->v1->y, s) && fcz2 <= P_FloorHeight(curline->v2->x, curline->v2->y, s)) { // will any columns of this window be visible or will they be blocked // by 1s lines and closed doors? if (memchr(solidcol + rw_start, 0, rw_stop - rw_start + 1) != NULL) { doorunderwater = true; r_fakingunderwater = true; } } } if (underwater || doorunderwater) { tempsec->floorplane = sec->floorplane; tempsec->ceilingplane = s->floorplane; P_InvertPlane(&tempsec->ceilingplane); P_ChangeCeilingHeight(tempsec, -1); tempsec->colormap = s->colormap; } // killough 11/98: prevent sudden light changes from non-water sectors: if ((underwater && !back) || doorunderwater) { // head-below-floor hack tempsec->floorpic = diffTex ? sec->floorpic : s->floorpic; tempsec->floor_xoffs = s->floor_xoffs; tempsec->floor_yoffs = s->floor_yoffs; tempsec->floor_xscale = s->floor_xscale; tempsec->floor_yscale = s->floor_yscale; tempsec->floor_angle = s->floor_angle; tempsec->base_floor_angle = s->base_floor_angle; tempsec->base_floor_yoffs = s->base_floor_yoffs; tempsec->ceilingplane = s->floorplane; P_InvertPlane(&tempsec->ceilingplane); P_ChangeCeilingHeight(tempsec, -1); if (s->ceilingpic == skyflatnum) { tempsec->floorplane = tempsec->ceilingplane; P_InvertPlane(&tempsec->floorplane); P_ChangeFloorHeight(tempsec, +1); tempsec->ceilingpic = tempsec->floorpic; tempsec->ceiling_xoffs = tempsec->floor_xoffs; tempsec->ceiling_yoffs = tempsec->floor_yoffs; tempsec->ceiling_xscale = tempsec->floor_xscale; tempsec->ceiling_yscale = tempsec->floor_yscale; tempsec->ceiling_angle = tempsec->floor_angle; tempsec->base_ceiling_angle = tempsec->base_floor_angle; tempsec->base_ceiling_yoffs = tempsec->base_floor_yoffs; } else { tempsec->ceilingpic = diffTex ? s->floorpic : s->ceilingpic; tempsec->ceiling_xoffs = s->ceiling_xoffs; tempsec->ceiling_yoffs = s->ceiling_yoffs; tempsec->ceiling_xscale = s->ceiling_xscale; tempsec->ceiling_yscale = s->ceiling_yscale; tempsec->ceiling_angle = s->ceiling_angle; tempsec->base_ceiling_angle = s->base_ceiling_angle; tempsec->base_ceiling_yoffs = s->base_ceiling_yoffs; } if (!(s->MoreFlags & SECF_NOFAKELIGHT)) { tempsec->lightlevel = s->lightlevel; if (floorlightlevel != NULL) { *floorlightlevel = s->floorlightsec == NULL ? s->lightlevel : s->floorlightsec->lightlevel; } if (ceilinglightlevel != NULL) { *ceilinglightlevel = s->ceilinglightsec == NULL ? s->lightlevel : s->ceilinglightsec->lightlevel; } } FakeSide = FAKED_BelowFloor; } else if (heightsec && viewz >= P_CeilingHeight(viewx, viewy, heightsec) && orgceilz > refceilz && !(s->MoreFlags & SECF_FAKEFLOORONLY)) { // Above-ceiling hack tempsec->ceilingplane = s->ceilingplane; tempsec->floorplane = s->ceilingplane; P_InvertPlane(&tempsec->floorplane); P_ChangeFloorHeight(tempsec, +1); tempsec->colormap = s->colormap; tempsec->ceilingpic = diffTex ? sec->ceilingpic : s->ceilingpic; tempsec->floorpic = s->ceilingpic; tempsec->floor_xoffs = tempsec->ceiling_xoffs = s->ceiling_xoffs; tempsec->floor_yoffs = tempsec->ceiling_yoffs = s->ceiling_yoffs; tempsec->floor_xscale = tempsec->ceiling_xscale = s->ceiling_xscale; tempsec->floor_yscale = tempsec->ceiling_yscale = s->ceiling_yscale; tempsec->floor_angle = tempsec->ceiling_angle = s->ceiling_angle; tempsec->base_floor_angle = tempsec->base_ceiling_angle = s->base_ceiling_angle; tempsec->base_floor_yoffs = tempsec->base_ceiling_yoffs = s->base_ceiling_yoffs; if (s->floorpic != skyflatnum) { tempsec->ceilingplane = sec->ceilingplane; tempsec->floorpic = s->floorpic; tempsec->floor_xoffs = s->floor_xoffs; tempsec->floor_yoffs = s->floor_yoffs; tempsec->floor_xscale = s->floor_xscale; tempsec->floor_yscale = s->floor_yscale; tempsec->floor_angle = s->floor_angle; } if (!(s->MoreFlags & SECF_NOFAKELIGHT)) { tempsec->lightlevel = s->lightlevel; if (floorlightlevel != NULL) { *floorlightlevel = s->floorlightsec == NULL ? s->lightlevel : s->floorlightsec->lightlevel; } if (ceilinglightlevel != NULL) { *ceilinglightlevel = s->ceilinglightsec == NULL ? s->lightlevel : s->ceilinglightsec->lightlevel; } } FakeSide = FAKED_AboveCeiling; } sec = tempsec; // Use other sector return sec; }
DPlat::DPlat(sector_t *sec, DPlat::EPlatType type, fixed_t height, int speed, int delay, fixed_t lip) : DMovingFloor(sec), m_Status(init) { m_Type = type; m_Crush = false; m_Speed = speed; m_Wait = delay; m_Height = height; m_Lip = lip; //jff 1/26/98 Avoid raise plat bouncing a head off a ceiling and then //going down forever -- default lower to plat height when triggered m_Low = P_FloorHeight(sec); switch (type) { case DPlat::platRaiseAndStay: m_High = P_FindNextHighestFloor(sec); m_Status = DPlat::midup; PlayPlatSound(); break; case DPlat::platUpByValue: case DPlat::platUpByValueStay: m_High = P_FloorHeight(sec) + height; m_Status = DPlat::midup; PlayPlatSound(); break; case DPlat::platDownByValue: m_Low = P_FloorHeight(sec) - height; m_Status = DPlat::middown; PlayPlatSound(); break; case DPlat::platDownWaitUpStay: m_Low = P_FindLowestFloorSurrounding(sec) + lip; if (m_Low > P_FloorHeight(sec)) m_Low = P_FloorHeight(sec); m_High = P_FloorHeight(sec); m_Status = DPlat::down; PlayPlatSound(); break; case DPlat::platUpWaitDownStay: m_High = P_FindHighestFloorSurrounding(sec); if (m_High < P_FloorHeight(sec)) m_High = P_FloorHeight(sec); m_Status = DPlat::up; PlayPlatSound(); break; case DPlat::platPerpetualRaise: m_Low = P_FindLowestFloorSurrounding(sec) + lip; if (m_Low > P_FloorHeight(sec)) m_Low = P_FloorHeight(sec); m_High = P_FindHighestFloorSurrounding (sec); if (m_High < P_FloorHeight(sec)) m_High = P_FloorHeight(sec); m_Status = P_Random () & 1 ? DPlat::down : DPlat::up; PlayPlatSound(); break; case DPlat::platToggle: //jff 3/14/98 add new type to support instant toggle m_Crush = false; //jff 3/14/98 crush anything in the way // set up toggling between ceiling, floor inclusive m_Low = P_CeilingHeight(sec); m_High = P_FloorHeight(sec); m_Status = DPlat::down; // SN_StartSequence (sec, "Silence"); break; case DPlat::platDownToNearestFloor: m_Low = P_FindNextLowestFloor(sec) + lip; m_Status = DPlat::down; m_High = P_FloorHeight(sec); PlayPlatSound(); break; case DPlat::platDownToLowestCeiling: m_Low = P_FindLowestCeilingSurrounding (sec); m_High = P_FloorHeight(sec); if (m_Low > P_FloorHeight(sec)) m_Low = P_FloorHeight(sec); m_Status = DPlat::down; PlayPlatSound(); break; default: break; } }
// // Move a plat up and down // void DPlat::RunThink () { EResult res; switch (m_Status) { case midup: case up: res = MoveFloor (m_Speed, m_High, m_Crush, 1); if (res == crushed && !m_Crush) { m_Count = m_Wait; m_Status = down; PlayPlatSound(); } else if (res == pastdest) { if (m_Type != platToggle) { m_Count = m_Wait; m_Status = waiting; switch (m_Type) { case platDownWaitUpStay: case platRaiseAndStay: case platUpByValueStay: case platDownToNearestFloor: case platDownToLowestCeiling: m_Status = finished; break; default: break; } } else { m_OldStatus = m_Status; //jff 3/14/98 after action wait m_Status = in_stasis; //for reactivation of toggle } PlayPlatSound(); } break; case middown: case down: res = MoveFloor (m_Speed, m_Low, false, -1); if (res == pastdest) { // if not an instant toggle, start waiting if (m_Type != platToggle) //jff 3/14/98 toggle up down { // is silent, instant, no waiting m_Count = m_Wait; m_Status = waiting; switch (m_Type) { case platUpWaitDownStay: case platUpByValue: m_Status = finished; break; default: break; } } else { // instant toggles go into stasis awaiting next activation m_OldStatus = m_Status; //jff 3/14/98 after action wait m_Status = in_stasis; //for reactivation of toggle } PlayPlatSound(); } //jff 1/26/98 remove the plat if it bounced so it can be tried again //only affects plats that raise and bounce // remove the plat if it's a pure raise type switch (m_Type) { case platUpByValueStay: case platRaiseAndStay: m_Status = finished; break; default: break; } break; case waiting: if (!--m_Count) { if (P_FloorHeight(m_Sector) <= m_Low) m_Status = up; else m_Status = down; PlayPlatSound(); } break; case in_stasis: break; default: break; } if (m_Status == finished) { PlayPlatSound(); m_Status = destroy; } if (m_Status == destroy) P_SetPlatDestroy(this); }
// // Move a plane (floor or ceiling) and check for crushing // [RH] Crush specifies the actual amount of crushing damage inflictable. // (Use -1 to prevent it from trying to crush) // DMover::EResult DMover::MovePlane (fixed_t speed, fixed_t dest, bool crush, int floorOrCeiling, int direction) { bool flag; fixed_t lastpos; switch (floorOrCeiling) { case 0: // FLOOR switch (direction) { case -1: // DOWN lastpos = P_FloorHeight(m_Sector); if (lastpos - speed < dest) { P_ChangeFloorHeight(m_Sector, dest - lastpos); flag = P_ChangeSector (m_Sector, crush); if (flag == true) { P_ChangeFloorHeight(m_Sector, lastpos - dest); P_ChangeSector (m_Sector, crush); //return crushed; } return pastdest; } else { P_ChangeFloorHeight(m_Sector, -speed); flag = P_ChangeSector (m_Sector, crush); if (flag == true) { P_ChangeFloorHeight(m_Sector, speed); // should be lastpos P_ChangeSector (m_Sector, crush); return crushed; } } break; case 1: // UP lastpos = P_FloorHeight(m_Sector); if (lastpos + speed > dest) { P_ChangeFloorHeight(m_Sector, dest - lastpos); flag = P_ChangeSector (m_Sector, crush); if (flag == true) { P_ChangeFloorHeight(m_Sector, lastpos - dest); P_ChangeSector (m_Sector, crush); } return pastdest; } else { // COULD GET CRUSHED P_ChangeFloorHeight(m_Sector, speed); flag = P_ChangeSector (m_Sector, crush); if (flag == true) { if (crush) return crushed; P_ChangeFloorHeight(m_Sector, -speed); P_ChangeSector (m_Sector, crush); return crushed; } } break; } break; case 1: // CEILING switch(direction) { case -1: // DOWN lastpos = P_CeilingHeight(m_Sector); if (lastpos - speed < dest) { P_SetCeilingHeight(m_Sector, dest); flag = P_ChangeSector (m_Sector, crush); if (flag == true) { P_SetCeilingHeight(m_Sector, lastpos); P_ChangeSector (m_Sector, crush); } return pastdest; } else { // COULD GET CRUSHED P_SetCeilingHeight(m_Sector, lastpos - speed); flag = P_ChangeSector (m_Sector, crush); if (flag == true) { if (crush) return crushed; P_SetCeilingHeight(m_Sector, lastpos); P_ChangeSector (m_Sector, crush); return crushed; } } break; case 1: // UP lastpos = P_CeilingHeight(m_Sector); if (lastpos + speed > dest) { P_SetCeilingHeight(m_Sector, dest); flag = P_ChangeSector (m_Sector, crush); if (flag == true) { P_SetCeilingHeight(m_Sector, lastpos); P_ChangeSector (m_Sector, crush); } return pastdest; } else { P_SetCeilingHeight(m_Sector, lastpos + speed); flag = P_ChangeSector (m_Sector, crush); // UNUSED #if 0 if (flag == true) { P_ChangeCeilingHeight(m_Sector, -speed); P_ChangeSector (m_Sector, crush); return crushed; } #endif } break; } break; } return ok; }
// // R_AddLine // Clips the given segment // and adds any visible pieces to the line list. // void R_AddLine (seg_t *line) { int x1; int x2; angle_t angle1; angle_t angle2; angle_t span; angle_t tspan; static sector_t tempsec; // killough 3/8/98: ceiling/water hack curline = line; // [RH] Color if not texturing line dc_color = ((line - segs) & 31) * 4; // OPTIMIZE: quickly reject orthogonal back sides. angle1 = R_PointToAngle (line->v1->x, line->v1->y); angle2 = R_PointToAngle (line->v2->x, line->v2->y); // Clip to view edges. // OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW). span = angle1 - angle2; // Back side? I.e. backface culling? if (span >= ANG180) return; // Global angle needed by segcalc. rw_angle1 = angle1; angle1 -= viewangle; angle2 -= viewangle; tspan = angle1 + clipangle; if (tspan > 2*clipangle) { // Totally off the left edge? if (tspan - 2*clipangle >= span) return; angle1 = clipangle; } tspan = clipangle - angle2; if (tspan > 2*clipangle) { // Totally off the left edge? if (tspan - 2*clipangle >= span) return; angle2 = (unsigned) (-(int)clipangle); } // The seg is in the view range, but not necessarily visible. angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; // killough 1/31/98: Here is where "slime trails" can SOMETIMES occur: x1 = viewangletox[angle1]; x2 = viewangletox[angle2]; // Does not cross a pixel? if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness return; rw_start = x1; rw_stop = x2 - 1; rw_frontcz1 = P_CeilingHeight(line->v1->x, line->v1->y, frontsector); rw_frontfz1 = P_FloorHeight(line->v1->x, line->v1->y, frontsector); rw_frontcz2 = P_CeilingHeight(line->v2->x, line->v2->y, frontsector); rw_frontfz2 = P_FloorHeight(line->v2->x, line->v2->y, frontsector); backsector = line->backsector; // Single sided line? if (!backsector) goto clipsolid; // killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water backsector = R_FakeFlat (backsector, &tempsec, NULL, NULL, true); rw_backcz1 = P_CeilingHeight(line->v1->x, line->v1->y, backsector); rw_backfz1 = P_FloorHeight(line->v1->x, line->v1->y, backsector); rw_backcz2 = P_CeilingHeight(line->v2->x, line->v2->y, backsector); rw_backfz2 = P_FloorHeight(line->v2->x, line->v2->y, backsector); // [SL] Check for closed doors or other scenarios that would make this // line seg solid. // // This fixes the automap floor height bug -- killough 1/18/98: // killough 4/7/98: optimize: save result in doorclosed for use in r_segs.c if (!(line->linedef->flags & ML_TWOSIDED) || (rw_backcz1 <= rw_frontfz1 && rw_backcz2 <= rw_frontfz2) || (rw_backfz1 >= rw_frontcz1 && rw_backfz2 >= rw_frontcz2) || // handle a case where the backsector slopes one direction // and the frontsector slopes the opposite: (rw_backcz1 <= rw_frontfz1 && rw_backfz1 >= rw_frontcz1) || (rw_backcz2 <= rw_frontfz2 && rw_backfz2 >= rw_frontcz2) || // if door is closed because back is shut: ((rw_backcz1 <= rw_backfz1 && rw_backcz2 <= rw_backfz2) && // preserve a kind of transparent door/lift special effect: ((rw_backcz1 >= rw_frontcz1 && rw_backcz2 >= rw_frontcz2) || line->sidedef->toptexture) && ((rw_backfz1 <= rw_frontfz1 && rw_backfz2 <= rw_frontfz2) || line->sidedef->bottomtexture) && // properly render skies (consider door "open" if both ceilings are sky): (backsector->ceilingpic !=skyflatnum || frontsector->ceilingpic!=skyflatnum))) { doorclosed = true; goto clipsolid; } else { doorclosed = false; } // Window. if (!P_IdenticalPlanes(&frontsector->ceilingplane, &backsector->ceilingplane) || !P_IdenticalPlanes(&frontsector->floorplane, &backsector->floorplane)) goto clippass; // Reject empty lines used for triggers // and special events. // Identical floor and ceiling on both sides, // identical light levels on both sides, // and no middle texture. if (backsector->lightlevel == frontsector->lightlevel && backsector->floorpic == frontsector->floorpic && backsector->ceilingpic == frontsector->ceilingpic && curline->sidedef->midtexture == 0 // killough 3/7/98: Take flats offsets into account: && backsector->floor_xoffs == frontsector->floor_xoffs && (backsector->floor_yoffs + backsector->base_floor_yoffs) == (frontsector->floor_yoffs + backsector->base_floor_yoffs) && backsector->ceiling_xoffs == frontsector->ceiling_xoffs && (backsector->ceiling_yoffs + backsector->base_ceiling_yoffs) == (frontsector->ceiling_yoffs + frontsector->base_ceiling_yoffs) // killough 4/16/98: consider altered lighting && backsector->floorlightsec == frontsector->floorlightsec && backsector->ceilinglightsec == frontsector->ceilinglightsec // [RH] Also consider colormaps && backsector->floorcolormap == frontsector->floorcolormap && backsector->ceilingcolormap == frontsector->ceilingcolormap // [RH] and scaling && backsector->floor_xscale == frontsector->floor_xscale && backsector->floor_yscale == frontsector->floor_yscale && backsector->ceiling_xscale == frontsector->ceiling_xscale && backsector->ceiling_yscale == frontsector->ceiling_yscale // [RH] and rotation && (backsector->floor_angle + backsector->base_floor_angle) == (frontsector->floor_angle + frontsector->base_floor_angle) && (backsector->ceiling_angle + backsector->base_ceiling_angle) == (frontsector->ceiling_angle + frontsector->base_ceiling_angle) ) { return; } clippass: R_ClipPassWallSegment (x1, x2-1); return; clipsolid: R_ClipSolidWallSegment (x1, x2-1); }
// // T_VerticalDoor // void DDoor::RunThink () { fixed_t ceilingheight = P_CeilingHeight(m_Sector); fixed_t floorheight = P_FloorHeight(m_Sector); EResult res; switch (m_Status) { case finished: PlayDoorSound(); // fall through case destroy: P_SetDoorDestroy(this); return; case waiting: // WAITING if (!--m_TopCountdown) { switch (m_Type) { case doorRaise: // time to go back down m_Status = closing; PlayDoorSound(); break; case doorCloseWaitOpen: m_Status = opening; PlayDoorSound(); break; default: break; } } break; case init: // INITIAL WAIT if (!--m_TopCountdown) { switch (m_Type) { case doorRaiseIn5Mins: m_Type = doorRaise; m_Status = opening; PlayDoorSound(); break; default: break; } } break; case closing: res = MoveCeiling(m_Speed, floorheight, false, -1); if (m_Line && m_Line->id) { EV_LightTurnOnPartway(m_Line->id, FixedDiv(ceilingheight - floorheight, m_TopHeight - floorheight)); } if (res == pastdest) { //S_StopSound (m_Sector->soundorg); SN_StopSequence (m_Sector); switch (m_Type) { case doorRaise: case doorClose: m_Status = finished; return; case doorCloseWaitOpen: m_TopCountdown = m_TopWait; m_Status = waiting; break; default: break; } if (m_Line && m_Line->id) { EV_LightTurnOnPartway(m_Line->id, 0); } } else if (res == crushed) { switch (m_Type) { case doorClose: // DO NOT GO BACK UP! break; default: m_Status = reopening; PlayDoorSound(); break; } } break; case reopening: case opening: res = MoveCeiling(m_Speed, m_TopHeight, false, 1); if (m_Line && m_Line->id) { EV_LightTurnOnPartway(m_Line->id, FixedDiv(ceilingheight - floorheight, m_TopHeight - floorheight)); } if (res == pastdest) { //S_StopSound (m_Sector->soundorg); SN_StopSequence (m_Sector); switch (m_Type) { case doorRaise: // wait at top m_TopCountdown = m_TopWait; m_Status = waiting; break; case doorCloseWaitOpen: case doorOpen: m_Status = finished; return; default: break; } if (m_Line && m_Line->id) { EV_LightTurnOnPartway(m_Line->id, FRACUNIT); } } break; default: break; } }
DPillar::DPillar (sector_t *sector, EPillar type, fixed_t speed, fixed_t height, fixed_t height2, bool crush) : DMover (sector), m_Status(init) { fixed_t ceilingdist, floordist; sector->floordata = sector->ceilingdata = this; fixed_t floorheight = P_FloorHeight(sector); fixed_t ceilingheight = P_CeilingHeight(sector); m_Type = type; m_Crush = crush; if (type == pillarBuild) { // If the pillar height is 0, have the floor and ceiling meet halfway if (height == 0) { m_FloorTarget = m_CeilingTarget = (ceilingheight - floorheight) / 2 + floorheight; floordist = m_FloorTarget - floorheight; } else { m_FloorTarget = m_CeilingTarget = floorheight + height; floordist = height; } ceilingdist = ceilingheight - m_CeilingTarget; } else { // If one of the heights is 0, figure it out based on the // surrounding sectors if (height == 0) { m_FloorTarget = P_FindLowestFloorSurrounding (sector); floordist = floorheight - m_FloorTarget; } else { floordist = height; m_FloorTarget = floorheight - height; } if (height2 == 0) { m_CeilingTarget = P_FindHighestCeilingSurrounding (sector); ceilingdist = m_CeilingTarget - ceilingheight; } else { m_CeilingTarget = ceilingheight + height2; ceilingdist = height2; } } // The speed parameter applies to whichever part of the pillar // travels the farthest. The other part's speed is then set so // that it arrives at its destination at the same time. if (floordist > ceilingdist) { m_FloorSpeed = speed; m_CeilingSpeed = FixedDiv (FixedMul (speed, ceilingdist), floordist); } else { m_CeilingSpeed = speed; m_FloorSpeed = FixedDiv (FixedMul (speed, floordist), ceilingdist); } PlayPillarSound(); }