static void GetPortalTransition(DVector3 &pos, sector_t *&sec) { bool moved = false; double testz = pos.Z; while (!sec->PortalBlocksMovement(sector_t::ceiling)) { if (pos.Z > sec->GetPortalPlaneZ(sector_t::ceiling)) { pos += sec->GetPortalDisplacement(sector_t::ceiling); sec = P_PointInSector(pos); moved = true; } else break; } if (!moved) { while (!sec->PortalBlocksMovement(sector_t::floor)) { if (pos.Z <= sec->GetPortalPlaneZ(sector_t::floor)) { pos += sec->GetPortalDisplacement(sector_t::floor); sec = P_PointInSector(pos); } else break; } } }
void AActor::UpdateRenderSectorList() { static const double SPRITE_SPACE = 64.; if (Pos() != OldRenderPos && !(flags & MF_NOSECTOR)) { // Only check if the map contains line portals ClearRenderLineList(); if (level.PortalBlockmap.containsLines && Pos().XY() != OldRenderPos.XY()) { int bx = level.blockmap.GetBlockX(X()); int by = level.blockmap.GetBlockY(Y()); FBoundingBox bb(X(), Y(), MIN(radius*1.5, 128.)); // Don't go further than 128 map units, even for large actors // Are there any portals near the actor's position? if (level.blockmap.isValidBlock(bx, by) && level.PortalBlockmap(bx, by).neighborContainsLines) { // Go through the entire list. In most cases this is faster than setting up a blockmap iterator for (auto &p : level.linePortals) { if (p.mType == PORTT_VISUAL) continue; if (bb.inRange(p.mOrigin) && bb.BoxOnLineSide(p.mOrigin)) { touching_lineportallist = P_AddPortalnode(&p, this, touching_lineportallist); } } } } sector_t *sec = Sector; double lasth = -FLT_MAX; ClearRenderSectorList(); while (!sec->PortalBlocksMovement(sector_t::ceiling)) { double planeh = sec->GetPortalPlaneZ(sector_t::ceiling); if (planeh <= lasth) break; // broken setup. if (Top() + SPRITE_SPACE < planeh) break; lasth = planeh; DVector2 newpos = Pos() + sec->GetPortalDisplacement(sector_t::ceiling); sec = P_PointInSector(newpos); touching_sectorportallist = P_AddSecnode(sec, this, touching_sectorportallist, sec->sectorportal_thinglist); } sec = Sector; lasth = FLT_MAX; while (!sec->PortalBlocksMovement(sector_t::floor)) { double planeh = sec->GetPortalPlaneZ(sector_t::floor); if (planeh >= lasth) break; // broken setup. if (Z() - SPRITE_SPACE > planeh) break; lasth = planeh; DVector2 newpos = Pos() + sec->GetPortalDisplacement(sector_t::floor); sec = P_PointInSector(newpos); touching_sectorportallist = P_AddSecnode(sec, this, touching_sectorportallist, sec->sectorportal_thinglist); } } }
void FTraceInfo::EnterLinePortal(FPathTraverse &pt, intercept_t *in) { line_t *li = in->d.line; FLinePortal *port = li->getPortal(); double frac = in->frac + EQUAL_EPSILON; double enterdist = MaxDist * frac; DVector3 exit = Start + MaxDist * in->frac * Vec; P_TranslatePortalXY(li, Start.X, Start.Y); P_TranslatePortalZ(li, Start.Z); P_TranslatePortalVXVY(li, Vec.X, Vec.Y); P_TranslatePortalZ(li, limitz); CurSector = P_PointInSector(Start + enterdist * Vec); EnterDist = enterdist; inshootthrough = true; startfrac = frac; Results->unlinked |= (port->mType != PORTT_LINKED); pt.PortalRelocate(in, ptflags); if ((TraceFlags & TRACE_ReportPortals) && TraceCallback != NULL) { enterdist = MaxDist * in->frac; Results->HitType = TRACE_CrossingPortal; Results->HitPos = exit; P_TranslatePortalXY(li, exit.X, exit.Y); P_TranslatePortalZ(li, exit.Z); Results->SrcFromTarget = exit; Results->HitVector = Vec; TraceCallback(*Results, TraceCallbackData); } }
void FTraceInfo::EnterSectorPortal(FPathTraverse &pt, int position, double frac, sector_t *entersec) { DVector2 displacement = entersec->GetPortalDisplacement(position);; double enterdist = MaxDist * frac; DVector3 exit = Start + enterdist * Vec; DVector3 enter = exit + displacement; Start += displacement; CurSector = P_PointInSector(enter); inshootthrough = true; startfrac = frac; EnterDist = enterdist; pt.PortalRelocate(entersec->GetPortal(position)->mDisplacement, ptflags, frac); if ((TraceFlags & TRACE_ReportPortals) && TraceCallback != NULL) { enterdist = MaxDist * frac; Results->HitType = TRACE_CrossingPortal; Results->HitPos = exit; Results->SrcFromTarget = enter; Results->HitVector = Vec; TraceCallback(*Results, TraceCallbackData); } Setup3DFloors(); }
static void DrawCoordinates(player_t * CPlayer) { DVector3 pos; char coordstr[18]; int h = SmallFont->GetHeight()+1; if (!map_point_coordinates || !automapactive) { pos = CPlayer->mo->Pos(); } else { DVector2 apos = AM_GetPosition(); double z = P_PointInSector(apos)->floorplane.ZatPoint(apos); pos = DVector3(apos, z); } int vwidth, vheight; if (active_con_scaletext() == 0) { vwidth = SCREENWIDTH / 2; vheight = SCREENHEIGHT / 2; } else { vwidth = SCREENWIDTH / active_con_scaletext(); vheight = SCREENHEIGHT / active_con_scaletext(); } int xpos = vwidth - SmallFont->StringWidth("X: -00000")-6; int ypos = 18; screen->DrawText(SmallFont, hudcolor_titl, vwidth - 6 - SmallFont->StringWidth(level.MapName), ypos, level.MapName, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); screen->DrawText(SmallFont, hudcolor_titl, vwidth - 6 - SmallFont->StringWidth(level.LevelName), ypos + h, level.LevelName, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); mysnprintf(coordstr, countof(coordstr), "X: %d", int(pos.X)); screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos+2*h, coordstr, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); mysnprintf(coordstr, countof(coordstr), "Y: %d", int(pos.Y)); screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos+3*h, coordstr, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); mysnprintf(coordstr, countof(coordstr), "Z: %d", int(pos.Z)); screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos+4*h, coordstr, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); }
void P_SpawnSlopeMakers (FMapThing *firstmt, FMapThing *lastmt, const int *oldvertextable) { FMapThing *mt; for (mt = firstmt; mt < lastmt; ++mt) { if (mt->info != NULL && mt->info->Type == NULL && (mt->info->Special >= SMT_SlopeFloorPointLine && mt->info->Special <= SMT_VavoomCeiling)) { DVector3 pos = mt->pos; secplane_t *refplane; sector_t *sec; bool ceiling; sec = P_PointInSector (mt->pos); if (mt->info->Special == SMT_SlopeCeilingPointLine || mt->info->Special == SMT_VavoomCeiling || mt->info->Special == SMT_SetCeilingSlope) { refplane = &sec->ceilingplane; ceiling = true; } else { refplane = &sec->floorplane; ceiling = false; } pos.Z = refplane->ZatPoint (mt->pos) + mt->pos.Z; if (mt->info->Special <= SMT_SlopeCeilingPointLine) { // SlopeFloorPointLine and SlopCeilingPointLine P_SlopeLineToPoint (mt->args[0], pos, ceiling); } else if (mt->info->Special <= SMT_SetCeilingSlope) { // SetFloorSlope and SetCeilingSlope P_SetSlope (refplane, ceiling, mt->angle, mt->args[0], pos); } else { // VavoomFloor and VavoomCeiling (these do not perform any sector height adjustment - z is absolute) P_VavoomSlope(sec, mt->thingid, mt->pos, ceiling); } mt->EdNum = 0; } } for (mt = firstmt; mt < lastmt; ++mt) { if (mt->info != NULL && mt->info->Type == NULL && (mt->info->Special == SMT_CopyFloorPlane || mt->info->Special == SMT_CopyCeilingPlane)) { P_CopyPlane (mt->args[0], mt->pos, mt->info->Special == SMT_CopyCeilingPlane); mt->EdNum = 0; } } P_SetSlopesFromVertexHeights(firstmt, lastmt, oldvertextable); }
DEFINE_ACTION_FUNCTION(AActor, A_Burnination) { PARAM_ACTION_PROLOGUE; self->Vel.Z -= 8; self->Vel.X += (pr_phburn.Random2 (3)); self->Vel.Y += (pr_phburn.Random2 (3)); S_Sound (self, CHAN_VOICE, "world/largefire", 1, ATTN_NORM); // Only the main fire spawns more. if (!(self->flags & MF_DROPPED)) { // Original x and y offsets seemed to be like this: // x + (((pr_phburn() + 12) & 31) << F.RACBITS); // // But that creates a lop-sided burn because it won't use negative offsets. int xofs, xrand = pr_phburn(); int yofs, yrand = pr_phburn(); // Adding 12 is pointless if you're going to mask it afterward. xofs = xrand & 31; if (xrand & 128) { xofs = -xofs; } yofs = yrand & 31; if (yrand & 128) { yofs = -yofs; } DVector2 pos = self->Vec2Offset((double)xofs, (double)yofs); sector_t * sector = P_PointInSector(pos); // The sector's floor is too high so spawn the flame elsewhere. if (sector->floorplane.ZatPoint(pos) > self->Z() + self->MaxStepHeight) { pos = self->Pos(); } AActor *drop = Spawn<APhosphorousFire> (DVector3(pos, self->Z() + 4.), ALLOW_REPLACE); if (drop != NULL) { drop->Vel.X = self->Vel.X + pr_phburn.Random2 (7); drop->Vel.Y = self->Vel.Y + pr_phburn.Random2 (7); drop->Vel.Z = self->Vel.Z - 1; drop->reactiontime = (pr_phburn() & 3) + 2; drop->flags |= MF_DROPPED; } } return 0; }
int P_Find3DFloor(sector_t * sec, const DVector3 &pos, bool above, bool floor, double &cmpz) { // If no sector given, find the one appropriate if (sec == NULL) sec = P_PointInSector(pos); // Above normal ceiling cmpz = sec->ceilingplane.ZatPoint(pos); if (pos.Z >= cmpz) return -1; // Below normal floor cmpz = sec->floorplane.ZatPoint(pos); if (pos.Z <= cmpz) return -1; // Looking through planes from top to bottom for (int i = 0; i < (signed)sec->e->XFloor.ffloors.Size(); ++i) { F3DFloor *rover = sec->e->XFloor.ffloors[i]; // We are only interested in solid 3D floors here if(!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; if (above) { // z is above that floor if (floor && (pos.Z >= (cmpz = rover->top.plane->ZatPoint(pos)))) return i - 1; // z is above that ceiling if (pos.Z >= (cmpz = rover->bottom.plane->ZatPoint(pos))) return i - 1; } else // below { // z is below that ceiling if (!floor && (pos.Z <= (cmpz = rover->bottom.plane->ZatPoint(pos)))) return i; // z is below that floor if (pos.Z <= (cmpz = rover->top.plane->ZatPoint(pos))) return i; } } // Failsafe return -1; }
void ASkyCamCompat::BeginPlay () { if (Sector == NULL) { Printf("Sector not initialized for SkyCamCompat\n"); Sector = P_PointInSector(x, y); } if (Sector) { line_t * refline = NULL; for (short i = 0; i < Sector->linecount; i++) { refline = Sector->lines[i]; if (refline->special == Sector_SetPortal && refline->args[1] == 2) { // We found the setup linedef for this skybox, so let's use it for our init. int skybox_id = refline->args[0]; // Then, change the alpha alpha = refline->args[4]; // Finally, skyboxify all tagged sectors // This involves changing their texture to the sky flat, because while // EE works with any texture for its skybox portals, ZDoom doesn't. for (int secnum =-1; (secnum = P_FindSectorFromTag (skybox_id, secnum)) != -1; ) { // plane: 0=floor, 1=ceiling, 2=both if (refline->args[2] == 1 || refline->args[2] == 2) { sectors[secnum].CeilingSkyBox = this; sectors[secnum].SetTexture(sector_t::ceiling, skyflatnum, false); } if (refline->args[2] == 0 || refline->args[2] == 2) { sectors[secnum].FloorSkyBox = this; sectors[secnum].SetTexture(sector_t::floor, skyflatnum, false); } } } } } // Do not call the SkyViewpoint's super method because it would trash our setup AActor::BeginPlay(); }
static void DrawCoordinates(player_t * CPlayer) { fixed_t x; fixed_t y; fixed_t z; char coordstr[18]; int h = SmallFont->GetHeight()+1; if (!map_point_coordinates || !automapactive) { x=CPlayer->mo->X(); y=CPlayer->mo->Y(); z=CPlayer->mo->Z(); } else { AM_GetPosition(x,y); z = P_PointInSector(x, y)->floorplane.ZatPoint(x, y); } int vwidth = con_scaletext==0? SCREENWIDTH : SCREENWIDTH/2; int vheight = con_scaletext==0? SCREENHEIGHT : SCREENHEIGHT/2; int xpos = vwidth - SmallFont->StringWidth("X: -00000")-6; int ypos = 18; mysnprintf(coordstr, countof(coordstr), "X: %d", x>>FRACBITS); screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos, coordstr, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); mysnprintf(coordstr, countof(coordstr), "Y: %d", y>>FRACBITS); screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos+h, coordstr, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); mysnprintf(coordstr, countof(coordstr), "Z: %d", z>>FRACBITS); screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos+2*h, coordstr, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); }
bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, bool useFog, bool sourceFog, bool keepOrientation, bool bHaltVelocity, bool keepHeight) { bool predicting = (thing->player && (thing->player->cheats & CF_PREDICTING)); fixed_t oldx; fixed_t oldy; fixed_t oldz; fixed_t aboveFloor; player_t *player; angle_t an; sector_t *destsect; bool resetpitch = false; fixed_t floorheight, ceilingheight; fixed_t missilespeed; oldx = thing->x; oldy = thing->y; oldz = thing->z; aboveFloor = thing->z - thing->floorz; destsect = P_PointInSector (x, y); // killough 5/12/98: exclude voodoo dolls: player = thing->player; if (player && player->mo != thing) player = NULL; floorheight = destsect->floorplane.ZatPoint (x, y); ceilingheight = destsect->ceilingplane.ZatPoint (x, y); if (thing->flags & MF_MISSILE) { // We don't measure z velocity, because it doesn't change. missilespeed = xs_CRoundToInt(TVector2<double>(thing->velx, thing->vely).Length()); } if (keepHeight) { z = floorheight + aboveFloor; } else if (z == ONFLOORZ) { if (player) { if (thing->flags & MF_NOGRAVITY && aboveFloor) { z = floorheight + aboveFloor; if (z + thing->height > ceilingheight) { z = ceilingheight - thing->height; } } else { z = floorheight; if (!keepOrientation) { resetpitch = false; } } } else if (thing->flags & MF_MISSILE) { z = floorheight + aboveFloor; if (z + thing->height > ceilingheight) { z = ceilingheight - thing->height; } } else { z = floorheight; } } if (!P_TeleportMove (thing, x, y, z, false)) { return false; } if (player) { player->viewz = thing->z + player->viewheight; if (resetpitch) { player->mo->pitch = 0; } } if (!keepOrientation) { thing->angle = angle; } else { angle = thing->angle; } // Spawn teleport fog at source and destination if (sourceFog && !predicting) { fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; P_SpawnTeleportFog(thing, oldx, oldy, oldz, true, true); //Passes the actor through which then pulls the TeleFog metadate types based on properties. } if (useFog) { if (!predicting) { fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; an = angle >> ANGLETOFINESHIFT; P_SpawnTeleportFog(thing, x + 20 * finecosine[an], y + 20 * finesine[an], thing->z + fogDelta, false, true); } if (thing->player) { // [RH] Zoom player's field of vision // [BC] && bHaltVelocity. if (telezoom && thing->player->mo == thing && bHaltVelocity) thing->player->FOV = MIN (175.f, thing->player->DesiredFOV + 45.f); } }
static void P_CopyPlane (int tag, const DVector2 &pos, bool copyCeil) { sector_t *dest = P_PointInSector (pos); P_CopyPlane(tag, dest, copyCeil); }
bool P_Teleport (AActor *thing, DVector3 pos, DAngle angle, int flags) { bool predicting = (thing->player && (thing->player->cheats & CF_PREDICTING)); DVector3 old; double aboveFloor; player_t *player; sector_t *destsect; bool resetpitch = false; double floorheight, ceilingheight; double missilespeed = 0; old = thing->Pos(); aboveFloor = thing->Z() - thing->floorz; destsect = P_PointInSector (pos); // killough 5/12/98: exclude voodoo dolls: player = thing->player; if (player && player->mo != thing) player = NULL; floorheight = destsect->floorplane.ZatPoint (pos); ceilingheight = destsect->ceilingplane.ZatPoint (pos); if (thing->flags & MF_MISSILE) { // We don't measure z velocity, because it doesn't change. missilespeed = thing->VelXYToSpeed(); } if (flags & TELF_KEEPHEIGHT) { pos.Z = floorheight + aboveFloor; } else if (pos.Z == ONFLOORZ) { if (player) { if (thing->flags & MF_NOGRAVITY && aboveFloor) { pos.Z = floorheight + aboveFloor; if (pos.Z + thing->Height > ceilingheight) { pos.Z = ceilingheight - thing->Height; } } else { pos.Z = floorheight; if (!(flags & TELF_KEEPORIENTATION)) { resetpitch = false; } } } else if (thing->flags & MF_MISSILE) { pos.Z = floorheight + aboveFloor; if (pos.Z + thing->Height > ceilingheight) { pos.Z = ceilingheight - thing->Height; } } else { pos.Z = floorheight; } } if (!P_TeleportMove (thing, pos, false)) { return false; } if (player) { player->viewz = thing->Z() + player->viewheight; if (resetpitch) { player->mo->Angles.Pitch = 0.; } } if (!(flags & TELF_KEEPORIENTATION)) { thing->Angles.Yaw = angle; } else { angle = thing->Angles.Yaw; } // Spawn teleport fog at source and destination if ((flags & TELF_SOURCEFOG) && !predicting) { P_SpawnTeleportFog(thing, old, true, true); //Passes the actor through which then pulls the TeleFog metadata types based on properties. } if (flags & TELF_DESTFOG) { if (!predicting) { DVector2 vector = angle.ToVector(20); DVector2 fogpos = P_GetOffsetPosition(pos.X, pos.Y, vector.X, vector.Y); P_SpawnTeleportFog(thing, DVector3(fogpos, thing->Z()), false, true); } if (thing->player) { // [RH] Zoom player's field of vision // [BC] && bHaltVelocity. if (telezoom && thing->player->mo == thing && !(flags & TELF_KEEPVELOCITY)) thing->player->FOV = MIN (175.f, thing->player->DesiredFOV + 45.f); } } // [BC] && bHaltVelocity. if (thing->player && ((flags & TELF_DESTFOG) || !(flags & TELF_KEEPORIENTATION)) && !(flags & TELF_KEEPVELOCITY)) { // Freeze player for about .5 sec if (thing->Inventory == NULL || !thing->Inventory->GetNoTeleportFreeze()) thing->reactiontime = 18; } if (thing->flags & MF_MISSILE) { thing->VelFromAngle(missilespeed); } // [BC] && bHaltVelocity. else if (!(flags & TELF_KEEPORIENTATION) && !(flags & TELF_KEEPVELOCITY)) { // no fog doesn't alter the player's momentum thing->Vel.Zero(); // killough 10/98: kill all bobbing velocity too if (player) player->Vel.Zero(); } return true; }
bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, bool useFog, bool sourceFog, bool keepOrientation, bool bHaltVelocity, bool keepHeight) { fixed_t oldx; fixed_t oldy; fixed_t oldz; fixed_t aboveFloor; player_t *player; angle_t an; sector_t *destsect; bool resetpitch = false; fixed_t floorheight, ceilingheight; fixed_t missilespeed; oldx = thing->x; oldy = thing->y; oldz = thing->z; aboveFloor = thing->z - thing->floorz; destsect = P_PointInSector (x, y); // killough 5/12/98: exclude voodoo dolls: player = thing->player; if (player && player->mo != thing) player = NULL; floorheight = destsect->floorplane.ZatPoint (x, y); ceilingheight = destsect->ceilingplane.ZatPoint (x, y); if (thing->flags & MF_MISSILE) { // We don't measure z velocity, because it doesn't change. missilespeed = xs_CRoundToInt(TVector2<double>(thing->velx, thing->vely).Length()); } if (keepHeight) { z = floorheight + aboveFloor; } else if (z == ONFLOORZ) { if (player) { if (thing->flags & MF_NOGRAVITY && aboveFloor) { z = floorheight + aboveFloor; if (z + thing->height > ceilingheight) { z = ceilingheight - thing->height; } } else { z = floorheight; if (!keepOrientation) { resetpitch = false; } } } else if (thing->flags & MF_MISSILE) { z = floorheight + aboveFloor; if (z + thing->height > ceilingheight) { z = ceilingheight - thing->height; } } else { z = floorheight; } } if (!P_TeleportMove (thing, x, y, z, false)) { return false; } if (player) { player->viewz = thing->z + player->viewheight; if (resetpitch) { player->mo->pitch = 0; } } if (!keepOrientation) { thing->angle = angle; } else { angle = thing->angle; } // Spawn teleport fog at source and destination if (sourceFog) { fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; AActor *fog = Spawn<ATeleportFog> (oldx, oldy, oldz + fogDelta, ALLOW_REPLACE); fog->target = thing; } if (useFog) { fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; an = angle >> ANGLETOFINESHIFT; AActor *fog = Spawn<ATeleportFog> (x + 20*finecosine[an], y + 20*finesine[an], thing->z + fogDelta, ALLOW_REPLACE); fog->target = thing; if (thing->player) { // [RH] Zoom player's field of vision // [BC] && bHaltVelocity. if (telezoom && thing->player->mo == thing && bHaltVelocity) thing->player->FOV = MIN (175.f, thing->player->DesiredFOV + 45.f); } } // [BC] && bHaltVelocity. if (thing->player && (useFog || !keepOrientation) && bHaltVelocity) { // Freeze player for about .5 sec if (thing->Inventory == NULL || thing->Inventory->GetSpeedFactor() <= FRACUNIT) thing->reactiontime = 18; } if (thing->flags & MF_MISSILE) { angle >>= ANGLETOFINESHIFT; thing->velx = FixedMul (missilespeed, finecosine[angle]); thing->vely = FixedMul (missilespeed, finesine[angle]); }