From 8a433d6f12fc943cde9328a58e1d0db3596a5d88 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 23 Dec 2007 21:56:46 +0000 Subject: [PATCH] - Fixed a few font related problems. - Fixed: ASkyViewpoint::Destroy was missing the super call. - Added SnowKate709's A_LookEx update. - Moved M_DrawPlayerBackdrop into DCanvas as a virtual function. Since this directly accesses the frame buffer it must be overridable for renderers that work differently. SVN r632 (trunk) --- docs/rh-log.txt | 6 + src/actor.h | 6 + src/codepointers.h | 2 + src/g_shared/a_skies.cpp | 1 + src/m_menu.cpp | 46 +-- src/p_enemy_a_lookex.cpp | 490 +++++++++++++++++++++++++----- src/thingdef_codeptr.cpp | 52 ++++ src/v_draw.cpp | 52 +++- src/v_font.cpp | 1 + src/v_video.h | 3 + wadsrc/decorate/nativeclasses.txt | 3 +- 11 files changed, 545 insertions(+), 117 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 804a6d58f..0f3770995 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,10 @@ December 23, 2007 (Changes by Graf Zahl) +- Fixed a few font related problems. +- Fixed: ASkyViewpoint::Destroy was missing the super call. +- Added SnowKate709's A_LookEx update. +- Moved M_DrawPlayerBackdrop into DCanvas as a virtual function. Since this + directly accesses the frame buffer it must be overridable for rendereres + that work differently. - Added Blzut3's third SBARINFO update: * Added drawshader to draw Heretic style transparency gradients. * Added artiflash flag to drawselectedinventory. diff --git a/src/actor.h b/src/actor.h index 95b1e1c67..21cc84001 100644 --- a/src/actor.h +++ b/src/actor.h @@ -696,6 +696,12 @@ public: int bouncecount; // Strife's grenades only bounce twice before exploding fixed_t gravity; // [GRB] Gravity factor int FastChaseStrafeCount; + // [KS] These temporary-use properties are needed to allow A_LookEx to pass it's parameters to LookFor*InBlock in + // P_BlockmapSearch so that friendly enemies and monsters that look for other monsters can find their targets properly. + // If there's a cleaner way of doing this, feel free to remove these and use that method instead. + fixed_t LookExMinDist; // Minimum sight distance + fixed_t LookExMaxDist; // Maximum sight distance + angle_t LookExFOV; // Field of Vision // a linked list of sectors where this object appears struct msecnode_s *touching_sectorlist; // phares 3/14/98 diff --git a/src/codepointers.h b/src/codepointers.h index ec28a989b..e9ce9e793 100644 --- a/src/codepointers.h +++ b/src/codepointers.h @@ -104,5 +104,7 @@ ACTOR(SetGravity) ACTOR(ItBurnsItBurns) ACTOR(CrispyPlayer) ACTOR(DropFire) + ACTOR(ClearTarget) ACTOR(LookEx) +ACTOR(JumpIfTargetInLOS) diff --git a/src/g_shared/a_skies.cpp b/src/g_shared/a_skies.cpp index 928149686..a6214a066 100644 --- a/src/g_shared/a_skies.cpp +++ b/src/g_shared/a_skies.cpp @@ -86,6 +86,7 @@ void ASkyViewpoint::Destroy () sectors[i].CeilingSkyBox = NULL; } } + Super::Destroy(); } //--------------------------------------------------------------------------- diff --git a/src/m_menu.cpp b/src/m_menu.cpp index e3b60e5eb..08477b14d 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -149,7 +149,6 @@ static void M_StartMessage (const char *string, void(*routine)(int), bool input) static void M_PlayerSetupTicker (); static void M_PlayerSetupDrawer (); static void M_RenderPlayerBackdrop (); -static void M_DrawPlayerBackdrop (int x, int y); static void M_EditPlayerName (int choice); static void M_ChangePlayerTeam (int choice); static void M_PlayerNameChanged (FSaveGameNode *dummy); @@ -1677,8 +1676,8 @@ static void M_DrawClassMenu () { FireScreen->Lock (); M_RenderPlayerBackdrop (); - M_DrawPlayerBackdrop (x, y - 1); FireScreen->Unlock (); + screen->DrawPlayerBackdrop (FireScreen, FireRemap, x, y - 1); } M_DrawFrame (x, y, 72*CleanXfac, 80*CleanYfac-1); @@ -2097,8 +2096,8 @@ static void M_PlayerSetupDrawer () { FireScreen->Lock (); M_RenderPlayerBackdrop (); - M_DrawPlayerBackdrop (x, y - 1); FireScreen->Unlock (); + screen->DrawPlayerBackdrop (FireScreen, FireRemap, x, y - 1); } M_DrawFrame (x, y, 72*CleanXfac, 80*CleanYfac-1); @@ -2377,47 +2376,6 @@ static void M_RenderPlayerBackdrop () z2ang += z2add; } -static void M_DrawPlayerBackdrop (int x, int y) -{ - DCanvas *src = FireScreen; - DCanvas *dest = screen; - BYTE *destline, *srcline; - const int destwidth = src->GetWidth() * CleanXfac / 2; - const int destheight = src->GetHeight() * CleanYfac / 2; - const int desty = y; - const int destx = x; - const fixed_t fracxstep = FRACUNIT*2 / CleanXfac; - const fixed_t fracystep = FRACUNIT*2 / CleanYfac; - fixed_t fracx, fracy = 0; - - - if (fracxstep == FRACUNIT) - { - for (y = desty; y < desty + destheight; y++, fracy += fracystep) - { - srcline = src->GetBuffer() + (fracy >> FRACBITS) * src->GetPitch(); - destline = dest->GetBuffer() + y * dest->GetPitch() + destx; - - for (x = 0; x < destwidth; x++) - { - destline[x] = FireRemap[srcline[x]]; - } - } - } - else - { - for (y = desty; y < desty + destheight; y++, fracy += fracystep) - { - srcline = src->GetBuffer() + (fracy >> FRACBITS) * src->GetPitch(); - destline = dest->GetBuffer() + y * dest->GetPitch() + destx; - for (x = fracx = 0; x < destwidth; x++, fracx += fracxstep) - { - destline[x] = FireRemap[srcline[fracx >> FRACBITS]]; - } - } - } -} - static void M_ChangeClass (int choice) { if (PlayerClasses.Size () == 1) diff --git a/src/p_enemy_a_lookex.cpp b/src/p_enemy_a_lookex.cpp index 93245e281..ff679c774 100644 --- a/src/p_enemy_a_lookex.cpp +++ b/src/p_enemy_a_lookex.cpp @@ -21,32 +21,324 @@ #include "gi.h" -AActor *LookForTIDinBlock (AActor *lookee, int index); -bool P_LookForEnemies (AActor *actor, INTBOOL allaround); bool P_LookForMonsters (AActor *actor); static FRandom pr_look2 ("LookyLookyEx"); static FRandom pr_look3 ("IGotHookyEx"); static FRandom pr_lookforplayers ("LookForPlayersEx"); +static FRandom pr_skiptarget("SkipTargetEx"); // [KS] *** Start additions by me - p_enemy.cpp *** +// LookForTIDinBlockEx +// LookForEnemiesInBlockEx // P_NewLookTID (copied from P_LookForTID) // P_NewLookPlayers (copied from P_LookForPlayers) // Takes FOV and sight distances into account when acquiring a target. -// TODO: This is very unfriendly to the friendly monster logic due to the intermingled code. -// TODO: Default the FOV to 360 if the monster has +LOOKALLAROUND set. -// ~Kate S. 12/19/2007 +// TODO: Not sure if using actor properties to pass parameters around indirectly is such a good idea. If there's a cleaner method, do it that way instead. +// ~Kate S. Last updated on 12/23/2007 + +AActor *LookForTIDinBlockEx (AActor *lookee, int index) +{ + FBlockNode *block; + AActor *link; + AActor *other; + fixed_t dist; + angle_t an; + + for (block = blocklinks[index]; block != NULL; block = block->NextActor) + { + link = block->Me; + + if (!(link->flags & MF_SHOOTABLE)) + continue; // not shootable (observer or dead) + + if (link == lookee) + continue; + + if (link->health <= 0) + continue; // dead + + if (link->flags2 & MF2_DORMANT) + continue; // don't target dormant things + + if (link->tid == lookee->TIDtoHate) + { + other = link; + } + else if (link->target != NULL && link->target->tid == lookee->TIDtoHate) + { + other = link->target; + if (!(other->flags & MF_SHOOTABLE) || + other->health <= 0 || + (other->flags2 & MF2_DORMANT)) + { + continue; + } + } + else + { + continue; + } + + if (!(lookee->flags3 & MF3_NOSIGHTCHECK)) + { + if (!P_CheckSight (lookee, other, 2)) + continue; // out of sight + + dist = P_AproxDistance (other->x - lookee->x, + other->y - lookee->y); + + if (lookee->LookExMaxDist && dist > lookee->LookExMaxDist) + continue; // [KS] too far + + if (lookee->LookExMinDist && dist < lookee->LookExMinDist) + continue; // [KS] too close + + if (lookee->LookExFOV && lookee->LookExFOV < ANGLE_MAX) + { + an = R_PointToAngle2 (lookee->x, + lookee->y, + other->x, + other->y) + - lookee->angle; + + if (an > (lookee->LookExFOV / 2) && an < (ANGLE_MAX - (lookee->LookExFOV / 2))) + { + // if real close, react anyway + // [KS] but respect minimum distance rules + if (lookee->LookExMinDist || dist > MELEERANGE) + continue; // outside of fov + } + } + else + { + if(!(lookee->flags4 & MF4_LOOKALLAROUND) || (lookee->LookExFOV >= ANGLE_MAX)) // Just in case angle_t doesn't clamp stuff, because I can't be too sure. + { + an = R_PointToAngle2 (lookee->x, + lookee->y, + other->x, + other->y) + - lookee->angle; + + if (an > ANG90 && an < ANG270) + { + // if real close, react anyway + // [KS] but respect minimum distance rules + if (lookee->LookExMinDist || dist > MELEERANGE) + continue; // behind back + } + } + } + } + + return other; + } + return NULL; +} + +AActor *LookForEnemiesInBlockEx (AActor *lookee, int index) +{ + FBlockNode *block; + AActor *link; + AActor *other; + fixed_t dist; + angle_t an; + + for (block = blocklinks[index]; block != NULL; block = block->NextActor) + { + link = block->Me; + + if (!(link->flags & MF_SHOOTABLE)) + continue; // not shootable (observer or dead) + + if (link == lookee) + continue; + + if (link->health <= 0) + continue; // dead + + if (link->flags2 & MF2_DORMANT) + continue; // don't target dormant things + + if (!(link->flags3 & MF3_ISMONSTER)) + continue; // don't target it if it isn't a monster (could be a barrel) + + other = NULL; + if (link->flags & MF_FRIENDLY) + { + if (deathmatch && + lookee->FriendPlayer != 0 && link->FriendPlayer != 0 && + lookee->FriendPlayer != link->FriendPlayer) + { + // This is somebody else's friend, so go after it + other = link; + } + else if (link->target != NULL && !(link->target->flags & MF_FRIENDLY)) + { + other = link->target; + if (!(other->flags & MF_SHOOTABLE) || + other->health <= 0 || + (other->flags2 & MF2_DORMANT)) + { + other = NULL;; + } + } + } + else + { + other = link; + } + + // [MBF] If the monster is already engaged in a one-on-one attack + // with a healthy friend, don't attack around 60% the time. + + // [GrafZahl] This prevents friendlies from attacking all the same + // target. + + if (other) + { + AActor *targ = other->target; + if (targ && targ->target == other && pr_skiptarget() > 100 && lookee->IsFriend (targ) && + targ->health*2 >= targ->GetDefault()->health) + { + continue; + } + } + + // [KS] Hey, shouldn't there be a check for MF3_NOSIGHTCHECK here? + + if (other == NULL || !P_CheckSight (lookee, other, 2)) + continue; // out of sight + + dist = P_AproxDistance (other->x - lookee->x, + other->y - lookee->y); + + if (lookee->LookExMaxDist && dist > lookee->LookExMaxDist) + continue; // [KS] too far + + if (lookee->LookExMinDist && dist < lookee->LookExMinDist) + continue; // [KS] too close + + if (lookee->LookExFOV && lookee->LookExFOV < ANGLE_MAX) + { + an = R_PointToAngle2 (lookee->x, + lookee->y, + other->x, + other->y) + - lookee->angle; + + if (an > (lookee->LookExFOV / 2) && an < (ANGLE_MAX - (lookee->LookExFOV / 2))) + { + // if real close, react anyway + // [KS] but respect minimum distance rules + if (lookee->LookExMinDist || dist > MELEERANGE) + continue; // outside of fov + } + } + else + { + if(!(lookee->flags4 & MF4_LOOKALLAROUND) || (lookee->LookExFOV >= ANGLE_MAX)) // Just in case angle_t doesn't clamp stuff, because I can't be too sure. + { + an = R_PointToAngle2 (lookee->x, + lookee->y, + other->x, + other->y) + - lookee->angle; + + if (an > ANG90 && an < ANG270) + { + // if real close, react anyway + // [KS] but respect minimum distance rules + if (lookee->LookExMinDist || dist > MELEERANGE) + continue; // behind back + } + } + } + + return other; + } + return NULL; +} bool P_NewLookTID (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxdist, bool chasegoal) { AActor *other; + + actor->LookExMinDist = mindist; + actor->LookExMaxDist = maxdist; + actor->LookExFOV = fov; + other = P_BlockmapSearch (actor, 0, LookForTIDinBlockEx); + bool reachedend = false; fixed_t dist; angle_t an; - other = P_BlockmapSearch (actor, 0, LookForTIDinBlock); + if (other != NULL) + { + if (!(actor->flags3 & MF3_NOSIGHTCHECK)) + { + dist = P_AproxDistance (other->x - actor->x, + other->y - actor->y); + + if (maxdist && dist > maxdist) + { + other = NULL; // [KS] too far + goto endcheck; + } + + if (mindist && dist < mindist) + { + other = NULL; // [KS] too close + goto endcheck; + } + + if (fov && fov < ANGLE_MAX) + { + an = R_PointToAngle2 (actor->x, + actor->y, + other->x, + other->y) + - actor->angle; + + if (an > (fov / 2) && an < (ANGLE_MAX - (fov / 2))) + { + // if real close, react anyway + // [KS] but respect minimum distance rules + if (mindist || dist > MELEERANGE) + { + other = NULL; // outside of fov + goto endcheck; + } + } + } + else + { + if(!((actor->flags4 & MF4_LOOKALLAROUND) || (fov >= ANGLE_MAX))) // Just in case angle_t doesn't clamp stuff, because I can't be too sure. + { + an = R_PointToAngle2 (actor->x, + actor->y, + other->x, + other->y) + - actor->angle; + + if (an > ANG90 && an < ANG270) + { + // if real close, react anyway + // [KS] but respect minimum distance rules + if (mindist || dist > MELEERANGE) + { + other = NULL; // behind back + goto endcheck; + } + } + } + } + } + } + + endcheck: if (other != NULL) { @@ -113,7 +405,7 @@ bool P_NewLookTID (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxdist, if (mindist && dist < mindist) continue; // [KS] too close - if (fov) + if (fov && fov < ANGLE_MAX) { an = R_PointToAngle2 (actor->x, actor->y, @@ -131,17 +423,21 @@ bool P_NewLookTID (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxdist, } else { - an = R_PointToAngle2 (actor->x, - actor->y, - other->x, - other->y) - - actor->angle; - - if (an > ANG90 && an < ANG270) + if(!((actor->flags4 & MF4_LOOKALLAROUND) || (fov >= ANGLE_MAX))) // Just in case angle_t doesn't clamp stuff, because I can't be too sure. { - // if real close, react anyway - if (dist > MELEERANGE) - continue; // behind back + an = R_PointToAngle2 (actor->x, + actor->y, + other->x, + other->y) + - actor->angle; + + if (an > ANG90 && an < ANG270) + { + // if real close, react anyway + // [KS] but respect minimum distance rules + if (mindist || dist > MELEERANGE) + continue; // behind back + } } } } @@ -182,6 +478,51 @@ bool P_NewLookTID (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxdist, return false; } +bool P_NewLookEnemies (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxdist, bool chasegoal) +{ + AActor *other; + + actor->LookExMinDist = mindist; + actor->LookExMaxDist = maxdist; + actor->LookExFOV = fov; + other = P_BlockmapSearch (actor, 10, LookForEnemiesInBlockEx); + + if (other != NULL) + { + if (actor->goal && actor->target == actor->goal) + actor->reactiontime = 0; + + actor->target = other; +// actor->LastLook.Actor = other; + return true; + } + + if (actor->target == NULL) + { + // [RH] use goal as target + if (actor->goal != NULL) + { + actor->target = actor->goal; + return true; + } + // Use last known enemy if no hatee sighted -- killough 2/15/98: + if (actor->lastenemy != NULL && actor->lastenemy->health > 0) + { + if (!actor->IsFriend(actor->lastenemy)) + { + actor->target = actor->lastenemy; + actor->lastenemy = NULL; + return true; + } + else + { + actor->lastenemy = NULL; + } + } + } + return false; +} + bool P_NewLookPlayers (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxdist, bool chasegoal) { int c; @@ -204,7 +545,7 @@ bool P_NewLookPlayers (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxd } else if (actor->flags & MF_FRIENDLY) { - return P_LookForEnemies (actor, fov? (fov > ANG270) : 0); + return P_NewLookEnemies (actor, fov, mindist, maxdist, chasegoal); } if (!(gameinfo.gametype & (GAME_Doom|GAME_Strife)) && @@ -307,17 +648,21 @@ bool P_NewLookPlayers (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxd } else { - an = R_PointToAngle2 (actor->x, - actor->y, - player->mo->x, - player->mo->y) - - actor->angle; - - if (an > ANG90 && an < ANG270) + if(!((actor->flags4 & MF4_LOOKALLAROUND) || (fov >= ANGLE_MAX))) { - // if real close, react anyway - if (dist > MELEERANGE) - continue; // behind back + an = R_PointToAngle2 (actor->x, + actor->y, + player->mo->x, + player->mo->y) + - actor->angle; + + if (an > ANG90 && an < ANG270) + { + // if real close, react anyway + // [KS] but respect minimum distance rules + if (mindist || dist > MELEERANGE) + continue; // behind back + } } } if ((player->mo->flags & MF_SHADOW && !(i_compatflags & COMPATF_INVISIBILITY)) || @@ -386,8 +731,6 @@ void A_LookEx (AActor *actor) AActor *targ = NULL; // Shuts up gcc fixed_t dist; - // [KS] I -had- some sanity checks for the parameters here but they caused the rest of the code to fail so I removed them again. - // [RH] Set goal now if appropriate if (actor->special == Thing_SetGoal && actor->args[0] == 0) { @@ -409,8 +752,7 @@ void A_LookEx (AActor *actor) { if (!(flags & LOF_NOSOUNDCHECK)) { - targ = (i_compatflags & COMPATF_SOUNDTARGET || actor->flags & MF_NOSECTOR)? - actor->Sector->SoundTarget : actor->LastHeard; + targ = actor->LastHeard; if (targ != NULL) { // [RH] If the soundtarget is dead, don't chase it @@ -418,15 +760,17 @@ void A_LookEx (AActor *actor) { targ = NULL; } - - dist = P_AproxDistance (targ->x - actor->x, - targ->y - actor->y); - - // [KS] If the target is too far away, don't respond to the sound. - if (maxheardist && dist > maxheardist) + else { - targ = NULL; - actor->LastHeard = NULL; + dist = P_AproxDistance (targ->x - actor->x, + targ->y - actor->y); + + // [KS] If the target is too far away, don't respond to the sound. + if (maxheardist && dist > maxheardist) + { + targ = NULL; + actor->LastHeard = NULL; + } } } @@ -447,51 +791,57 @@ void A_LookEx (AActor *actor) { if (actor->IsFriend (targ)) // be a little more precise! { - if (!(flags & LOF_NOSIGHTCHECK)) + if (!(actor->flags4 & MF4_STANDSTILL)) { - // If we find a valid target here, the wandering logic should *not* - // be activated! If would cause the seestate to be set twice. - if (P_NewLookPlayers(actor, fov, minseedist, maxseedist, !(flags & LOF_DONTCHASEGOAL))) - goto seeyou; - } - - // Let the actor wander around aimlessly looking for a fight - if (actor->SeeState != NULL) - { - if (!(actor->flags & MF_INCHASE)) + if (!(flags & LOF_NOSIGHTCHECK)) { - if (seestate) + // If we find a valid target here, the wandering logic should *not* + // be activated! If would cause the seestate to be set twice. + if (P_NewLookPlayers(actor, fov, minseedist, maxseedist, !(flags & LOF_DONTCHASEGOAL))) + goto seeyou; + } + + // Let the actor wander around aimlessly looking for a fight + if (actor->SeeState != NULL) + { + if (!(actor->flags & MF_INCHASE)) { - actor->SetState (seestate); - } - else - { - actor->SetState (actor->SeeState); + if (seestate) + { + actor->SetState (seestate); + } + else + { + actor->SetState (actor->SeeState); + } } } - } - else - { - A_Wander (actor); + else + { + A_Wander (actor); + } } } else { actor->target = targ; //We already have a target? - if (actor->flags & MF_AMBUSH) + if (targ != NULL) { - dist = P_AproxDistance (targ->x - actor->x, - targ->y - actor->y); - if (P_CheckSight (actor, actor->target, 2) && - (!minseedist || dist > minseedist) && - (!maxseedist || dist < maxseedist)) + if (actor->flags & MF_AMBUSH) { - goto seeyou; + dist = P_AproxDistance (targ->x - actor->x, + targ->y - actor->y); + if (P_CheckSight (actor, actor->target, 2) && + (!minseedist || dist > minseedist) && + (!maxseedist || dist < maxseedist)) + { + goto seeyou; + } } + else + goto seeyou; } - else - goto seeyou; } } diff --git a/src/thingdef_codeptr.cpp b/src/thingdef_codeptr.cpp index c88bb8bc4..3058521e5 100644 --- a/src/thingdef_codeptr.cpp +++ b/src/thingdef_codeptr.cpp @@ -2113,4 +2113,56 @@ void A_ClearTarget(AActor * self) } } +//========================================================================== +// +// A_JumpIfTargetInLOS (fixed fov, state label) +// Jumps if the actor can see it's target, or if the player has a linetarget. +// +//========================================================================== + +void A_JumpIfTargetInLOS(AActor * self) +{ + FState * CallingState; + int index = CheckIndex(2, &CallingState); + angle_t an; + angle_t fov = angle_t(EvalExpressionF (StateParameters[index], self) * FRACUNIT); + AActor * target; + + if (pStateCall != NULL) pStateCall->Result=false; // Jumps should never set the result for inventory state chains! + + if (!self->player) + { + target=self->target; + + if (!P_CheckSight (self, target, 1)) + return; // [KS] Cannot see target - return + + if (fov && (fov < ANGLE_MAX)) + { + an = R_PointToAngle2 (self->x, + self->y, + target->x, + target->y) + - self->angle; + + if (an > (fov / 2) && an < (ANGLE_MAX - (fov / 2))) + { + return; // [KS] Outside of FOV - return + } + + } + } + else + { + // Does the player aim at something that can be shot? + P_BulletSlope(self); + target = linetarget; + } + + // No target - return + if (target==NULL) return; + + DoJump(self, CallingState, StateParameters[index+1]); +} + // [KS] *** End of my modifications *** \ No newline at end of file diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 11179992e..2be618c1b 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -92,7 +92,10 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v { if (parms.font != NULL) { - dc_colormap = parms.font->GetColorTranslation (EColorRange(parms.translation)); + if (img->UseType == FTexture::TEX_FontChar) + dc_colormap = parms.font->GetColorTranslation (EColorRange(parms.translation)); + else + dc_colormap = identitymap; } else if (parms.translation != 0) { @@ -101,7 +104,7 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v else { dc_colormap = identitymap; - } + } } BYTE *destorgsave = dc_destorg; @@ -625,6 +628,51 @@ void DCanvas::FillBorder (FTexture *img) } } +// This was in m_menu.cpp but it's better to be here because +// non-software renderers must be able to override it. +void DCanvas::DrawPlayerBackdrop (DCanvas *src, const BYTE *FireRemap, int x, int y) +{ + DCanvas *dest = screen; + BYTE *destline, *srcline; + const int destwidth = src->GetWidth() * CleanXfac / 2; + const int destheight = src->GetHeight() * CleanYfac / 2; + const int desty = y; + const int destx = x; + const fixed_t fracxstep = FRACUNIT*2 / CleanXfac; + const fixed_t fracystep = FRACUNIT*2 / CleanYfac; + fixed_t fracx, fracy = 0; + + src->Lock(); + + if (fracxstep == FRACUNIT) + { + for (y = desty; y < desty + destheight; y++, fracy += fracystep) + { + srcline = src->GetBuffer() + (fracy >> FRACBITS) * src->GetPitch(); + destline = dest->GetBuffer() + y * dest->GetPitch() + destx; + + for (x = 0; x < destwidth; x++) + { + destline[x] = FireRemap[srcline[x]]; + } + } + } + else + { + for (y = desty; y < desty + destheight; y++, fracy += fracystep) + { + srcline = src->GetBuffer() + (fracy >> FRACBITS) * src->GetPitch(); + destline = dest->GetBuffer() + y * dest->GetPitch() + destx; + for (x = fracx = 0; x < destwidth; x++, fracx += fracxstep) + { + destline[x] = FireRemap[srcline[fracx >> FRACBITS]]; + } + } + } + + src->Unlock(); +} + /********************************/ /* */ diff --git a/src/v_font.cpp b/src/v_font.cpp index d46b6ec8e..2831b1c80 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -726,6 +726,7 @@ FFont::FFont () { Chars = NULL; Ranges = NULL; + PalRanges = NULL; PatchRemap = NULL; Name = NULL; } diff --git a/src/v_video.h b/src/v_video.h index d4dbc68ff..2bd1b3166 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -167,6 +167,9 @@ public: // Set an area to a specified color virtual void Clear (int left, int top, int right, int bottom, int palcolor, uint32 color) const; + // renders the player backdrop for the menu + virtual void DrawPlayerBackdrop (DCanvas *src, const BYTE *FireRemap, int x, int y); + // Calculate gamma table void CalcGamma (float gamma, BYTE gammalookup[256]); diff --git a/wadsrc/decorate/nativeclasses.txt b/wadsrc/decorate/nativeclasses.txt index ca4b3be08..4b2a25c5d 100644 --- a/wadsrc/decorate/nativeclasses.txt +++ b/wadsrc/decorate/nativeclasses.txt @@ -172,7 +172,8 @@ class Actor extends Thinker action native A_QueueCorpse(); action native A_DeQueueCorpse(); action native A_LookEx(optional eval int flags, optional eval float minseedist, optional eval float maxseedist, optional eval float maxheardist, optional eval float fov, optional state label); - action native A_ClearTarget(); + action native A_ClearTarget(); + action native A_JumpIfTargetInLOS (state label, optional eval float fov); action native A_SelectWeapon(class whichweapon); }