- 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)
This commit is contained in:
Christoph Oelckers 2007-12-23 21:56:46 +00:00
parent 7ae2a4e35c
commit 8a433d6f12
11 changed files with 545 additions and 117 deletions

View file

@ -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.

View file

@ -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

View file

@ -104,5 +104,7 @@ ACTOR(SetGravity)
ACTOR(ItBurnsItBurns)
ACTOR(CrispyPlayer)
ACTOR(DropFire)
ACTOR(ClearTarget)
ACTOR(LookEx)
ACTOR(JumpIfTargetInLOS)

View file

@ -86,6 +86,7 @@ void ASkyViewpoint::Destroy ()
sectors[i].CeilingSkyBox = NULL;
}
}
Super::Destroy();
}
//---------------------------------------------------------------------------

View file

@ -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)

View file

@ -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,
@ -130,6 +422,8 @@ bool P_NewLookTID (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxdist,
}
}
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,
@ -140,11 +434,13 @@ bool P_NewLookTID (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxdist,
if (an > ANG90 && an < ANG270)
{
// if real close, react anyway
if (dist > MELEERANGE)
// [KS] but respect minimum distance rules
if (mindist || dist > MELEERANGE)
continue; // behind back
}
}
}
}
// [RH] Need to be sure the reactiontime is 0 if the monster is
// leaving its goal to go after something else.
@ -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)) &&
@ -306,6 +647,8 @@ bool P_NewLookPlayers (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxd
}
}
else
{
if(!((actor->flags4 & MF4_LOOKALLAROUND) || (fov >= ANGLE_MAX)))
{
an = R_PointToAngle2 (actor->x,
actor->y,
@ -316,10 +659,12 @@ bool P_NewLookPlayers (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxd
if (an > ANG90 && an < ANG270)
{
// if real close, react anyway
if (dist > MELEERANGE)
// [KS] but respect minimum distance rules
if (mindist || dist > MELEERANGE)
continue; // behind back
}
}
}
if ((player->mo->flags & MF_SHADOW && !(i_compatflags & COMPATF_INVISIBILITY)) ||
player->mo->flags3 & MF3_GHOST)
{
@ -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,7 +760,8 @@ void A_LookEx (AActor *actor)
{
targ = NULL;
}
else
{
dist = P_AproxDistance (targ->x - actor->x,
targ->y - actor->y);
@ -429,6 +772,7 @@ void A_LookEx (AActor *actor)
actor->LastHeard = NULL;
}
}
}
if (targ && targ->player && (targ->player->cheats & CF_NOTARGET))
{
@ -446,6 +790,8 @@ void A_LookEx (AActor *actor)
if (targ && (targ->flags & MF_SHOOTABLE))
{
if (actor->IsFriend (targ)) // be a little more precise!
{
if (!(actor->flags4 & MF4_STANDSTILL))
{
if (!(flags & LOF_NOSIGHTCHECK))
{
@ -475,10 +821,13 @@ void A_LookEx (AActor *actor)
A_Wander (actor);
}
}
}
else
{
actor->target = targ; //We already have a target?
if (targ != NULL)
{
if (actor->flags & MF_AMBUSH)
{
dist = P_AproxDistance (targ->x - actor->x,
@ -494,6 +843,7 @@ void A_LookEx (AActor *actor)
goto seeyou;
}
}
}
if (!(flags & LOF_NOSIGHTCHECK))
{

View file

@ -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 ***

View file

@ -92,7 +92,10 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v
{
if (parms.font != NULL)
{
if (img->UseType == FTexture::TEX_FontChar)
dc_colormap = parms.font->GetColorTranslation (EColorRange(parms.translation));
else
dc_colormap = identitymap;
}
else if (parms.translation != 0)
{
@ -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();
}
/********************************/
/* */

View file

@ -726,6 +726,7 @@ FFont::FFont ()
{
Chars = NULL;
Ranges = NULL;
PalRanges = NULL;
PatchRemap = NULL;
Name = NULL;
}

View file

@ -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]);

View file

@ -173,6 +173,7 @@ class Actor extends Thinker
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_JumpIfTargetInLOS (state label, optional eval float fov);
action native A_SelectWeapon(class<Weapon> whichweapon);
}