inline void GLPortal::ClearClipper() { DAngle angleOffset = deltaangle(savedAngle, ViewAngle); clipper.Clear(); static int call=0; // Set the clipper to the minimal visible area clipper.SafeAddClipRange(0,0xffffffff); for (unsigned int i = 0; i < lines.Size(); i++) { DAngle startAngle = (DVector2(lines[i].glseg.x2, lines[i].glseg.y2) - savedViewPos).Angle() + angleOffset; DAngle endAngle = (DVector2(lines[i].glseg.x1, lines[i].glseg.y1) - savedViewPos).Angle() + angleOffset; if (deltaangle(endAngle, startAngle) < 0) { clipper.SafeRemoveClipRangeRealAngles(startAngle.BAMs(), endAngle.BAMs()); } } // and finally clip it to the visible area angle_t a1 = GLRenderer->FrustumAngle(); if (a1 < ANGLE_180) clipper.SafeAddClipRangeRealAngles(ViewAngle.BAMs() + a1, ViewAngle.BAMs() - a1); // lock the parts that have just been clipped out. clipper.SetSilhouette(); }
void HWScenePortalBase::ClearClipper(HWDrawInfo *di, Clipper *clipper) { auto outer_di = di->outer; DAngle angleOffset = deltaangle(outer_di->Viewpoint.Angles.Yaw, di->Viewpoint.Angles.Yaw); clipper->Clear(); // Set the clipper to the minimal visible area clipper->SafeAddClipRange(0, 0xffffffff); for (unsigned int i = 0; i < lines.Size(); i++) { DAngle startAngle = (DVector2(lines[i].glseg.x2, lines[i].glseg.y2) - outer_di->Viewpoint.Pos).Angle() + angleOffset; DAngle endAngle = (DVector2(lines[i].glseg.x1, lines[i].glseg.y1) - outer_di->Viewpoint.Pos).Angle() + angleOffset; if (deltaangle(endAngle, startAngle) < 0) { clipper->SafeRemoveClipRangeRealAngles(startAngle.BAMs(), endAngle.BAMs()); } } // and finally clip it to the visible area angle_t a1 = di->FrustumAngle(); if (a1 < ANGLE_180) clipper->SafeAddClipRangeRealAngles(di->Viewpoint.Angles.Yaw.BAMs() + a1, di->Viewpoint.Angles.Yaw.BAMs() - a1); // lock the parts that have just been clipped out. clipper->SetSilhouette(); }
DEFINE_ACTION_FUNCTION(AActor, A_Tracer2) { PARAM_ACTION_PROLOGUE; AActor *dest; double dist; double slope; dest = self->tracer; if (!dest || dest->health <= 0 || self->Speed == 0 || !self->CanSeek(dest)) return 0; DAngle exact = self->AngleTo(dest); DAngle diff = deltaangle(self->Angles.Yaw, exact); if (diff < 0) { self->Angles.Yaw -= TRACEANGLE; if (deltaangle(self->Angles.Yaw, exact) > 0) self->Angles.Yaw = exact; } else if (diff > 0) { self->Angles.Yaw += TRACEANGLE; if (deltaangle(self->Angles.Yaw, exact) < 0.) self->Angles.Yaw = exact; } self->VelFromAngle(); if (!(self->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER))) { // change slope dist = self->DistanceBySpeed (dest, self->Speed); if (dest->Height >= 56) { slope = (dest->Z()+40 - self->Z()) / dist; } else { slope = (dest->Z() + self->Height*(2./3) - self->Z()) / dist; } if (slope < self->Vel.Z) { self->Vel.Z -= 1 / 8.; } else { self->Vel.Z += 1 / 8.; } } return 0; }
void PolyDrawSectorPortal::SaveGlobals() { auto &viewpoint = PolyRenderer::Instance()->Viewpoint; const auto &viewwindow = PolyRenderer::Instance()->Viewwindow; SavedViewpoint = viewpoint; SavedInvisibility = viewpoint.camera ? (viewpoint.camera->renderflags & RF_INVISIBLE) == RF_INVISIBLE : false; if (Portal->mType == PORTS_SKYVIEWPOINT) { // Don't let gun flashes brighten the sky box AActor *sky = Portal->mSkybox; viewpoint.extralight = 0; //PolyRenderer::Instance()->Light.SetVisibility(sky->args[0] * 0.25f); viewpoint.Pos = sky->InterpolatedPosition(viewpoint.TicFrac); viewpoint.Angles.Yaw = SavedViewpoint.Angles.Yaw + (sky->PrevAngles.Yaw + deltaangle(sky->PrevAngles.Yaw, sky->Angles.Yaw) * viewpoint.TicFrac); } else //if (Portal->mType == PORTS_STACKEDSECTORTHING || Portal->mType == PORTS_PORTAL || Portal->mType == PORTS_LINKEDPORTAL) { //extralight = pl->extralight; //SetVisibility(pl->visibility); viewpoint.Pos.X += Portal->mDisplacement.X; viewpoint.Pos.Y += Portal->mDisplacement.Y; } viewpoint.camera = nullptr; viewpoint.sector = Portal->mDestination; viewpoint.SetViewAngle(viewwindow); Portal->mFlags |= PORTSF_INSKYBOX; if (Portal->mPartner > 0) PolyRenderer::Instance()->Level->sectorPortals[Portal->mPartner].mFlags |= PORTSF_INSKYBOX; }
void GLSkyboxPortal::DrawContents() { int old_pm = PlaneMirrorMode; int saved_extralight = extralight; if (skyboxrecursion >= 3) { ClearScreen(); return; } skyboxrecursion++; AActor *origin = portal->mSkybox; portal->mFlags |= PORTSF_INSKYBOX; extralight = 0; PlaneMirrorMode = 0; bool oldclamp = gl_RenderState.SetDepthClamp(false); ViewPos = origin->InterpolatedPosition(r_TicFracF); ViewAngle += (origin->PrevAngles.Yaw + deltaangle(origin->PrevAngles.Yaw, origin->Angles.Yaw) * r_TicFracF); // Don't let the viewpoint be too close to a floor or ceiling double floorh = origin->Sector->floorplane.ZatPoint(origin->Pos()); double ceilh = origin->Sector->ceilingplane.ZatPoint(origin->Pos()); if (ViewPos.Z < floorh + 4) ViewPos.Z = floorh + 4; if (ViewPos.Z > ceilh - 4) ViewPos.Z = ceilh - 4; GLRenderer->mViewActor = origin; inskybox = true; GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1)); GLRenderer->SetViewArea(); ClearClipper(); int mapsection = R_PointInSubsector(ViewPos)->mapsection; SaveMapSection(); currentmapsection[mapsection >> 3] |= 1 << (mapsection & 7); GLRenderer->DrawScene(DM_PORTAL); portal->mFlags &= ~PORTSF_INSKYBOX; inskybox = false; gl_RenderState.SetDepthClamp(oldclamp); skyboxrecursion--; PlaneMirrorMode = old_pm; extralight = saved_extralight; RestoreMapSection(); }
bool HWSkyboxPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) { auto state = mState; old_pm = state->PlaneMirrorMode; if (mState->skyboxrecursion >= 3) { return false; } auto &vp = di->Viewpoint; state->skyboxrecursion++; state->PlaneMirrorMode = 0; state->inskybox = true; AActor *origin = portal->mSkybox; portal->mFlags |= PORTSF_INSKYBOX; vp.extralight = 0; oldclamp = rstate.SetDepthClamp(false); vp.Pos = origin->InterpolatedPosition(vp.TicFrac); vp.ActorPos = origin->Pos(); vp.Angles.Yaw += (origin->PrevAngles.Yaw + deltaangle(origin->PrevAngles.Yaw, origin->Angles.Yaw) * vp.TicFrac); // Don't let the viewpoint be too close to a floor or ceiling double floorh = origin->Sector->floorplane.ZatPoint(origin->Pos()); double ceilh = origin->Sector->ceilingplane.ZatPoint(origin->Pos()); if (vp.Pos.Z < floorh + 4) vp.Pos.Z = floorh + 4; if (vp.Pos.Z > ceilh - 4) vp.Pos.Z = ceilh - 4; vp.ViewActor = origin; di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); di->SetViewArea(); ClearClipper(di, clipper); di->UpdateCurrentMapSection(); return true; }
void AdjustPlayerAngle (AActor *pmo, FTranslatedLineTarget *t) { // normally this will adjust relative to the actual direction to the target, // but with arbitrary portals that cannot be calculated so using the actual // attack angle is the only option. DAngle atkangle = t->unlinked ? t->angleFromSource : pmo->AngleTo(t->linetarget); DAngle difference = deltaangle(pmo->Angles.Yaw, atkangle); if (fabs(difference) > MAX_ANGLE_ADJUST) { if (difference > 0) { pmo->Angles.Yaw += MAX_ANGLE_ADJUST; } else { pmo->Angles.Yaw -= MAX_ANGLE_ADJUST; } } else { pmo->Angles.Yaw = t->angleFromSource; } }
// Draws any recorded sky boxes and then frees them. // // The process: // 1. Move the camera to coincide with the SkyViewpoint. // 2. Clear out the old planes. (They have already been drawn.) // 3. Clear a window out of the ClipSegs just large enough for the plane. // 4. Pretend the existing vissprites and drawsegs aren't there. // 5. Create a drawseg at 0 distance to clip sprites to the visplane. It // doesn't need to be associated with a line in the map, since there // will never be any sprites in front of it. // 6. Render the BSP, then planes, then masked stuff. // 7. Restore the previous vissprites and drawsegs. // 8. Repeat for any other sky boxes. // 9. Put the camera back where it was to begin with. // void RenderPortal::RenderPlanePortals() { numskyboxes = 0; VisiblePlaneList *planes = Thread->PlaneList.get(); DrawSegmentList *drawseglist = Thread->DrawSegments.get(); if (!planes->HasPortalPlanes()) return; Thread->Clip3D->EnterSkybox(); CurrentPortalInSkybox = true; int savedextralight = Thread->Viewport->viewpoint.extralight; DVector3 savedpos = Thread->Viewport->viewpoint.Pos; DRotator savedangles = Thread->Viewport->viewpoint.Angles; double savedvisibility = Thread->Light->GetVisibility(); AActor *savedcamera = Thread->Viewport->viewpoint.camera; sector_t *savedsector = Thread->Viewport->viewpoint.sector; for (VisiblePlane *pl = planes->PopFirstPortalPlane(); pl != nullptr; pl = planes->PopFirstPortalPlane()) { if (pl->right < pl->left || !r_skyboxes || numskyboxes == MAX_SKYBOX_PLANES || pl->portal == nullptr) { pl->Render(Thread, OPAQUE, false, false); continue; } numskyboxes++; FSectorPortal *port = pl->portal; switch (port->mType) { case PORTS_SKYVIEWPOINT: { // Don't let gun flashes brighten the sky box AActor *sky = port->mSkybox; Thread->Viewport->viewpoint.extralight = 0; Thread->Light->SetVisibility(Thread->Viewport.get(), sky->args[0] * 0.25f); Thread->Viewport->viewpoint.Pos = sky->InterpolatedPosition(Thread->Viewport->viewpoint.TicFrac); Thread->Viewport->viewpoint.Angles.Yaw = savedangles.Yaw + (sky->PrevAngles.Yaw + deltaangle(sky->PrevAngles.Yaw, sky->Angles.Yaw) * Thread->Viewport->viewpoint.TicFrac); CopyStackedViewParameters(); break; } case PORTS_STACKEDSECTORTHING: case PORTS_PORTAL: case PORTS_LINKEDPORTAL: Thread->Viewport->viewpoint.extralight = pl->extralight; Thread->Light->SetVisibility(Thread->Viewport.get(), pl->visibility); Thread->Viewport->viewpoint.Pos.X = pl->viewpos.X + port->mDisplacement.X; Thread->Viewport->viewpoint.Pos.Y = pl->viewpos.Y + port->mDisplacement.Y; Thread->Viewport->viewpoint.Pos.Z = pl->viewpos.Z; Thread->Viewport->viewpoint.Angles.Yaw = pl->viewangle; break; case PORTS_HORIZON: case PORTS_PLANE: // not implemented yet default: pl->Render(Thread, OPAQUE, false, false); numskyboxes--; continue; } SetInSkyBox(port); if (port->mPartner > 0) SetInSkyBox(&level.sectorPortals[port->mPartner]); Thread->Viewport->viewpoint.camera = nullptr; Thread->Viewport->viewpoint.sector = port->mDestination; assert(Thread->Viewport->viewpoint.sector != nullptr); R_SetViewAngle(Thread->Viewport->viewpoint, Thread->Viewport->viewwindow); Thread->OpaquePass->ClearSeenSprites(); Thread->Clip3D->ClearFakeFloors(); planes->ClearKeepFakePlanes(); Thread->ClipSegments->Clear(pl->left, pl->right); WindowLeft = pl->left; WindowRight = pl->right; auto ceilingclip = Thread->OpaquePass->ceilingclip; auto floorclip = Thread->OpaquePass->floorclip; for (int i = pl->left; i < pl->right; i++) { if (pl->top[i] == 0x7fff) { ceilingclip[i] = viewheight; floorclip[i] = -1; } else { ceilingclip[i] = pl->top[i]; floorclip[i] = pl->bottom[i]; } } drawseglist->PushPortal(); Thread->SpriteList->PushPortal(); viewposStack.Push(Thread->Viewport->viewpoint.Pos); visplaneStack.Push(pl); // Create a drawseg to clip sprites to the sky plane DrawSegment *draw_segment = Thread->FrameMemory->NewObject<DrawSegment>(); draw_segment->CurrentPortalUniq = CurrentPortalUniq; draw_segment->siz1 = INT_MAX; draw_segment->siz2 = INT_MAX; draw_segment->sz1 = 0; draw_segment->sz2 = 0; draw_segment->x1 = pl->left; draw_segment->x2 = pl->right; draw_segment->silhouette = SIL_BOTH; draw_segment->sprbottomclip = Thread->FrameMemory->AllocMemory<short>(pl->right - pl->left); draw_segment->sprtopclip = Thread->FrameMemory->AllocMemory<short>(pl->right - pl->left); draw_segment->maskedtexturecol = nullptr; draw_segment->swall = nullptr; draw_segment->bFogBoundary = false; draw_segment->curline = nullptr; draw_segment->foggy = false; memcpy(draw_segment->sprbottomclip, floorclip + pl->left, (pl->right - pl->left) * sizeof(short)); memcpy(draw_segment->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left) * sizeof(short)); drawseglist->Push(draw_segment); Thread->OpaquePass->RenderScene(); Thread->Clip3D->ResetClip(); // reset clips (floor/ceiling) planes->Render(); ClearInSkyBox(port); if (port->mPartner > 0) SetInSkyBox(&level.sectorPortals[port->mPartner]); } // Draw all the masked textures in a second pass, in the reverse order they // were added. This must be done separately from the previous step for the // sake of nested skyboxes. while (viewposStack.Size() > 0) { // Masked textures and planes need the view coordinates restored for proper positioning. viewposStack.Pop(Thread->Viewport->viewpoint.Pos); Thread->TranslucentPass->Render(); VisiblePlane *pl = nullptr; // quiet, GCC! visplaneStack.Pop(pl); if (pl->Alpha > 0 && pl->picnum != skyflatnum) { pl->Render(Thread, pl->Alpha, pl->Additive, true); } Thread->SpriteList->PopPortal(); drawseglist->PopPortal(); } Thread->Viewport->viewpoint.camera = savedcamera; Thread->Viewport->viewpoint.sector = savedsector; Thread->Viewport->viewpoint.Pos = savedpos; Thread->Light->SetVisibility(Thread->Viewport.get(), savedvisibility); Thread->Viewport->viewpoint.extralight = savedextralight; Thread->Viewport->viewpoint.Angles = savedangles; R_SetViewAngle(Thread->Viewport->viewpoint, Thread->Viewport->viewwindow); CurrentPortalInSkybox = false; Thread->Clip3D->LeaveSkybox(); if (Thread->Clip3D->fakeActive) return; planes->ClearPortalPlanes(); }
void R_DrawPortals () { static TArray<size_t> interestingStack; static TArray<ptrdiff_t> drawsegStack; static TArray<ptrdiff_t> visspriteStack; static TArray<DVector3> viewposStack; static TArray<visplane_t *> visplaneStack; numskyboxes = 0; if (visplanes[MAXVISPLANES] == NULL) return; R_3D_EnterSkybox(); CurrentPortalInSkybox = true; int savedextralight = extralight; DVector3 savedpos = ViewPos; DAngle savedangle = ViewAngle; ptrdiff_t savedvissprite_p = vissprite_p - vissprites; ptrdiff_t savedds_p = ds_p - drawsegs; ptrdiff_t savedlastopening = lastopening; size_t savedinteresting = FirstInterestingDrawseg; double savedvisibility = R_GetVisibility(); AActor *savedcamera = camera; sector_t *savedsector = viewsector; int i; visplane_t *pl; for (pl = visplanes[MAXVISPLANES]; pl != NULL; pl = visplanes[MAXVISPLANES]) { // Pop the visplane off the list now so that if this skybox adds more // skyboxes to the list, they will be drawn instead of skipped (because // new skyboxes go to the beginning of the list instead of the end). visplanes[MAXVISPLANES] = pl->next; pl->next = NULL; if (pl->right < pl->left || !r_skyboxes || numskyboxes == MAX_SKYBOX_PLANES || pl->portal == NULL) { R_DrawSinglePlane (pl, OPAQUE, false, false); *freehead = pl; freehead = &pl->next; continue; } numskyboxes++; FSectorPortal *port = pl->portal; switch (port->mType) { case PORTS_SKYVIEWPOINT: { // Don't let gun flashes brighten the sky box ASkyViewpoint *sky = barrier_cast<ASkyViewpoint*>(port->mSkybox); extralight = 0; R_SetVisibility(sky->args[0] * 0.25f); ViewPos = sky->InterpolatedPosition(r_TicFracF); ViewAngle = savedangle + (sky->PrevAngles.Yaw + deltaangle(sky->PrevAngles.Yaw, sky->Angles.Yaw) * r_TicFracF); R_CopyStackedViewParameters(); break; } case PORTS_STACKEDSECTORTHING: case PORTS_PORTAL: case PORTS_LINKEDPORTAL: extralight = pl->extralight; R_SetVisibility (pl->visibility); ViewPos.X = pl->viewpos.X + port->mDisplacement.X; ViewPos.Y = pl->viewpos.Y + port->mDisplacement.Y; ViewPos.Z = pl->viewpos.Z; ViewAngle = pl->viewangle; break; case PORTS_HORIZON: case PORTS_PLANE: // not implemented yet default: R_DrawSinglePlane(pl, OPAQUE, false, false); *freehead = pl; freehead = &pl->next; numskyboxes--; continue; } port->mFlags |= PORTSF_INSKYBOX; if (port->mPartner > 0) sectorPortals[port->mPartner].mFlags |= PORTSF_INSKYBOX; camera = NULL; viewsector = port->mDestination; assert(viewsector != NULL); R_SetViewAngle (); validcount++; // Make sure we see all sprites R_ClearPlanes (false); R_ClearClipSegs (pl->left, pl->right); WindowLeft = pl->left; WindowRight = pl->right; for (i = pl->left; i < pl->right; i++) { if (pl->top[i] == 0x7fff) { ceilingclip[i] = viewheight; floorclip[i] = -1; } else { ceilingclip[i] = pl->top[i]; floorclip[i] = pl->bottom[i]; } } // Create a drawseg to clip sprites to the sky plane R_CheckDrawSegs (); ds_p->CurrentPortalUniq = CurrentPortalUniq; ds_p->siz1 = INT_MAX; ds_p->siz2 = INT_MAX; ds_p->sz1 = 0; ds_p->sz2 = 0; ds_p->x1 = pl->left; ds_p->x2 = pl->right; ds_p->silhouette = SIL_BOTH; ds_p->sprbottomclip = R_NewOpening (pl->right - pl->left); ds_p->sprtopclip = R_NewOpening (pl->right - pl->left); ds_p->maskedtexturecol = ds_p->swall = -1; ds_p->bFogBoundary = false; ds_p->curline = NULL; ds_p->fake = 0; memcpy (openings + ds_p->sprbottomclip, floorclip + pl->left, (pl->right - pl->left)*sizeof(short)); memcpy (openings + ds_p->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left)*sizeof(short)); firstvissprite = vissprite_p; firstdrawseg = ds_p++; FirstInterestingDrawseg = InterestingDrawsegs.Size(); interestingStack.Push (FirstInterestingDrawseg); ptrdiff_t diffnum = firstdrawseg - drawsegs; drawsegStack.Push (diffnum); diffnum = firstvissprite - vissprites; visspriteStack.Push (diffnum); viewposStack.Push(ViewPos); visplaneStack.Push (pl); InSubsector = NULL; R_RenderBSPNode (nodes + numnodes - 1); R_3D_ResetClip(); // reset clips (floor/ceiling) R_DrawPlanes (); port->mFlags &= ~PORTSF_INSKYBOX; if (port->mPartner > 0) sectorPortals[port->mPartner].mFlags &= ~PORTSF_INSKYBOX; } // Draw all the masked textures in a second pass, in the reverse order they // were added. This must be done separately from the previous step for the // sake of nested skyboxes. while (interestingStack.Pop (FirstInterestingDrawseg)) { ptrdiff_t pd = 0; drawsegStack.Pop (pd); firstdrawseg = drawsegs + pd; visspriteStack.Pop (pd); firstvissprite = vissprites + pd; // Masked textures and planes need the view coordinates restored for proper positioning. viewposStack.Pop(ViewPos); R_DrawMasked (); ds_p = firstdrawseg; vissprite_p = firstvissprite; visplaneStack.Pop (pl); if (pl->Alpha > 0 && pl->picnum != skyflatnum) { R_DrawSinglePlane (pl, pl->Alpha, pl->Additive, true); } *freehead = pl; freehead = &pl->next; } firstvissprite = vissprites; vissprite_p = vissprites + savedvissprite_p; firstdrawseg = drawsegs; ds_p = drawsegs + savedds_p; InterestingDrawsegs.Resize ((unsigned int)FirstInterestingDrawseg); FirstInterestingDrawseg = savedinteresting; lastopening = savedlastopening; camera = savedcamera; viewsector = savedsector; ViewPos = savedpos; R_SetVisibility(savedvisibility); extralight = savedextralight; ViewAngle = savedangle; R_SetViewAngle (); CurrentPortalInSkybox = false; R_3D_LeaveSkybox(); if(fakeActive) return; for (*freehead = visplanes[MAXVISPLANES], visplanes[MAXVISPLANES] = NULL; *freehead; ) freehead = &(*freehead)->next; }
int FMugShot::UpdateState(player_t *player, StateFlags stateflags) { FString full_state_name; if (player->health > 0) { if (bEvilGrin && !(stateflags & DISABLEGRIN)) { if (player->bonuscount) { SetState("grin", false); return 0; } } bEvilGrin = false; bool ouch = (!st_oldouch && FaceHealth - player->health > ST_MUCHPAIN) || (st_oldouch && player->health - FaceHealth > ST_MUCHPAIN); if (player->damagecount && // Now go in if pain is disabled but we think ouch will be shown (and ouch is not disabled!) (!(stateflags & DISABLEPAIN) || (((FaceHealth != -1 && ouch) || bOuchActive) && !(stateflags & DISABLEOUCH)))) { int damage_angle = 1; if (player->attacker && player->attacker != player->mo) { if (player->mo != NULL) { // The next 12 lines are from the Doom statusbar code. DAngle badguyangle = player->mo->AngleTo(player->attacker); DAngle diffang = deltaangle(player->mo->Angles.Yaw, badguyangle); if (diffang > 45.) { // turn face right damage_angle = 0; } else if (diffang < -45.) { // turn face left damage_angle = 2; } } } bool use_ouch = false; if (((FaceHealth != -1 && ouch) || bOuchActive) && !(stateflags & DISABLEOUCH)) { use_ouch = true; full_state_name = "ouch."; } else { full_state_name = "pain."; } full_state_name += player->LastDamageType; if (SetState(full_state_name, false, true)) { bDamageFaceActive = (CurrentState != NULL); LastDamageAngle = damage_angle; bOuchActive = use_ouch; } return damage_angle; } if (bDamageFaceActive) { if (CurrentState == NULL) { bDamageFaceActive = false; } else { bool use_ouch = false; if (((FaceHealth != -1 && ouch) || bOuchActive) && !(stateflags & DISABLEOUCH)) { use_ouch = true; full_state_name = "ouch."; } else { full_state_name = "pain."; } full_state_name += player->LastDamageType; if (SetState(full_state_name)) { bOuchActive = use_ouch; } return LastDamageAngle; } } if (RampageTimer == ST_RAMPAGEDELAY && !(stateflags & DISABLERAMPAGE)) { SetState("rampage", !bNormal); //If we have nothing better to show, use the rampage face. return 0; } if (bNormal) { bool good; if ((player->cheats & CF_GODMODE) || (player->cheats & CF_GODMODE2) || (player->mo != NULL && player->mo->flags2 & MF2_INVULNERABLE)) { good = SetState((stateflags & ANIMATEDGODMODE) ? "godanimated" : "god"); } else { good = SetState("normal"); } if (good) { bNormal = true; //SetState sets bNormal to false. } } } else { if (!(stateflags & XDEATHFACE) || !(player->cheats & CF_EXTREMELYDEAD)) { full_state_name = "death."; } else { full_state_name = "xdeath."; } full_state_name += player->LastDamageType; SetState(full_state_name); bNormal = true; //Allow the face to return to alive states when the player respawns. } return 0; }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) { PARAM_ACTION_PROLOGUE; PARAM_SOUND_OPT (fullsound) { fullsound = "weapons/sawfull"; } PARAM_SOUND_OPT (hitsound) { hitsound = "weapons/sawhit"; } PARAM_INT_OPT (damage) { damage = 2; } PARAM_CLASS_OPT (pufftype, AActor) { pufftype = NULL; } PARAM_INT_OPT (flags) { flags = 0; } PARAM_FLOAT_OPT (range) { range = 0; } PARAM_ANGLE_OPT (spread_xy) { spread_xy = 2.8125; } PARAM_ANGLE_OPT (spread_z) { spread_z = 0.; } PARAM_FLOAT_OPT (lifesteal) { lifesteal = 0; } PARAM_INT_OPT (lifestealmax) { lifestealmax = 0; } PARAM_CLASS_OPT (armorbonustype, ABasicArmorBonus) { armorbonustype = NULL; } DAngle angle; DAngle slope; player_t *player; FTranslatedLineTarget t; int actualdamage; if (NULL == (player = self->player)) { return 0; } if (pufftype == NULL) { pufftype = PClass::FindActor(NAME_BulletPuff); } if (damage == 0) { damage = 2; } if (!(flags & SF_NORANDOM)) { damage *= (pr_saw()%10+1); } if (range == 0) { range = SAWRANGE; } angle = self->Angles.Yaw + spread_xy * (pr_saw.Random2() / 255.); slope = P_AimLineAttack (self, angle, range, &t) + spread_z * (pr_saw.Random2() / 255.); AWeapon *weapon = self->player->ReadyWeapon; if ((weapon != NULL) && !(flags & SF_NOUSEAMMO) && !(!t.linetarget && (flags & SF_NOUSEAMMOMISS)) && !(weapon->WeaponFlags & WIF_DEHAMMO) && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return 0; } P_LineAttack (self, angle, range, slope, damage, NAME_Melee, pufftype, false, &t, &actualdamage); if (!t.linetarget) { if ((flags & SF_RANDOMLIGHTMISS) && (pr_saw() > 64)) { player->extralight = !player->extralight; } S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM); return 0; } if (flags & SF_RANDOMLIGHTHIT) { int randVal = pr_saw(); if (randVal < 64) { player->extralight = 0; } else if (randVal < 160) { player->extralight = 1; } else { player->extralight = 2; } } if (lifesteal && !(t.linetarget->flags5 & MF5_DONTDRAIN)) { if (flags & SF_STEALARMOR) { if (armorbonustype == NULL) { armorbonustype = dyn_cast<ABasicArmorBonus::MetaClass>(PClass::FindClass("ArmorBonus")); } if (armorbonustype != NULL) { assert(armorbonustype->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus))); ABasicArmorBonus *armorbonus = static_cast<ABasicArmorBonus *>(Spawn(armorbonustype)); armorbonus->SaveAmount = int(armorbonus->SaveAmount * actualdamage * lifesteal); armorbonus->MaxSaveAmount = lifestealmax <= 0 ? armorbonus->MaxSaveAmount : lifestealmax; armorbonus->flags |= MF_DROPPED; armorbonus->ClearCounters(); if (!armorbonus->CallTryPickup (self)) { armorbonus->Destroy (); } } } else { P_GiveBody (self, int(actualdamage * lifesteal), lifestealmax); } } S_Sound (self, CHAN_WEAPON, hitsound, 1, ATTN_NORM); // turn to face target if (!(flags & SF_NOTURN)) { DAngle anglediff = deltaangle(self->Angles.Yaw, t.angleFromSource); if (anglediff < 0.0) { if (anglediff < -4.5) self->Angles.Yaw = angle + 90.0 / 21; else self->Angles.Yaw -= 4.5; } else { if (anglediff > 4.5) self->Angles.Yaw = angle - 90.0 / 21; else self->Angles.Yaw += 4.5; } } if (!(flags & SF_NOPULLIN)) self->flags |= MF_JUSTATTACKED; return 0; }
bool APathFollower::Interpolate () { DVector3 dpos(0, 0, 0); FLinkContext ctx; if ((args[2] & 8) && Time > 0.f) { dpos = Pos(); } if (CurrNode->Next==NULL) return false; UnlinkFromWorld (&ctx); DVector3 newpos; if (args[2] & 1) { // linear newpos.X = Lerp(CurrNode->X(), CurrNode->Next->X()); newpos.Y = Lerp(CurrNode->Y(), CurrNode->Next->Y()); newpos.Z = Lerp(CurrNode->Z(), CurrNode->Next->Z()); } else { // spline if (CurrNode->Next->Next==NULL) return false; newpos.X = Splerp(PrevNode->X(), CurrNode->X(), CurrNode->Next->X(), CurrNode->Next->Next->X()); newpos.Y = Splerp(PrevNode->Y(), CurrNode->Y(), CurrNode->Next->Y(), CurrNode->Next->Next->Y()); newpos.Z = Splerp(PrevNode->Z(), CurrNode->Z(), CurrNode->Next->Z(), CurrNode->Next->Next->Z()); } SetXYZ(newpos); LinkToWorld (&ctx); if (args[2] & 6) { if (args[2] & 8) { if (args[2] & 1) { // linear dpos.X = CurrNode->Next->X() - CurrNode->X(); dpos.Y = CurrNode->Next->Y() - CurrNode->Y(); dpos.Z = CurrNode->Next->Z() - CurrNode->Z(); } else if (Time > 0.f) { // spline dpos = newpos - dpos; } else { int realarg = args[2]; args[2] &= ~(2|4|8); Time += 0.1f; dpos = newpos; Interpolate (); Time -= 0.1f; args[2] = realarg; dpos = newpos - dpos; newpos -= dpos; SetXYZ(newpos); } if (args[2] & 2) { // adjust yaw Angles.Yaw = dpos.Angle(); } if (args[2] & 4) { // adjust pitch; use floats for precision double dist = dpos.XY().Length(); Angles.Pitch = dist != 0.f ? VecToAngle(dist, -dpos.Z) : 0.; } } else { if (args[2] & 2) { // interpolate angle DAngle angle1 = CurrNode->Angles.Yaw.Normalized180(); DAngle angle2 = angle1 + deltaangle(angle1, CurrNode->Next->Angles.Yaw); Angles.Yaw = Lerp(angle1.Degrees, angle2.Degrees); } if (args[2] & 1) { // linear if (args[2] & 4) { // interpolate pitch Angles.Pitch = Lerp(CurrNode->Angles.Pitch.Degrees, CurrNode->Next->Angles.Pitch.Degrees); } } else { // spline if (args[2] & 4) { // interpolate pitch Angles.Pitch = Splerp(PrevNode->Angles.Pitch.Degrees, CurrNode->Angles.Pitch.Degrees, CurrNode->Next->Angles.Pitch.Degrees, CurrNode->Next->Next->Angles.Pitch.Degrees); } } } } return true; }