// // If player's view height is underneath fake floor, lower the // drawn ceiling to be just under the floor height, and replace // the drawn floor and ceiling textures, and light level, with // the control sector's. // // Similar for ceiling, only reflected. // 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; if (ceilinglightlevel) *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) { const sector_t *s = §ors[sec->heightsec]; mobj_t *viewmobj = viewplayer->mo; INT32 heightsec; boolean underwater; if (splitscreen && viewplayer == &players[secondarydisplayplayer] && camera2.chase) heightsec = R_PointInSubsector(camera2.x, camera2.y)->sector->heightsec; else if (camera.chase && viewplayer == &players[displayplayer]) heightsec = R_PointInSubsector(camera.x, camera.y)->sector->heightsec; else if (viewmobj) heightsec = R_PointInSubsector(viewmobj->x, viewmobj->y)->sector->heightsec; else return sec; underwater = heightsec != -1 && viewz <= sectors[heightsec].floorheight; // Replace sector being drawn, with a copy to be hacked *tempsec = *sec; // Replace floor and ceiling height with other sector's heights. 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 tempsec->floorpic = s->floorpic; tempsec->floor_xoffs = s->floor_xoffs; tempsec->floor_yoffs = s->floor_yoffs; tempsec->floorpic_angle = s->floorpic_angle; if (underwater) { if (s->ceilingpic == skyflatnum) { tempsec->floorheight = tempsec->ceilingheight+1; tempsec->ceilingpic = tempsec->floorpic; tempsec->ceiling_xoffs = tempsec->floor_xoffs; tempsec->ceiling_yoffs = tempsec->floor_yoffs; tempsec->ceilingpic_angle = tempsec->floorpic_angle; } else { tempsec->ceilingpic = s->ceilingpic; tempsec->ceiling_xoffs = s->ceiling_xoffs; tempsec->ceiling_yoffs = s->ceiling_yoffs; tempsec->ceilingpic_angle = s->ceilingpic_angle; } mapnum = s->bottommap; } tempsec->lightlevel = s->lightlevel; if (floorlightlevel) *floorlightlevel = s->floorlightsec == -1 ? s->lightlevel : sectors[s->floorlightsec].lightlevel; if (ceilinglightlevel) *ceilinglightlevel = s->ceilinglightsec == -1 ? s->lightlevel : sectors[s->ceilinglightsec].lightlevel; } else if (heightsec != -1 && viewz >= sectors[heightsec].ceilingheight && sec->ceilingheight > s->ceilingheight) { // Above-ceiling hack tempsec->ceilingheight = s->ceilingheight; tempsec->floorheight = s->ceilingheight + 1; tempsec->floorpic = tempsec->ceilingpic = s->ceilingpic; tempsec->floor_xoffs = tempsec->ceiling_xoffs = s->ceiling_xoffs; 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; tempsec->floorpic = tempsec->ceilingpic; tempsec->floor_xoffs = tempsec->ceiling_xoffs; tempsec->floor_yoffs = tempsec->ceiling_yoffs; tempsec->floorpic_angle = tempsec->ceilingpic_angle; } else { tempsec->ceilingheight = sec->ceilingheight; tempsec->floorpic = s->floorpic; tempsec->floor_xoffs = s->floor_xoffs; tempsec->floor_yoffs = s->floor_yoffs; tempsec->floorpic_angle = s->floorpic_angle; } tempsec->lightlevel = s->lightlevel; if (floorlightlevel) *floorlightlevel = s->floorlightsec == -1 ? s->lightlevel : sectors[s->floorlightsec].lightlevel; if (ceilinglightlevel) *ceilinglightlevel = s->ceilinglightsec == -1 ? s->lightlevel : sectors[s->ceilinglightsec].lightlevel; } sec = tempsec; } if (mapnum >= 0 && (size_t)mapnum < num_extra_colormaps) sec->extra_colormap = &extra_colormaps[mapnum]; else sec->extra_colormap = NULL; return sec; }
/* * Returns true if it the thing can be positioned in the coordinates. */ boolean P_CheckPosXYZ(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z) { int xl, xh; int yl, yh; int bx, by; subsector_t *newsubsec; checkpos_data_t data; boolean result = true; blockingMobj = NULL; thing->onmobj = NULL; thing->wallhit = false; // Prepare the data struct. data.thing = thing; data.flags = thing->ddflags; data.x = x; data.y = y; data.z = z; data.height = thing->height; data.box[BOXTOP] = y + thing->radius; data.box[BOXBOTTOM] = y - thing->radius; data.box[BOXRIGHT] = x + thing->radius; data.box[BOXLEFT] = x - thing->radius; newsubsec = R_PointInSubsector(x, y); // The base floor / ceiling is from the subsector // that contains the point. // Any contacted lines the step closer together // will adjust them. data.floorz = data.dropoffz = newsubsec->sector->floorheight; data.ceilingz = newsubsec->sector->ceilingheight; validcount++; // Check things first, possibly picking things up. // The bounding box is extended by MAXRADIUS // because mobj_ts are grouped into mapblocks // based on their origin point, and can overlap // into adjacent blocks by up to MAXRADIUS units. xl = (data.box[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; xh = (data.box[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; yl = (data.box[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; yh = (data.box[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; if(!dontHitMobjs) { for(bx = xl; bx <= xh; bx++) for(by = yl; by <= yh; by++) if(!P_BlockThingsIterator(bx, by, PIT_CheckThing, &data)) { result = false; goto checkpos_done; } } // check lines xl = (data.box[BOXLEFT] - bmaporgx) >> MAPBLOCKSHIFT; xh = (data.box[BOXRIGHT] - bmaporgx) >> MAPBLOCKSHIFT; yl = (data.box[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT; yh = (data.box[BOXTOP] - bmaporgy) >> MAPBLOCKSHIFT; for(bx = xl; bx <= xh; bx++) for(by = yl; by <= yh; by++) if(!P_BlockLinesIterator(bx, by, PIT_CheckLine, &data)) { result = false; goto checkpos_done; } checkpos_done: tmceilingz = data.ceilingz; tmfloorz = data.floorz; tmdropoffz = data.dropoffz; return result; }
void ADynamicLight::LinkLight() { // mark the old light nodes FLightNode * node; node = touching_sides; while (node) { node->lightsource = NULL; node = node->nextTarget; } node = touching_subsectors; while (node) { node->lightsource = NULL; node = node->nextTarget; } node = touching_sector; while (node) { node->lightsource = NULL; node = node->nextTarget; } if (radius>0) { // passing in radius*radius allows us to do a distance check without any calls to sqrtf subsector_t * subSec = R_PointInSubsector(x, y); if (subSec) { float fradius = FIXED2FLOAT(radius); ::validcount++; CollectWithinRadius(subSec, fradius*fradius); } } // Now delete any nodes that won't be used. These are the ones where // m_thing is still NULL. node = touching_sides; while (node) { if (node->lightsource == NULL) { node = DeleteLightNode(node); } else node = node->nextTarget; } node = touching_subsectors; while (node) { if (node->lightsource == NULL) { node = DeleteLightNode(node); } else node = node->nextTarget; } node = touching_sector; while (node) { if (node->lightsource == NULL) { node = DeleteLightNode(node); } else node = node->nextTarget; } }
mobj_t *P_SpawnTeleFog(int x, int y) { subsector_t *ss = R_PointInSubsector(x, y); return P_SpawnMobj(x, y, ss->sector->floorheight + TELEFOGHEIGHT, MT_TFOG); }
/* * A light decoration is created in the specified coordinates. * Does largely the same thing as DL_AddLuminous(). */ void Rend_AddLightDecoration(float pos[3], ded_decorlight_t * def, float brightness, boolean isWall, DGLuint decorMap) { decorsource_t *source; lumobj_t *lum; float distance = Rend_PointDist3D(pos); float fadeMul = 1, flareMul = 1; float maxDist = (isWall ? decorWallMaxDist : decorPlaneMaxDist); int i; // Is the point in range? if(distance > maxDist) return; // Close enough to the maximum distance, the lights fade out. if(distance > .67f * maxDist) { fadeMul = (maxDist - distance) / (.33f * maxDist); } // Apply the brightness factor (was calculated using sector lightlevel). fadeMul *= brightness * (isWall ? decorWallFactor : decorPlaneFactor); // Brightness drops as the angle gets too big. if(def->elevation < 2 && decorFadeAngle > 0) // Close the surface? { float vector[3] = { pos[VX] - vx, pos[VZ] - vy, pos[VY] - vz }; float dot; M_Normalize(vector); dot = -(surfaceNormal[VX] * vector[VX] + surfaceNormal[VY] * vector[VY] + surfaceNormal[VZ] * vector[VZ]); if(dot < decorFadeAngle / 2) { flareMul = 0; } else if(dot < 3 * decorFadeAngle) { flareMul *= (dot - decorFadeAngle / 2) / (2.5f * decorFadeAngle); } } if(fadeMul <= 0) return; if(!(source = Rend_NewLightDecorationSource())) return; // Out of sources! // Initialize the essentials in the dummy mobj. source->thing.x = pos[VX] * FRACUNIT; source->thing.y = pos[VY] * FRACUNIT; source->thing.z = pos[VZ] * FRACUNIT; source->thing.frame = FF_FULLBRIGHT; source->thing.halofactor = 0xff; // Assumed visible. source->thing.subsector = R_PointInSubsector(source->thing.x, source->thing.y); // Fill in the data for a new luminous object. source->thing.light = DL_NewLuminous(); lum = DL_GetLuminous(source->thing.light); lum->thing = &source->thing; lum->center = 0; lum->flags = LUMF_CLIPPED; lum->tex = def->sides.tex; lum->ceilTex = def->up.tex; lum->floorTex = def->down.tex; // These are the same rules as in DL_ThingRadius(). lum->radius = def->radius * 40 * dlRadFactor; // Don't make a too small or too large light. if(lum->radius > dlMaxRad) lum->radius = dlMaxRad; if(def->halo_radius > 0) { lum->flareSize = def->halo_radius * 60 * (50 + haloSize) / 100.0f; if(lum->flareSize < 1) lum->flareSize = 1; } else { lum->flareSize = 0; } // This light source is associated with a decoration map, if one is // available. lum->decorMap = decorMap; // Zero = Texture chosen automatically. lum->flareTex = def->flare_texture; lum->flareMul = flareMul; for(i = 0; i < 3; i++) lum->rgb[i] = (byte) (255 * def->color[i] * fadeMul); // Approximate the distance. lum->distance = P_ApproxDistance3(source->thing.x - viewx, source->thing.y - viewy, source->thing.z - viewz); }