- Sync with trunk.

SVN r1872 (scripting)
This commit is contained in:
Randy Heit 2009-09-23 00:24:47 +00:00
commit 1a442742f7
167 changed files with 1887 additions and 2342 deletions

View File

@ -1,3 +1,101 @@
September 22, 2009
- Added a technique to try and minimize input lag with vsync enabled: Two
surfaces are alternately locked for read-only access each frame, forcing
the driver to stop buffering more than one frame at a time. The input lag
on my system doesn't seem to be as bad as it once was (I can no longer
see it obviously with my naked eye), but turning antilag on "feels"
slightly more responsive. The cvar d3d_antilag turns this technique on and
off. See <http://www.xyzw.de/c120.html> for more details.
September 22, 2009 (Changes by Graf Zahl)
- Added a check to Dehacked code which tries to set the blend color.
It must set it to 0 if the alpha is 0 to avoid problems with special
colormap detection.
- Changed SPECIALCOLORMAP_MASK again so that it does not interfere with
any valid setting. It must use a value with a 0-alpha because these
are guaranteed not to be produced by the DECORATE code elsewhere.
- Fixed precision issues with AddFixedColormap's search for identical colormaps.
- Added custom colormap support to texture composition code.
- Fixed initialization of FSpecialColormap::GrayscaleToColor. This is not
a mapping from the palette but from a [0,255] grayscale ramp and used to
apply colormaps to true color images for texture composition.
September 21, 2009
- For hardware 2D, apply fixed colormaps when copying to video memory instead
of doing it directly during the rendering, in order to improve visual
fidelity for colormaps that aren't grayscale.
- Added support for defining the full color range of a special colormap.
- Moved the code for specialcolormap and colormapstyle in D3DFB::SetStyle()
at the end of the normally-colored block so that they get all the proper
texture format setup.
- Fixed: In letterbox modes, the clipping window needs to be adjusted down.
September 21, 2009 (Changes by Graf Zahl)
- Fixed: When drawing with a special colormap the quad's flags weren't cleared
which could cause crashes.
- Added custom special colormaps to DECORATE.
- Cleaned up special colormap code and removed lots of dependencies on the
knowledge of the tables' contents.
September 20, 2009 (Changes by Graf Zahl)
- Changed call to R_DrawRemainingPlayerSprites into a virtual function
of DFrameBuffer because its implementation is specific to the software
renderer and needs to be overridable.
September 19, 2009
- Fixed: Wall drawing handled fixed light levels improperly (but did not
completely ignore them, either).
- Separated light level fixing out of player_t's fixedcolormap parameter.
Using a fixed light level (e.g. PowerTorch) will no longer wipe out
colored lighting.
- Moved the blending rectangle drawing into a separate discrete stage, since
doing it while copying the 3D view window to the display now blends
underneath the weapon instead of on top of it.
- Consolidated the special colormaps into a single 2D table.
- Tweaked the special colormaps slightly to make the true color results more
closely match the paletted approximations.
- fb_d3d9_shaders.h was getting unwieldy, so I moved the shaders out of the
executable and into zdoom.pk3. Shaders are still precompiled so I don't need
to pull in a dependancy on D3DX.
- Added a few more shaders to accomodate drawing weapons with all the in-game
lighting models. These are accessed with the new DrawTexture tags
DTA_SpecialColormap and DTA_ColormapStyle.
- Player weapon sprites are now drawn using Direct3D and receive all the
benefits thereof.
September 17, 2009 (Changes by Graf Zahl)
- Fixed: Unmorphing while invulnerable was blocked.
- Various cleanup changes.
- fixed Dog's class name in DEHSUPP.
- Renamed plane flags from SECF_* to PLANEF_*.
- Changed Heretic's plat raise type to use a flag to block further sector movement
instead of keeping the dead thinker around to block the sector.
September 16, 2009 (Changes by Graf Zahl)
- Fixed: A_LookEx did not work for monsters having the MF_NOSECTOR flag.
- Fixed: The deprecated flag handler for the old bounce flags needs to clear
BOUNCE_MBF and BOUNCE_UseSeeSound, too, when clearing one of these flags.
- Fixed: When adding the AVOIDMELEE code the code was accidentally changed so that
friendly monsters could no longer acquire targets by themselves.
- Renamed WIF_BOT_MELEE to WIF_MELEEWEAPON because it's no longer a bot only flag.
- Added MBF's monster_backing feature as an actor flag: AVOIDMELEE.
- Gez's misc. bugs patch:
* Moves the dog sound out of the Doom-specific sounds in SNDINFO to address this,
* Renames the dog actor to MBFHelperDog to prevent name conflicts,
* Adds APROP_Score to CheckActorProperty,
* Completes the randomspawner update (the reason I moved the recursion counter out of
special1 was that I found some projectiles had this set to them, for example in
A_LichAttack, but I forgot to add transfer for them),
* Provides centered sprites for beta plasma balls if this is deemed deserving correction.
- Added some pieces of MBF's friendly AI.
- Cleaned up A_LookEx code and merged most of it with the base functions.
The major difference was a common piece of code that was repeated 5 times
throughout the code so I moved it into a subfunction.
- Changed P_BlockmapSearch to pass a user parameter to its callback so that
A_LookEx does not need to store its info inside the actor itself.
- fixed: The linetarget CCMD duplicated all of the info CCMD.
- fixed: PrintActorInfo crashed due to some incomplete implementation.
September 15, 2009 (Changes by Graf Zahl)
- added PinkSilver's A_Respawn enhancement patch.
- added RandomSpawner update from Gez's experimental build.
@ -16872,7 +16970,7 @@ November 14, 2000
into c_cvars.cpp. Virtual inline functions are not inlined and cause the
function to be generated for every source file the class is used in.
- Fixed bug with Transfer_CeilingLight special. I was or'ing CeilingLight
with SECF_ABSLIGHTING instead of CeilingFlags.
with PLANEF_ABSLIGHTING instead of CeilingFlags.
November 11, 2000
- Slopes don't work in mirrors. :-(

View File

@ -589,7 +589,6 @@ add_executable( zdoom WIN32
p_doors.cpp
p_effect.cpp
p_enemy.cpp
p_enemy_a_lookex.cpp
p_floor.cpp
p_interaction.cpp
p_lights.cpp

View File

@ -216,7 +216,7 @@ enum
MF3_NOBLOCKMONST = 0x00100000, // Can cross ML_BLOCKMONSTERS lines
MF3_CRASHED = 0x00200000, // Actor entered its crash state
MF3_FULLVOLDEATH = 0x00400000, // DeathSound is played full volume (for missiles)
/* = 0x00800000, */
MF3_AVOIDMELEE = 0x00800000, // Avoids melee attacks (same as MBF's monster_backing but must be explicitly set)
/* = 0x01000000, */
MF3_FOILINVUL = 0x02000000, // Actor can hurt MF2_INVULNERABLE things
MF3_NOTELEOTHER = 0x04000000, // Monster is unaffected by teleport other artifact
@ -399,7 +399,7 @@ enum EBounceFlags
// for them that are not present in ZDoom, so it is necessary to identify it properly.
BOUNCE_MBF = 1<<12, // This in itself is not a valid mode, but replaces MBF's MF_BOUNCE flag.
BOUNCE_TypeMask = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors | BOUNCE_AutoOff | BOUNCE_HereticType,
BOUNCE_TypeMask = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors | BOUNCE_AutoOff | BOUNCE_HereticType | BOUNCE_MBF,
// The three "standard" types of bounciness are:
// HERETIC - Missile will only bounce off the floor once and then enter
@ -760,6 +760,7 @@ public:
BYTE movedir; // 0-7
SBYTE visdir;
SWORD movecount; // when 0, select a new dir
SWORD strafecount; // for MF3_AVOIDMELEE
TObjPtr<AActor> target; // thing being chased/attacked (or NULL)
// also the originator for missiles
TObjPtr<AActor> lastenemy; // Last known enemy -- killough 2/15/98
@ -810,14 +811,6 @@ public:
AActor *BlockingMobj; // Actor that blocked the last move
line_t *BlockingLine; // Line that blocked the last move
// [KS] These temporary-use properties are needed to allow A_LookEx to pass its 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_t *touching_sectorlist; // phares 3/14/98

View File

@ -136,7 +136,6 @@ void InitBotStuff()
{ "SkullRod", 27000000, 0, "HornRodFX1" },
{ "SkullRodPowered", 27000000, 0, "HornRodFX2" },
{ "PhoenixRod", 18350080, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_EXPLOSIVE, "PhoenixFX1" },
{ "PhoenixRodPowered", 0, WIF_BOT_MELEE, "PhoenixFX2" },
{ "Mace", 27000000, WIF_BOT_REACTION_SKILL_THING, "MaceFX2" },
{ "MacePowered", 27000000, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_EXPLOSIVE, "MaceFX4" },
{ "FWeapHammer", 22000000, 0, "HammerMissile" },

View File

@ -175,7 +175,7 @@ void FCajunMaster::Dofire (AActor *actor, ticcmd_t *cmd)
(actor->y + actor->vely) - (enemy->y + enemy->vely));
//FIRE EACH TYPE OF WEAPON DIFFERENT: Here should all the different weapons go.
if (actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_MELEE)
if (actor->player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON)
{
if ((actor->player->ReadyWeapon->ProjectileType != NULL))
{

View File

@ -342,7 +342,7 @@ void FCajunMaster::TurnToAng (AActor *actor)
if(actor->player->enemy)
if(!actor->player->dest) //happens when running after item in combat situations, or normal, prevents weak turns
if(actor->player->ReadyWeapon->ProjectileType == NULL && !(actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_MELEE))
if(actor->player->ReadyWeapon->ProjectileType == NULL && !(actor->player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON))
if(Check_LOS(actor, actor->player->enemy, SHOOTFOV+5*ANGLE_1))
maxturn = 3;
}

View File

@ -778,7 +778,6 @@ CCMD(linetarget)
linetarget->GetClass()->TypeName.GetChars(),
linetarget->health,
linetarget->SpawnHealth());
PrintMiscActorInfo(linetarget);
}
else Printf("No target found\n");
}

View File

@ -43,6 +43,11 @@ public:
void SetPalette (const DWORD *palette);
BYTE Pick (int r, int g, int b);
BYTE Pick (PalEntry pe)
{
return Pick(pe.r, pe.g, pe.b);
}
FColorMatcher &operator= (const FColorMatcher &other);
private:

View File

@ -1793,7 +1793,7 @@ static int PatchMisc (int dummy)
{
Printf ("Bad powerup color description \"%s\" for %s\n", Line2, Line1);
}
else
else if (a > 0)
{
static_cast<APowerup *>(GetDefaultByType (*types[i]))->BlendColor = PalEntry(
BYTE(clamp(a,0.f,1.f)*255.f),
@ -1801,6 +1801,10 @@ static int PatchMisc (int dummy)
clamp(g,0,255),
clamp(b,0,255));
}
else
{
static_cast<APowerup *>(GetDefaultByType (*types[i]))->BlendColor = 0;
}
}
}
else

View File

@ -681,6 +681,8 @@ void D_Display ()
SB_state = screen->GetPageCount();
BorderNeedRefresh = screen->GetPageCount();
}
screen->DrawRemainingPlayerSprites();
screen->DrawBlendingRect();
if (automapactive)
{
int saved_ST_Y = ST_Y;

View File

@ -839,6 +839,6 @@ CCMD (playerinfo)
Printf ("PlayerClass: %s (%d)\n",
ui->PlayerClass == -1 ? "Random" : PlayerClasses[ui->PlayerClass].Type->Meta.GetMetaString (APMETA_DisplayName),
ui->PlayerClass);
PrintMiscActorInfo(players[i].mo);
if (argv.argc() > 2) PrintMiscActorInfo(players[i].mo);
}
}

View File

@ -303,7 +303,8 @@ public:
TObjPtr<AActor> poisoner; // NULL for non-player actors
TObjPtr<AActor> attacker; // who did damage (NULL for floors)
int extralight; // so gun flashes light up areas
int fixedcolormap; // can be set to REDCOLORMAP, etc.
short fixedcolormap; // can be set to REDCOLORMAP, etc.
short fixedlightlevel;
pspdef_t psprites[NUMPSPRITES]; // view sprites (gun, etc)
int morphTics; // player is a chicken/pig if > 0
BYTE MorphedPlayerClass; // [MH] (for SBARINFO) class # for this player instance when morphed

View File

@ -519,6 +519,9 @@ IMPLEMENT_ABSTRACT_CLASS(PSymbol);
IMPLEMENT_CLASS(PSymbolConst);
IMPLEMENT_CLASS(PSymbolVariable);
IMPLEMENT_CLASS(PSymbolActionFunction);
IMPLEMENT_POINTY_CLASS(PSymbolVMFunction)
DECLARE_POINTER(Function)
END_POINTERS
PSymbol::~PSymbol()
{

View File

@ -13,7 +13,8 @@ enum ESymbolType
{
SYM_Const,
SYM_Variable,
SYM_ActionFunction
SYM_ActionFunction,
SYM_VMFunction
};
class PSymbol : public DObject
@ -96,6 +97,20 @@ public:
// A symbol table -----------------------------------------------------------
class VMFunction;
class PSymbolVMFunction : public PSymbol
{
DECLARE_CLASS(PSymbolVMFunction, PSymbol);
HAS_OBJECT_POINTERS;
public:
VMFunction *Function;
PSymbolVMFunction(FName name) : PSymbol(name, SYM_VMFunction) {}
PSymbolVMFunction() : PSymbol(NAME_None, SYM_VMFunction) {}
};
// A symbol table -----------------------------------------------------------
struct PSymbolTable
{
PSymbolTable();

View File

@ -238,7 +238,7 @@ static void SpawnFly(AActor *self, const PClass *spawntype, FSoundID sound)
{
newmobj->CopyFriendliness (eye, false);
}
if (newmobj->SeeState != NULL && P_LookForPlayers (newmobj, true))
if (newmobj->SeeState != NULL && P_LookForPlayers (newmobj, true, NULL))
newmobj->SetState (newmobj->SeeState);
if (!(newmobj->ObjectFlags & OF_EuthanizeMe))

View File

@ -168,7 +168,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_M_Refire)
{
if (self->MissileState && pr_m_refire() < 160)
{ // Look for a new target most of the time
if (P_LookForPlayers (self, true) && P_CheckMissileRange (self))
if (P_LookForPlayers (self, true, NULL) && P_CheckMissileRange (self))
{ // Found somebody new and in range, so don't stop shooting
return;
}

View File

@ -1195,7 +1195,8 @@ void G_PlayerFinishLevel (int player, EFinishLevelType mode, bool resetinventory
p->mo->RenderStyle = STYLE_Normal;
p->mo->alpha = FRACUNIT;
p->extralight = 0; // cancel gun flashes
p->fixedcolormap = 0; // cancel ir goggles
p->fixedcolormap = NOFIXEDCOLORMAP; // cancel ir goggles
p->fixedlightlevel = -1;
p->damagecount = 0; // no palette changes
p->bonuscount = 0;
p->poisoncount = 0;
@ -1230,7 +1231,7 @@ void G_PlayerFinishLevel (int player, EFinishLevelType mode, bool resetinventory
if (p->morphTics)
{ // Undo morph
P_UndoPlayerMorph (p, p, true);
P_UndoPlayerMorph (p, p, 0, true);
}
// Clears the entire inventory and gives back the defaults for starting a game

View File

@ -24,7 +24,7 @@ bool AArtiTomeOfPower::Use (bool pickup)
{
if (Owner->player->morphTics && (Owner->player->MorphStyle & MORPH_UNDOBYTOMEOFPOWER))
{ // Attempt to undo chicken
if (!P_UndoPlayerMorph (Owner->player, Owner->player))
if (!P_UndoPlayerMorph (Owner->player, Owner->player, MORPH_UNDOBYTOMEOFPOWER))
{ // Failed
if (!(Owner->player->MorphStyle & MORPH_FAILNOTELEFRAG))
{

View File

@ -213,7 +213,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DragonFlight)
}
else
{
P_LookForPlayers (self, true);
P_LookForPlayers (self, true, NULL);
}
}

View File

@ -145,7 +145,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FiredChase)
if(!self->target || !(self->target->flags&MF_SHOOTABLE))
{ // Invalid target
P_LookForPlayers (self,true);
P_LookForPlayers (self,true, NULL);
return;
}

View File

@ -19,7 +19,7 @@ void A_DropBloodscourgePieces (AActor *);
void A_MStaffAttack (AActor *actor);
void A_MStaffPalette (AActor *actor);
static AActor *FrontBlockCheck (AActor *mo, int index);
static AActor *FrontBlockCheck (AActor *mo, int index, void *);
static divline_t BlockCheckLine;
//==========================================================================
@ -254,7 +254,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MStaffTrack)
//
//============================================================================
static AActor *FrontBlockCheck (AActor *mo, int index)
static AActor *FrontBlockCheck (AActor *mo, int index, void *)
{
FBlockNode *link;

View File

@ -45,7 +45,8 @@ bool AArtiTeleport::Use (bool pickup)
bool canlaugh = true;
if (Owner->player->morphTics && (Owner->player->MorphStyle & MORPH_UNDOBYCHAOSDEVICE))
{ // Teleporting away will undo any morph effects (pig)
if (!P_UndoPlayerMorph (Owner->player, Owner->player) && (Owner->player->MorphStyle & MORPH_FAILNOLAUGH))
if (!P_UndoPlayerMorph (Owner->player, Owner->player, MORPH_UNDOBYCHAOSDEVICE)
&& (Owner->player->MorphStyle & MORPH_FAILNOLAUGH))
{
canlaugh = false;
}

View File

@ -139,14 +139,7 @@ PalEntry APowerup::GetBlend ()
if (EffectTics <= BLINKTHRESHOLD && !(EffectTics & 8))
return 0;
if (BlendColor == INVERSECOLOR ||
BlendColor == GOLDCOLOR ||
// [BC] HAX!
BlendColor == REDCOLOR ||
BlendColor == GREENCOLOR ||
BlendColor == BLUECOLOR)
return 0;
if (IsSpecialColormap(BlendColor)) return 0;
return BlendColor;
}
@ -175,37 +168,19 @@ void APowerup::DoEffect ()
if (EffectTics > 0)
{
int oldcolormap = Owner->player->fixedcolormap;
if (EffectTics > BLINKTHRESHOLD || (EffectTics & 8))
int Colormap = GetSpecialColormap(BlendColor);
if (Colormap != NOFIXEDCOLORMAP)
{
if (BlendColor == INVERSECOLOR)
if (EffectTics > BLINKTHRESHOLD || (EffectTics & 8))
{
Owner->player->fixedcolormap = INVERSECOLORMAP;
Owner->player->fixedcolormap = Colormap;
}
else if (BlendColor == GOLDCOLOR)
else if (Owner->player->fixedcolormap == Colormap)
{
Owner->player->fixedcolormap = GOLDCOLORMAP;
// only unset if the fixed colormap comes from this item
Owner->player->fixedcolormap = NOFIXEDCOLORMAP;
}
else if (BlendColor == REDCOLOR)
{
Owner->player->fixedcolormap = REDCOLORMAP;
}
else if (BlendColor == GREENCOLOR)
{
Owner->player->fixedcolormap = GREENCOLORMAP;
}
else if (BlendColor == BLUECOLOR)
{
Owner->player->fixedcolormap = BLUECOLORMAP;
}
}
else if ((BlendColor == INVERSECOLOR && Owner->player->fixedcolormap == INVERSECOLORMAP) ||
(BlendColor == GOLDCOLOR && Owner->player->fixedcolormap == GOLDCOLORMAP) ||
(BlendColor == REDCOLOR && Owner->player->fixedcolormap == REDCOLORMAP) ||
(BlendColor == GREENCOLOR && Owner->player->fixedcolormap == GREENCOLORMAP) ||
(BlendColor == BLUECOLOR && Owner->player->fixedcolormap == BLUECOLORMAP))
{
Owner->player->fixedcolormap = 0;
}
}
}
@ -471,7 +446,7 @@ void APowerInvulnerable::EndEffect ()
if (Owner->player != NULL)
{
Owner->player->fixedcolormap = 0;
Owner->player->fixedcolormap = NOFIXEDCOLORMAP;
}
}
@ -565,7 +540,7 @@ IMPLEMENT_CLASS (APowerInvisibility)
IMPLEMENT_CLASS (APowerShadow)
// Invisibility flag combos
#define INVISIBILITY_FLAGS1 (MF_SHADOW | MF_STEALTH)
#define INVISIBILITY_FLAGS1 (MF_SHADOW)
#define INVISIBILITY_FLAGS3 (MF3_GHOST)
#define INVISIBILITY_FLAGS5 (MF5_CANTSEEK)
@ -590,24 +565,6 @@ void APowerInvisibility::InitEffect ()
flags5 &= ~(Owner->flags5 & INVISIBILITY_FLAGS5);
Owner->flags5 |= flags5 & INVISIBILITY_FLAGS5;
// Finds out what's the normal alpha and render style for the owner.
// First assume it's what it currently is.
//OwnersNormalStyle = Owner->RenderStyle;
//OwnersNormalAlpha = Owner->alpha;
// Then look if there aren't active invis powerups and look what they're saying.
/*AInventory *item = Owner->Inventory;
while (item != NULL)
{
if (item->IsKindOf(RUNTIME_CLASS(APowerInvisibility)) && item != this)
{
OwnersNormalStyle = static_cast<APowerInvisibility*>(item)->OwnersNormalStyle;
OwnersNormalAlpha = static_cast<APowerInvisibility*>(item)->OwnersNormalAlpha;
item = NULL; // No need to look further
}
else item = item->Inventory;
}
Printf("Owner's normal style is found to be %i, normal alpha is found to be %i.\n",
OwnersNormalStyle, OwnersNormalAlpha>>FRACBITS);*/
DoEffect();
}
}
@ -623,7 +580,7 @@ void APowerInvisibility::DoEffect ()
// Due to potential interference with other PowerInvisibility items
// the effect has to be refreshed each tic.
fixed_t ts = Strength * (special1 + 1); if (ts > FRACUNIT) ts = FRACUNIT;
Owner->alpha = clamp<fixed_t>((/*OwnersNormalAlpha*/OPAQUE - ts), 0, OPAQUE);
Owner->alpha = clamp<fixed_t>((OPAQUE - ts), 0, OPAQUE);
switch (Mode)
{
case (NAME_Fuzzy):
@ -639,6 +596,7 @@ void APowerInvisibility::DoEffect ()
Owner->RenderStyle = STYLE_Stencil;
break;
case (NAME_None):
case (NAME_Cumulative):
case (NAME_Translucent):
Owner->RenderStyle = STYLE_Translucent;
break;
@ -663,8 +621,8 @@ void APowerInvisibility::EndEffect ()
Owner->flags3 &= ~(flags3 & INVISIBILITY_FLAGS3);
Owner->flags5 &= ~(flags5 & INVISIBILITY_FLAGS5);
Owner->RenderStyle = STYLE_Normal;//OwnersNormalStyle;
Owner->alpha = OPAQUE;//OwnersNormalAlpha;
Owner->RenderStyle = STYLE_Normal;
Owner->alpha = OPAQUE;
// Check whether there are other invisibility items and refresh their effect.
// If this isn't done there will be one incorrectly drawn frame when this
@ -693,15 +651,15 @@ int APowerInvisibility::AlterWeaponSprite (vissprite_t *vis)
// Blink if the powerup is wearing off
if (changed == 0 && EffectTics < 4*32 && !(EffectTics & 8))
{
vis->RenderStyle = STYLE_Normal;//OwnersNormalStyle;
vis->alpha = OPAQUE;//OwnersNormalAlpha;
vis->RenderStyle = STYLE_Normal;
vis->alpha = OPAQUE;
return 1;
}
else if (changed == 1)
{
// something else set the weapon sprite back to opaque but this item is still active.
fixed_t ts = Strength * (special1 + 1); if (ts > FRACUNIT) ts = FRACUNIT;
vis->alpha = clamp<fixed_t>((/*OwnersNormalAlpha*/OPAQUE - ts), 0, OPAQUE);
vis->alpha = clamp<fixed_t>((OPAQUE - ts), 0, OPAQUE);
switch (Mode)
{
case (NAME_Fuzzy):
@ -728,7 +686,7 @@ int APowerInvisibility::AlterWeaponSprite (vissprite_t *vis)
if ((vis->alpha < TRANSLUC25 && special1 > 0) || (vis->alpha == 0))
{
vis->alpha = clamp<fixed_t>((OPAQUE - Strength), 0, OPAQUE);
vis->colormap = InverseColormap;
vis->colormap = SpecialColormaps[INVERSECOLORMAP].Colormap;
}
return -1; // This item is valid so another one shouldn't reset the translucency
}
@ -847,11 +805,11 @@ void APowerLightAmp::DoEffect ()
{
if (EffectTics > BLINKTHRESHOLD || (EffectTics & 8))
{
Owner->player->fixedcolormap = 1;
Owner->player->fixedlightlevel = 1;
}
else
{
Owner->player->fixedcolormap = 0;
Owner->player->fixedlightlevel = -1;
}
}
}
@ -866,7 +824,7 @@ void APowerLightAmp::EndEffect ()
{
if (Owner != NULL && Owner->player != NULL && Owner->player->fixedcolormap < NUMCOLORMAPS)
{
Owner->player->fixedcolormap = 0;
Owner->player->fixedlightlevel = -1;
}
}
@ -911,22 +869,22 @@ void APowerTorch::DoEffect ()
{
if (NewTorch != 0)
{
if (Owner->player->fixedcolormap + NewTorchDelta > 7
|| Owner->player->fixedcolormap + NewTorchDelta < 1
|| NewTorch == Owner->player->fixedcolormap)
if (Owner->player->fixedlightlevel + NewTorchDelta > 7
|| Owner->player->fixedlightlevel + NewTorchDelta < 0
|| NewTorch == Owner->player->fixedlightlevel)
{
NewTorch = 0;
}
else
{
Owner->player->fixedcolormap += NewTorchDelta;
Owner->player->fixedlightlevel += NewTorchDelta;
}
}
else
{
NewTorch = (pr_torch() & 7) + 1;
NewTorchDelta = (NewTorch == Owner->player->fixedcolormap) ?
0 : ((NewTorch > Owner->player->fixedcolormap) ? 1 : -1);
NewTorchDelta = (NewTorch == Owner->player->fixedlightlevel) ?
0 : ((NewTorch > Owner->player->fixedlightlevel) ? 1 : -1);
}
}
}

View File

@ -3,14 +3,6 @@
#include "a_pickups.h"
#define INVERSECOLOR 0x00345678
#define GOLDCOLOR 0x009abcde
// [BC] More hacks!
#define REDCOLOR 0x00beefee
#define GREENCOLOR 0x00beefad
#define BLUECOLOR 0x00befeed
class player_t;
// A powerup is a pseudo-inventory item that applies an effect to its

View File

@ -173,7 +173,7 @@ bool P_MorphPlayer (player_t *activator, player_t *p, const PClass *spawntype, i
//
//----------------------------------------------------------------------------
bool P_UndoPlayerMorph (player_t *activator, player_t *player, bool force)
bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag, bool force)
{
AWeapon *beastweap;
APlayerPawn *mo;
@ -192,10 +192,13 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, bool force)
return false;
}
if ((pmo->flags2 & MF2_INVULNERABLE) && ((player != activator) || (!(player->MorphStyle & MORPH_WHENINVULNERABLE))))
{ // Immune when invulnerable unless this is something we initiated.
// If the WORLD is the initiator, the same player should be given
// as the activator; WORLD initiated actions should always succeed.
bool DeliberateUnmorphIsOkay = !!(player->MorphStyle & unmorphflag);
if ((pmo->flags2 & MF2_INVULNERABLE) // If the player is invulnerable
&& ((player != activator) // and either did not decide to unmorph,
|| (!((player->MorphStyle & MORPH_WHENINVULNERABLE) // or the morph style does not allow it
|| (DeliberateUnmorphIsOkay))))) // (but standard morph styles always allow it),
{ // Then the player is immune to the unmorph.
return false;
}

View File

@ -17,7 +17,7 @@ enum
MORPH_UNDOBYCHAOSDEVICE = 0x00000008, // Player unmorphs upon activating a Chaos Device
MORPH_FAILNOTELEFRAG = 0x00000010, // Player stays morphed if unmorph by Tome of Power fails
MORPH_FAILNOLAUGH = 0x00000020, // Player doesn't laugh if unmorph by Chaos Device fails
MORPH_WHENINVULNERABLE = 0x00000040, // Player can morph (or scripted unmorph) when invulnerable but ONLY if doing it to themselves
MORPH_WHENINVULNERABLE = 0x00000040, // Player can morph when invulnerable but ONLY if doing it to themselves
MORPH_LOSEACTUALWEAPON = 0x00000080, // Player loses specified morph weapon only (not "whichever they have when unmorphing")
MORPH_NEWTIDBEHAVIOUR = 0x00000100, // Actor TID is by default transferred from the old actor to the new actor
MORPH_UNDOBYDEATH = 0x00000200, // Actor unmorphs when killed and (unless MORPH_UNDOBYDEATHSAVES) stays dead
@ -32,7 +32,7 @@ class AMorphedMonster;
bool P_MorphPlayer (player_t *activator, player_t *player, const PClass *morphclass, int duration = 0, int style = 0,
const PClass *enter_flash = NULL, const PClass *exit_flash = NULL);
bool P_UndoPlayerMorph (player_t *activator, player_t *player, bool force = false);
bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag = 0, bool force = false);
bool P_MorphMonster (AActor *actor, const PClass *morphclass, int duration = 0, int style = 0,
const PClass *enter_flash = NULL, const PClass *exit_flash = NULL);
bool P_UndoMonsterMorph (AMorphedMonster *beast, bool force = false);

View File

@ -1741,10 +1741,7 @@ IMPLEMENT_CLASS(AScoreItem)
//
// AScoreItem :: TryPickup
//
// This function does nothing much. Theoretically, the player could have a
// score property which would be incremented by the score items' own score
// property (probably using the Amount property for that), but that is not
// needed for the moment.
// Adds the value (Amount) of the item to the toucher's Score property.
//
//===========================================================================

View File

@ -322,6 +322,7 @@ enum
WIF_NO_AUTO_SWITCH = 0x00001000, // never switch to this weapon when it's picked up
WIF_STAFF2_KICKBACK = 0x00002000, // the powered-up Heretic staff has special kickback
WIF_NOAUTOAIM = 0x00004000, // this weapon never uses autoaim (useful for ballistic projectiles)
WIF_MELEEWEAPON = 0x00008000, // melee weapon. Used by bots and monster AI.
WIF_CHEATNOTWEAPON = 0x08000000, // Give cheat considers this not a weapon (used by Sigil)
@ -329,7 +330,6 @@ enum
WIF_BOT_REACTION_SKILL_THING = 1<<31, // I don't understand this
WIF_BOT_EXPLOSIVE = 1<<30, // weapon fires an explosive
WIF_BOT_MELEE = 1<<29, // melee weapon
WIF_BOT_BFG = 1<<28, // this is a BFG
};
@ -477,7 +477,7 @@ public:
// A score item is picked up without being added to the inventory.
// Contrarily to FakeInventory, it does nothing.
// It differs from FakeInventory by doing nothing more than increasing the player's score.
class AScoreItem : public AInventory
{
DECLARE_CLASS (AScoreItem, AInventory)

View File

@ -111,6 +111,8 @@ class ARandomSpawner : public AActor
newmobj->args[2] = args[2];
newmobj->args[3] = args[3];
newmobj->args[4] = args[4];
newmobj->special1 = special1;
newmobj->special2 = special2;
newmobj->SpawnFlags = SpawnFlags;
newmobj->HandleSpawnFlags();
newmobj->tid = tid;

View File

@ -74,14 +74,14 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag
ffloor->bottom.plane = &sec2->floorplane;
ffloor->bottom.texture = &sec2->planes[sector_t::floor].Texture;
ffloor->bottom.texheight = &sec2->planes[sector_t::floor].TexZ;
ffloor->bottom.isceiling = false;
ffloor->bottom.isceiling = sector_t::floor;
}
else
{
ffloor->bottom.plane = &sec2->ceilingplane;
ffloor->bottom.texture = &sec2->planes[sector_t::ceiling].Texture;
ffloor->bottom.texheight = &sec2->planes[sector_t::ceiling].TexZ;
ffloor->bottom.isceiling = true;
ffloor->bottom.isceiling = sector_t::ceiling;
}
if (!(flags&FF_FIX))
@ -90,7 +90,7 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag
ffloor->top.texture = &sec2->planes[sector_t::ceiling].Texture;
ffloor->top.texheight = &sec2->planes[sector_t::ceiling].TexZ;
ffloor->toplightlevel = &sec2->lightlevel;
ffloor->top.isceiling = true;
ffloor->top.isceiling = sector_t::ceiling;
}
else // FF_FIX is a special case to patch rendering holes
{
@ -98,7 +98,7 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag
ffloor->top.texture = &sec2->planes[sector_t::floor].Texture;
ffloor->top.texheight = &sec2->planes[sector_t::floor].TexZ;
ffloor->toplightlevel = &sec->lightlevel;
ffloor->top.isceiling = false;
ffloor->top.isceiling = sector_t::floor;
ffloor->top.model = sec;
}
@ -117,12 +117,14 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag
// fortunately this plane won't be rendered - otherwise this wouldn't work...
ffloor->bottom.plane=&sec->floorplane;
ffloor->bottom.model=sec;
ffloor->bottom.isceiling = sector_t::floor;
}
}
ffloor->flags = flags;
ffloor->master = master;
ffloor->alpha = transluc;
ffloor->top.vindex = ffloor->bottom.vindex = -1;
// The engine cannot handle sloped translucent floors. Sorry
if (ffloor->top.plane->a || ffloor->top.plane->b || ffloor->bottom.plane->a || ffloor->bottom.plane->b)

View File

@ -73,7 +73,8 @@ struct F3DFloor
const FTextureID * texture;
const fixed_t * texheight;
sector_t * model;
bool isceiling;
int isceiling;
int vindex;
};
planeref bottom;

View File

@ -2684,6 +2684,7 @@ int DLevelScript::CheckActorProperty (int tid, int property, int value)
case APROP_Gravity:
case APROP_SpawnHealth:
case APROP_JumpZ:
case APROP_Score:
return (GetActorProperty(tid, property) == value);
// Boolean values need to compare to a binary version of value

View File

@ -381,7 +381,7 @@ static void LoadSectors (sectortype *bsec)
sec->SetXOffset(sector_t::floor, (bsec->floorxpanning << FRACBITS) + (32 << FRACBITS));
sec->SetYOffset(sector_t::floor, bsec->floorypanning << FRACBITS);
sec->SetPlaneLight(sector_t::floor, SHADE2LIGHT (bsec->floorshade));
sec->ChangeFlags(sector_t::floor, 0, SECF_ABSLIGHTING);
sec->ChangeFlags(sector_t::floor, 0, PLANEF_ABSLIGHTING);
sec->SetPlaneTexZ(sector_t::ceiling, -(LittleLong(bsec->ceilingz) << 8));
sec->ceilingplane.d = sec->GetPlaneTexZ(sector_t::ceiling);
@ -399,7 +399,7 @@ static void LoadSectors (sectortype *bsec)
sec->SetXOffset(sector_t::ceiling, (bsec->ceilingxpanning << FRACBITS) + (32 << FRACBITS));
sec->SetYOffset(sector_t::ceiling, bsec->ceilingypanning << FRACBITS);
sec->SetPlaneLight(sector_t::ceiling, SHADE2LIGHT (bsec->ceilingshade));
sec->ChangeFlags(sector_t::ceiling, 0, SECF_ABSLIGHTING);
sec->ChangeFlags(sector_t::ceiling, 0, PLANEF_ABSLIGHTING);
sec->lightlevel = (sec->GetPlaneLight(sector_t::floor) + sec->GetPlaneLight(sector_t::ceiling)) / 2;

View File

@ -232,7 +232,7 @@ bool EV_DoCeiling (DCeiling::ECeiling type, line_t *line,
sec = &sectors[secnum];
manual_ceiling:
// if ceiling already moving, don't start a second function on it
if (sec->ceilingdata)
if (sec->PlaneMoving(sector_t::ceiling))
{
if (!manual)
continue;

View File

@ -394,7 +394,7 @@ bool EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing,
secnum = int(sec-sectors);
// if door already has a thinker, use it
if (sec->ceilingdata)
if (sec->PlaneMoving(sector_t::ceiling))
{
if (sec->ceilingdata->IsKindOf (RUNTIME_CLASS(DDoor)))
{
@ -447,7 +447,7 @@ bool EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing,
{
sec = &sectors[secnum];
// if the ceiling already moving, don't start the door action
if (sec->ceilingdata)
if (sec->PlaneMoving(sector_t::ceiling))
continue;
if (new DDoor (sec, type, speed, delay, lightTag))

View File

@ -62,8 +62,10 @@ static FRandom pr_look2 ("LookyLooky");
static FRandom pr_look3 ("IGotHooky");
static FRandom pr_slook ("SlooK");
static FRandom pr_dropoff ("Dropoff");
static FRandom pr_defect ("Defect");
static FRandom pr_skiptarget("SkipTarget");
static FRandom pr_enemystrafe("EnemyStrafe");
// movement interpolation is fine for objects that are moved by their own
// velocity. But for monsters it is problematic.
@ -219,20 +221,20 @@ void P_NoiseAlert (AActor *target, AActor *emmiter, bool splash)
bool AActor::CheckMeleeRange ()
{
AActor *pl;
AActor *pl = target;
fixed_t dist;
if (!target)
if (!pl)
return false;
pl = target;
dist = P_AproxDistance (pl->x - x, pl->y - y);
if (dist >= meleerange + pl->radius)
return false;
// [RH] If moving toward goal, then we've reached it.
if (target == goal)
if (pl == goal)
return true;
// [RH] Don't melee things too far above or below actor.
@ -243,6 +245,10 @@ bool AActor::CheckMeleeRange ()
if (pl->z + pl->height < z)
return false;
}
// killough 7/18/98: friendly monsters don't attack other friends
if (IsFriend(pl))
return false;
if (!P_CheckSight (this, pl, 0))
return false;
@ -279,6 +285,12 @@ bool P_CheckMeleeRange2 (AActor *actor)
{ // Attacker is higher
return false;
}
else if (actor->IsFriend(mo))
{
// killough 7/18/98: friendly monsters don't attack other friends
return false;
}
if (!P_CheckSight(actor, mo))
{
return false;
@ -303,12 +315,34 @@ bool P_CheckMissileRange (AActor *actor)
{
// the target just hit the enemy, so fight back!
actor->flags &= ~MF_JUSTHIT;
return true;
// killough 7/18/98: no friendly fire at corpses
// killough 11/98: prevent too much infighting among friends
// Cleaned up and made readable
if (!(actor->flags & MF_FRIENDLY)) return true;
if (actor->target->health <= 0) return false;
if (!actor->IsFriend(actor->target)) return true;
if (actor->target->player != NULL)
{
return (pr_defect() >128);
}
else
{
return !(actor->target->flags & MF_JUSTHIT) && pr_defect() >128;
}
}
if (actor->reactiontime)
return false; // do not attack yet
// killough 7/18/98: friendly monsters don't attack other friendly
// monsters or players (except when attacked, and then only once)
if (actor->IsFriend(actor->target))
return false;
if (actor->flags & MF_FRIENDLY && P_HitFriend(actor))
return false;
// OPTIMIZE: get this from a global checksight
// [RH] What?
dist = P_AproxDistance (actor->x-actor->target->x,
@ -357,7 +391,7 @@ bool P_HitFriend(AActor * self)
if (self->flags&MF_FRIENDLY && self->target != NULL)
{
angle_t angle = R_PointToAngle2 (self->x, self->y, self->target->x, self->target->y);
fixed_t dist = P_AproxDistance (self->x-self->target->x, self->y-self->target->y);
fixed_t dist = P_AproxDistance (self->x - self->target->x, self->y - self->target->y);
P_AimLineAttack (self, angle, dist, &linetarget, 0, true);
if (linetarget != NULL && linetarget != self->target)
{
@ -739,6 +773,8 @@ void P_NewChaseDir(AActor * actor)
fixed_t deltax;
fixed_t deltay;
actor->strafecount = 0;
if ((actor->flags5&MF5_CHASEGOAL || actor->goal == actor->target) && actor->goal!=NULL)
{
deltax = actor->goal->x - actor->x;
@ -831,7 +867,56 @@ void P_NewChaseDir(AActor * actor)
return;
}
}
#if 0
// Move away from friends when too close, except
// in certain situations (e.g. a crowded lift)
// MBF code for friends. Cannot be done in ZDoom but left here as a reminder for later implementation.
if (actor->flags & target->flags & MF_FRIEND &&
distfriend << FRACBITS > dist &&
!P_IsOnLift(target) && !P_IsUnderDamage(actor))
deltax = -deltax, deltay = -deltay;
else
#endif
// MBF's monster_backing option. Made an actor flag instead. Also cleaned the code up to make it readable.
// Todo: implement the movement logic
AActor *target = actor->target;
if (target->health > 0 && !actor->IsFriend(target))
{ // Live enemy target
if (actor->flags3 & MF3_AVOIDMELEE)
{
bool ismeleeattacker = false;
fixed_t dist = P_AproxDistance(actor->x-target->x, actor->y-target->y);
if (target->player == NULL)
{
ismeleeattacker = (target->MissileState == NULL && dist < (target->meleerange + target->radius)*2);
}
else if (target->player->ReadyWeapon != NULL)
{
// melee range of player weapon is a parameter of the action function and cannot be checked here.
// Add a new weapon property?
ismeleeattacker = (target->player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON && dist < MELEERANGE*3);
}
if (ismeleeattacker)
{
actor->strafecount = pr_enemystrafe() & 15;
deltax = -deltax, deltay = -deltay;
}
}
}
P_DoNewChaseDir(actor, deltax, deltay);
// If strafing, set movecount to strafecount so that old Doom
// logic still works the same, except in the strafing part
if (actor->strafecount)
actor->movecount = actor->strafecount;
}
@ -996,6 +1081,58 @@ void P_RandomChaseDir (AActor *actor)
actor->movedir = DI_NODIR; // cannot move
}
//---------------------------------------------------------------------------
//
// P_IsVisible
//
// killough 9/9/98: whether a target is visible to a monster
// Extended to handle all A_LookEx related checking, too.
//
//---------------------------------------------------------------------------
bool P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams *params)
{
fixed_t maxdist;
fixed_t mindist;
angle_t fov;
if (params != NULL)
{
maxdist = params->maxdist;
mindist = params->mindist;
fov = params->fov;
}
else
{
mindist = maxdist = 0;
fov = allaround? 0 : ANGLE_180;
}
fixed_t dist = P_AproxDistance (other->x - lookee->x, other->y - lookee->y);
if (maxdist && dist > maxdist)
return false; // [KS] too far
if (mindist && dist < mindist)
return false; // [KS] too close
if (fov && fov < ANGLE_MAX)
{
angle_t an = R_PointToAngle2 (lookee->x, lookee->y, other->x, other->y) - lookee->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)
return false; // outside of fov
}
}
// P_CheckSight is by far the most expensive operation in here so let's do it last.
return P_CheckSight(lookee, other, 2);
}
//---------------------------------------------------------------------------
//
// FUNC P_LookForMonsters
@ -1061,8 +1198,9 @@ bool P_LookForMonsters (AActor *actor)
//
//============================================================================
AActor *LookForTIDinBlock (AActor *lookee, int index)
AActor *LookForTIDInBlock (AActor *lookee, int index, void *extparams)
{
FLookExParams *params = (FLookExParams *)extparams;
FBlockNode *block;
AActor *link;
AActor *other;
@ -1104,25 +1242,8 @@ AActor *LookForTIDinBlock (AActor *lookee, int index)
if (!(lookee->flags3 & MF3_NOSIGHTCHECK))
{
if (!P_CheckSight (lookee, other, 2))
if (!P_IsVisible(lookee, other, true, params))
continue; // out of sight
/*
if (!allaround)
{
angle_t an = R_PointToAngle2 (actor->x, actor->y,
other->x, other->y)
- actor->angle;
if (an > ANG90 && an < ANG270)
{
fixed_t dist = P_AproxDistance (other->x - actor->x,
other->y - actor->y);
// if real close, react anyway
if (dist > MELEERANGE)
continue; // behind back
}
}
*/
}
return other;
@ -1138,12 +1259,13 @@ AActor *LookForTIDinBlock (AActor *lookee, int index)
//
//============================================================================
bool P_LookForTID (AActor *actor, INTBOOL allaround)
bool P_LookForTID (AActor *actor, INTBOOL allaround, FLookExParams *params)
{
AActor *other;
bool reachedend = false;
bool chasegoal = params? (!(params->flags & LOF_DONTCHASEGOAL)) : true;
other = P_BlockmapSearch (actor, 0, LookForTIDinBlock);
other = P_BlockmapSearch (actor, 0, LookForTIDInBlock, params);
if (other != NULL)
{
@ -1198,24 +1320,8 @@ bool P_LookForTID (AActor *actor, INTBOOL allaround)
if (!(actor->flags3 & MF3_NOSIGHTCHECK))
{
if (!P_CheckSight (actor, other, 2))
if (!P_IsVisible (actor, other, !!allaround, params))
continue; // out of sight
if (!allaround)
{
angle_t an = R_PointToAngle2 (actor->x, actor->y,
other->x, other->y)
- actor->angle;
if (an > ANG90 && an < ANG270)
{
fixed_t dist = P_AproxDistance (other->x - actor->x,
other->y - actor->y);
// if real close, react anyway
if (dist > MELEERANGE)
continue; // behind back
}
}
}
// [RH] Need to be sure the reactiontime is 0 if the monster is
@ -1231,7 +1337,7 @@ bool P_LookForTID (AActor *actor, INTBOOL allaround)
if (actor->target == NULL)
{
// [RH] use goal as target
if (actor->goal != NULL)
if (actor->goal != NULL && chasegoal)
{
actor->target = actor->goal;
return true;
@ -1256,18 +1362,19 @@ bool P_LookForTID (AActor *actor, INTBOOL allaround)
//============================================================================
//
// LookForTIDinBlock
// LookForEnemiesinBlock
//
// Finds a non-friendly monster in a mapblock. It can also use targets of
// friendlies in this mapblock to find non-friendlies in other mapblocks.
//
//============================================================================
AActor *LookForEnemiesInBlock (AActor *lookee, int index)
AActor *LookForEnemiesInBlock (AActor *lookee, int index, void *extparam)
{
FBlockNode *block;
AActor *link;
AActor *other;
FLookExParams *params = (FLookExParams *)extparam;
for (block = blocklinks[index]; block != NULL; block = block->NextActor)
{
@ -1330,25 +1437,11 @@ AActor *LookForEnemiesInBlock (AActor *lookee, int index)
}
}
if (other == NULL || !P_CheckSight (lookee, other, 2))
// [KS] Hey, shouldn't there be a check for MF3_NOSIGHTCHECK here?
if (other == NULL || !P_IsVisible (lookee, other, true, params))
continue; // out of sight
/*
if (!allaround)
{
angle_t an = R_PointToAngle2 (actor->x, actor->y,
other->x, other->y)
- actor->angle;
if (an > ANG90 && an < ANG270)
{
fixed_t dist = P_AproxDistance (other->x - actor->x,
other->y - actor->y);
// if real close, react anyway
if (dist > MELEERANGE)
continue; // behind back
}
}
*/
return other;
}
@ -1363,11 +1456,11 @@ AActor *LookForEnemiesInBlock (AActor *lookee, int index)
//
//============================================================================
bool P_LookForEnemies (AActor *actor, INTBOOL allaround)
bool P_LookForEnemies (AActor *actor, INTBOOL allaround, FLookExParams *params)
{
AActor *other;
other = P_BlockmapSearch (actor, 10, LookForEnemiesInBlock);
other = P_BlockmapSearch (actor, 10, LookForEnemiesInBlock, params);
if (other != NULL)
{
@ -1415,18 +1508,17 @@ bool P_LookForEnemies (AActor *actor, INTBOOL allaround)
================
*/
bool P_LookForPlayers (AActor *actor, INTBOOL allaround)
bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params)
{
int c;
int stop;
int pnum;
player_t* player;
angle_t an;
fixed_t dist;
bool chasegoal = params? (!(params->flags & LOF_DONTCHASEGOAL)) : true;
if (actor->TIDtoHate != 0)
{
if (P_LookForTID (actor, allaround))
if (P_LookForTID (actor, allaround, params))
{
return true;
}
@ -1437,10 +1529,43 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround)
}
else if (actor->flags & MF_FRIENDLY)
{
if (!deathmatch) // [SP] If you don't see any enemies in deathmatch, look for players.
return P_LookForEnemies (actor, allaround);
else if ( P_LookForEnemies (actor, allaround) )
return true;
bool result = P_LookForEnemies (actor, allaround, params);
#ifdef MBF_FRIENDS
if (!result && (actor->flags & MF_FRIEND_MBF))
{ // killough 9/9/98: friendly monsters go about players differently
// Go back to a player, no matter whether it's visible or not
for (int anyone=0; anyone<=1; anyone++)
{
for (int c=0; c<MAXPLAYERS; c++)
{
if (playeringame[c] && players[c].playerstate==PST_LIVE &&
actor->IsFriend(players[c].mo) &&
(anyone || P_IsVisible(actor, players[c].mo, allaround)))
{
actor->target = players[c].mo;
// killough 12/98:
// get out of refiring loop, to avoid hitting player accidentally
if (actor->MissileState != NULL)
{
actor->SetStateNF(actor->SeeState);
actor->flags &= ~MF_JUSTHIT;
}
return true;
}
}
}
}
#endif
// [SP] If you don't see any enemies in deathmatch, look for players (but only when friend to a specific player.)
if (actor->FriendPlayer == 0) return result;
if (result || !deathmatch) return true;
} // [SP] if false, and in deathmatch, intentional fall-through
if (!(gameinfo.gametype & (GAME_DoomStrifeChex)) &&
@ -1478,7 +1603,8 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround)
if (actor->target == NULL)
{
// [RH] use goal as target
if (actor->goal != NULL)
// [KS] ...unless we're ignoring goals and we don't already have one
if (actor->goal != NULL && chasegoal)
{
actor->target = actor->goal;
return true;
@ -1512,7 +1638,7 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround)
if (player->health <= 0)
continue; // dead
if (!P_CheckSight (actor, player->mo, 2))
if (!P_IsVisible (actor, player->mo, allaround, params))
continue; // out of sight
// [SP] Deathmatch fixes - if we have MF_FRIENDLY we're definitely in deathmatch
@ -1525,23 +1651,6 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround)
continue; // This is my master.
}
if (!allaround)
{
an = R_PointToAngle2 (actor->x,
actor->y,
player->mo->x,
player->mo->y)
- actor->angle;
if (an > ANG90 && an < ANG270)
{
dist = P_AproxDistance (player->mo->x - actor->x,
player->mo->y - actor->y);
// if real close, react anyway
if (dist > MELEERANGE)
continue; // behind back
}
}
if ((player->mo->flags & MF_SHADOW && !(i_compatflags & COMPATF_INVISIBILITY)) ||
player->mo->flags3 & MF3_GHOST)
{
@ -1630,7 +1739,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look)
{
// If we find a valid target here, the wandering logic should *not*
// be activated! It would cause the seestate to be set twice.
if (P_LookForPlayers (self, self->flags4 & MF4_LOOKALLAROUND))
if (P_LookForPlayers (self, self->flags4 & MF4_LOOKALLAROUND, NULL))
goto seeyou;
// Let the self wander around aimlessly looking for a fight
@ -1657,7 +1766,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look)
}
}
if (!P_LookForPlayers (self, self->flags4 & MF4_LOOKALLAROUND))
if (!P_LookForPlayers (self, self->flags4 & MF4_LOOKALLAROUND, NULL))
return;
// go into chase state
@ -1687,6 +1796,193 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look)
}
//==========================================================================
//
// A_LookEx (int flags, fixed minseedist, fixed maxseedist, fixed maxheardist, fixed fov, state wakestate)
// [KS] Borrowed the A_Look code to make a parameterized version.
//
//==========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx)
{
ACTION_PARAM_START(6);
ACTION_PARAM_INT(flags, 0);
ACTION_PARAM_FIXED(minseedist, 1);
ACTION_PARAM_FIXED(maxseedist, 2);
ACTION_PARAM_FIXED(maxheardist, 3);
ACTION_PARAM_ANGLE(fov, 4);
ACTION_PARAM_STATE(seestate, 5);
AActor *targ = NULL; // Shuts up gcc
fixed_t dist;
FLookExParams params = {fov, minseedist, maxseedist, maxheardist, flags, seestate };
if (self->flags5 & MF5_INCONVERSATION)
return;
// [RH] Set goal now if appropriate
if (self->special == Thing_SetGoal && self->args[0] == 0)
{
NActorIterator iterator (NAME_PatrolPoint, self->args[1]);
self->special = 0;
self->goal = iterator.Next ();
self->reactiontime = self->args[2] * TICRATE + level.maptime;
if (self->args[3] == 0) self->flags5 &=~ MF5_CHASEGOAL;
else self->flags5 |= MF5_CHASEGOAL;
}
self->threshold = 0; // any shot will wake up
if (self->TIDtoHate != 0)
{
targ = self->target;
}
else
{
if (!(flags & LOF_NOSOUNDCHECK))
{
targ = (self->flags & MF_NOSECTOR)? self->Sector->SoundTarget : self->LastHeard;
if (targ != NULL)
{
// [RH] If the soundtarget is dead, don't chase it
if (targ->health <= 0)
{
targ = NULL;
}
else
{
dist = P_AproxDistance (targ->x - self->x,
targ->y - self->y);
// [KS] If the target is too far away, don't respond to the sound.
if (maxheardist && dist > maxheardist)
{
targ = NULL;
self->LastHeard = NULL;
}
}
}
}
if (targ && targ->player && (targ->player->cheats & CF_NOTARGET))
{
return;
}
}
// [RH] Andy Baker's stealth monsters
if (self->flags & MF_STEALTH)
{
self->visdir = -1;
}
if (targ && (targ->flags & MF_SHOOTABLE))
{
if (self->IsFriend (targ)) // be a little more precise!
{
if (!(self->flags4 & MF4_STANDSTILL))
{
if (!(flags & LOF_NOSIGHTCHECK))
{
// 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_LookForPlayers(self, true, &params))
goto seeyou;
}
// Let the self wander around aimlessly looking for a fight
if (!(self->flags & MF_INCHASE))
{
if (seestate)
{
self->SetState (seestate);
}
else
{
if (self->SeeState != NULL)
{
self->SetState (self->SeeState);
}
else
{
CALL_ACTION(A_Wander, self);
}
}
}
}
}
else
{
self->target = targ; //We already have a target?
// [KS] The target can become ourselves in rare circumstances (like
// if we committed suicide), so if that's the case, just ignore it.
if (self->target == self) self->target = NULL;
if (self->target != NULL)
{
if (self->flags & MF_AMBUSH)
{
dist = P_AproxDistance (self->target->x - self->x,
self->target->y - self->y);
if (P_CheckSight (self, self->target, 2) &&
(!minseedist || dist > minseedist) &&
(!maxseedist || dist < maxseedist))
{
goto seeyou;
}
}
else
goto seeyou;
}
}
}
if (!(flags & LOF_NOSIGHTCHECK))
{
if (!P_LookForPlayers(self, true, &params))
return;
}
else
{
return;
}
// go into chase state
seeyou:
// [RH] Don't start chasing after a goal if it isn't time yet.
if (self->target == self->goal)
{
if (self->reactiontime > level.maptime)
self->target = NULL;
}
else if (self->SeeSound && !(flags & LOF_NOSEESOUND))
{
if (flags & LOF_FULLVOLSEESOUND)
{ // full volume
S_Sound (self, CHAN_VOICE, self->SeeSound, 1, ATTN_NONE);
}
else
{
S_Sound (self, CHAN_VOICE, self->SeeSound, 1, ATTN_NORM);
}
}
if (self->target && !(self->flags & MF_INCHASE))
{
if (seestate)
{
self->SetState (seestate);
}
else
{
self->SetState (self->SeeState);
}
}
}
// [KS] *** End additions by me ***
//==========================================================================
//
// A_Wander
@ -1770,7 +2066,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look2)
}
else
{
if (!P_LookForPlayers (self, self->flags4 & MF4_LOOKALLAROUND))
if (!P_LookForPlayers (self, self->flags4 & MF4_LOOKALLAROUND, NULL))
goto nosee;
self->SetState (self->SeeState);
self->flags4 |= MF4_INCOMBAT;
@ -1856,7 +2152,11 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
}
// turn towards movement direction if not there yet
if (actor->movedir < 8)
if (actor->strafecount)
{
A_FaceTarget(actor);
}
else if (actor->movedir < 8)
{
actor->angle &= (angle_t)(7<<29);
delta = actor->angle - (actor->movedir << 29);
@ -1916,7 +2216,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
// hurt our old one temporarily.
actor->threshold = 0;
}
if (P_LookForPlayers (actor, true) && actor->target != actor->goal)
if (P_LookForPlayers (actor, true, NULL) && actor->target != actor->goal)
{ // got a new target
actor->flags &= ~MF_INCHASE;
return;
@ -2088,7 +2388,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
lookForBetter = true;
}
AActor * oldtarget = actor->target;
gotNew = P_LookForPlayers (actor, true);
gotNew = P_LookForPlayers (actor, true, NULL);
if (lookForBetter)
{
actor->flags3 |= MF3_NOSIGHTCHECK;
@ -2104,6 +2404,9 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
// chase towards player
//
if (actor->strafecount)
actor->strafecount--;
// class bosses don't do this when strafing
if ((!fastchase || !actor->FastChaseStrafeCount) && !dontmove)
{

View File

@ -25,6 +25,25 @@ enum dirtype_t
extern fixed_t xspeed[8], yspeed[8];
enum LO_Flags
{
LOF_NOSIGHTCHECK = 1,
LOF_NOSOUNDCHECK = 2,
LOF_DONTCHASEGOAL = 4,
LOF_NOSEESOUND = 8,
LOF_FULLVOLSEESOUND = 16,
};
struct FLookExParams
{
angle_t fov;
fixed_t mindist;
fixed_t maxdist;
fixed_t maxheardist;
int flags;
FState *seestate;
};
void P_RecursiveSound (sector_t *sec, AActor *soundtarget, bool splash, int soundblocks);
bool P_HitFriend (AActor *self);
void P_NoiseAlert (AActor *target, AActor *emmiter, bool splash=false);
@ -32,9 +51,9 @@ bool P_CheckMeleeRange2 (AActor *actor);
bool P_Move (AActor *actor);
bool P_TryWalk (AActor *actor);
void P_NewChaseDir (AActor *actor);
bool P_LookForPlayers (AActor *actor, INTBOOL allaround);
AInventory *P_DropItem (AActor *source, const PClass *type, int special, int chance);
void P_TossItem (AActor *item);
bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params);
DECLARE_ACTION(A_Look)
DECLARE_ACTION(A_Wander)

View File

@ -1,904 +0,0 @@
#include <stdlib.h>
#include "templates.h"
#include "m_random.h"
#include "i_system.h"
#include "doomdef.h"
#include "p_local.h"
#include "p_lnspec.h"
#include "s_sound.h"
#include "g_game.h"
#include "doomstat.h"
#include "r_state.h"
#include "c_cvars.h"
#include "p_enemy.h"
#include "a_sharedglobal.h"
#include "a_action.h"
#include "thingdef/thingdef.h"
#include "g_level.h"
#include "gi.h"
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: 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->SpawnHealth())
{
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;
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)
{
if (actor->goal && actor->target == actor->goal)
actor->reactiontime = 0;
actor->target = other;
actor->LastLookActor = other;
return true;
}
// The actor's TID could change because of death or because of
// Thing_ChangeTID. If it's not what we expect, then don't use
// it as a base for the iterator.
if (actor->LastLookActor != NULL &&
actor->LastLookActor->tid != actor->TIDtoHate)
{
actor->LastLookActor = NULL;
}
FActorIterator iterator (actor->TIDtoHate, actor->LastLookActor);
int c = (pr_look3() & 31) + 7; // Look for between 7 and 38 hatees at a time
while ((other = iterator.Next()) != actor->LastLookActor)
{
if (other == NULL)
{
if (reachedend)
{
// we have cycled through the entire list at least once
// so let's abort because even if we continue nothing can
// be found.
break;
}
reachedend = true;
continue;
}
if (!(other->flags & MF_SHOOTABLE))
continue; // not shootable (observer or dead)
if (other == actor)
continue; // don't hate self
if (other->health <= 0)
continue; // dead
if (other->flags2 & MF2_DORMANT)
continue; // don't target dormant things
if (--c == 0)
break;
if (!(actor->flags3 & MF3_NOSIGHTCHECK))
{
if (!P_CheckSight (actor, other, 2))
continue; // out of sight
dist = P_AproxDistance (other->x - actor->x,
other->y - actor->y);
if (maxdist && dist > maxdist)
continue; // [KS] too far
if (mindist && dist < mindist)
continue; // [KS] too close
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)
continue; // outside of fov
}
}
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)
continue; // behind back
}
}
}
}
// [RH] Need to be sure the reactiontime is 0 if the monster is
// leaving its goal to go after something else.
if (actor->goal && actor->target == actor->goal)
actor->reactiontime = 0;
actor->target = other;
actor->LastLookActor = other;
return true;
}
actor->LastLookActor = other;
if (actor->target == NULL)
{
// [RH] use goal as target
if (actor->goal != NULL && chasegoal)
{
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_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;
int stop;
int pnum;
player_t* player;
angle_t an;
fixed_t dist;
if (actor->TIDtoHate != 0)
{
if (P_NewLookTID (actor, fov, mindist, maxdist, chasegoal))
{
return true;
}
if (!(actor->flags3 & MF3_HUNTPLAYERS))
{
return false;
}
}
else if (actor->flags & MF_FRIENDLY)
{
if (!deathmatch) // [SP] If you don't see any enemies in deathmatch, look for players.
return P_NewLookEnemies (actor, fov, mindist, maxdist, chasegoal);
else if ( P_NewLookEnemies (actor, fov, mindist, maxdist, chasegoal) )
return true;
} // [SP] if false, and in deathmatch, intentional fall-through
if (!(gameinfo.gametype & (GAME_DoomStrifeChex)) &&
!multiplayer &&
players[0].health <= 0)
{ // Single player game and player is dead; look for monsters
return P_LookForMonsters (actor);
}
c = 0;
if (actor->TIDtoHate != 0)
{
pnum = pr_look2() & (MAXPLAYERS-1);
}
else
{
pnum = actor->LastLookPlayerNumber;
}
stop = (pnum - 1) & (MAXPLAYERS-1);
for (;;)
{
pnum = (pnum + 1) & (MAXPLAYERS-1);
if (!playeringame[pnum])
continue;
if (actor->TIDtoHate == 0)
{
actor->LastLookPlayerNumber = pnum;
}
if (++c == MAXPLAYERS-1 || pnum == stop)
{
// done looking
if (actor->target == NULL)
{
// [RH] use goal as target
// [KS] ...unless we're ignoring goals and we don't already have one
if (actor->goal != NULL && chasegoal)
{
actor->target = actor->goal;
return true;
}
// Use last known enemy if no players 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 actor->target == actor->goal && actor->goal != NULL;
}
player = &players[pnum];
if (!(player->mo->flags & MF_SHOOTABLE))
continue; // not shootable (observer or dead)
if (player->cheats & CF_NOTARGET)
continue; // no target
if (player->health <= 0)
continue; // dead
if (!P_CheckSight (actor, player->mo, 2))
continue; // out of sight
dist = P_AproxDistance (player->mo->x - actor->x,
player->mo->y - actor->y);
if (maxdist && dist > maxdist)
continue; // [KS] too far
if (mindist && dist < mindist)
continue; // [KS] too close
// [SP] Deathmatch fixes - if we have MF_FRIENDLY we're definitely in deathmatch
// We're going to ignore our master, but go after his enemies.
if ( actor->flags & MF_FRIENDLY )
{
if ( actor->FriendPlayer == 0 )
continue; // I have no friends, I will ignore players.
if ( actor->FriendPlayer == player->mo->FriendPlayer )
continue; // This is my master.
}
if (fov)
{
an = R_PointToAngle2 (actor->x,
actor->y,
player->mo->x,
player->mo->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)
continue; // outside of fov
}
}
else
{
if(!((actor->flags4 & MF4_LOOKALLAROUND) || (fov >= ANGLE_MAX)))
{
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)) ||
player->mo->flags3 & MF3_GHOST)
{
if ((P_AproxDistance (player->mo->x - actor->x,
player->mo->y - actor->y) > 2*MELEERANGE)
&& P_AproxDistance (player->mo->velx, player->mo->vely)
< 5*FRACUNIT)
{ // Player is sneaking - can't detect
return false;
}
if (pr_lookforplayers() < 225)
{ // Player isn't sneaking, but still didn't detect
return false;
}
}
// [RH] Need to be sure the reactiontime is 0 if the monster is
// leaving its goal to go after a player.
if (actor->goal && actor->target == actor->goal)
actor->reactiontime = 0;
actor->target = player->mo;
return true;
}
}
//
// ACTION ROUTINES
//
//
// A_Look
// Stay in state until a player is sighted.
// [RH] Will also leave state to move to goal.
//
// A_LookEx (int flags, fixed minseedist, fixed maxseedist, fixed maxheardist, fixed fov, state wakestate)
// [KS] Borrowed the A_Look code to make a parameterized version.
//
enum LO_Flags
{
LOF_NOSIGHTCHECK = 1,
LOF_NOSOUNDCHECK = 2,
LOF_DONTCHASEGOAL = 4,
LOF_NOSEESOUND = 8,
LOF_FULLVOLSEESOUND = 16,
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx)
{
ACTION_PARAM_START(6);
ACTION_PARAM_INT(flags, 0);
ACTION_PARAM_FIXED(minseedist, 1);
ACTION_PARAM_FIXED(maxseedist, 2);
ACTION_PARAM_FIXED(maxheardist, 3);
ACTION_PARAM_ANGLE(fov, 4);
ACTION_PARAM_STATE(seestate, 5);
AActor *targ = NULL; // Shuts up gcc
fixed_t dist;
if (self->flags5 & MF5_INCONVERSATION)
return;
// [RH] Set goal now if appropriate
if (self->special == Thing_SetGoal && self->args[0] == 0)
{
NActorIterator iterator (NAME_PatrolPoint, self->args[1]);
self->special = 0;
self->goal = iterator.Next ();
self->reactiontime = self->args[2] * TICRATE + level.maptime;
if (self->args[3] == 0) self->flags5 &=~ MF5_CHASEGOAL;
else self->flags5 |= MF5_CHASEGOAL;
}
self->threshold = 0; // any shot will wake up
if (self->TIDtoHate != 0)
{
targ = self->target;
}
else
{
if (!(flags & LOF_NOSOUNDCHECK))
{
targ = self->LastHeard;
if (targ != NULL)
{
// [RH] If the soundtarget is dead, don't chase it
if (targ->health <= 0)
{
targ = NULL;
}
else
{
dist = P_AproxDistance (targ->x - self->x,
targ->y - self->y);
// [KS] If the target is too far away, don't respond to the sound.
if (maxheardist && dist > maxheardist)
{
targ = NULL;
self->LastHeard = NULL;
}
}
}
}
if (targ && targ->player && (targ->player->cheats & CF_NOTARGET))
{
return;
}
}
// [RH] Andy Baker's stealth monsters
if (self->flags & MF_STEALTH)
{
self->visdir = -1;
}
if (targ && (targ->flags & MF_SHOOTABLE))
{
if (self->IsFriend (targ)) // be a little more precise!
{
if (!(self->flags4 & MF4_STANDSTILL))
{
if (!(flags & LOF_NOSIGHTCHECK))
{
// 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(self, fov, minseedist, maxseedist, !(flags & LOF_DONTCHASEGOAL)))
goto seeyou;
}
// Let the self wander around aimlessly looking for a fight
if (!(self->flags & MF_INCHASE))
{
if (seestate)
{
self->SetState (seestate);
}
else
{
if (self->SeeState != NULL)
{
self->SetState (self->SeeState);
}
else
{
CALL_ACTION(A_Wander, self);
}
}
}
}
}
else
{
self->target = targ; //We already have a target?
// [KS] The target can become ourselves in rare circumstances (like
// if we committed suicide), so if that's the case, just ignore it.
if (self->target == self) self->target = NULL;
if (self->target != NULL)
{
if (self->flags & MF_AMBUSH)
{
dist = P_AproxDistance (self->target->x - self->x,
self->target->y - self->y);
if (P_CheckSight (self, self->target, 2) &&
(!minseedist || dist > minseedist) &&
(!maxseedist || dist < maxseedist))
{
goto seeyou;
}
}
else
goto seeyou;
}
}
}
if (!(flags & LOF_NOSIGHTCHECK))
{
if (!P_NewLookPlayers(self, fov, minseedist, maxseedist, !(flags & LOF_DONTCHASEGOAL)))
return;
}
else
{
return;
}
// go into chase state
seeyou:
// [RH] Don't start chasing after a goal if it isn't time yet.
if (self->target == self->goal)
{
if (self->reactiontime > level.maptime)
self->target = NULL;
}
else if (self->SeeSound && !(flags & LOF_NOSEESOUND))
{
if (flags & LOF_FULLVOLSEESOUND)
{ // full volume
S_Sound (self, CHAN_VOICE, self->SeeSound, 1, ATTN_NONE);
}
else
{
S_Sound (self, CHAN_VOICE, self->SeeSound, 1, ATTN_NORM);
}
}
if (self->target && !(self->flags & MF_INCHASE))
{
if (seestate)
{
self->SetState (seestate);
}
else
{
self->SetState (self->SeeState);
}
}
}
// [KS] *** End additions by me ***

View File

@ -377,7 +377,7 @@ bool EV_DoFloor (DFloor::EFloor floortype, line_t *line, int tag,
manual_floor:
// ALREADY MOVING? IF SO, KEEP GOING...
if (sec->floordata)
if (sec->PlaneMoving(sector_t::floor))
{
if (manual)
continue;
@ -748,7 +748,7 @@ manual_stair:
// ALREADY MOVING? IF SO, KEEP GOING...
//jff 2/26/98 add special lockout condition to wait for entire
//staircase to build before retriggering
if (sec->floordata || sec->stairlock)
if (sec->PlaneMoving(sector_t::floor) || sec->stairlock)
{
if (!manual)
continue;
@ -800,7 +800,7 @@ manual_stair:
// if sector's floor already moving, look for another
//jff 2/26/98 special lockout condition for retriggering
if (tsec->floordata || tsec->stairlock)
if (tsec->PlaneMoving(sector_t::floor) || tsec->stairlock)
{
prev = sec;
sec = tsec;
@ -833,7 +833,7 @@ manual_stair:
// if sector's floor already moving, look for another
//jff 2/26/98 special lockout condition for retriggering
if (tsec->floordata || tsec->stairlock)
if (tsec->PlaneMoving(sector_t::floor) || tsec->stairlock)
continue;
ok = true;
@ -917,7 +917,7 @@ bool EV_DoDonut (int tag, fixed_t pillarspeed, fixed_t slimespeed)
s1 = &sectors[secnum]; // s1 is pillar's sector
// ALREADY MOVING? IF SO, KEEP GOING...
if (s1->floordata)
if (s1->PlaneMoving(sector_t::floor))
continue;
rtn = true;
@ -925,7 +925,7 @@ bool EV_DoDonut (int tag, fixed_t pillarspeed, fixed_t slimespeed)
if (!s2) // note lowest numbered line around
continue; // pillar must be two-sided
if (s2->floordata)
if (s2->PlaneMoving(sector_t::floor))
continue;
for (i = 0; i < s2->linecount; i++)
@ -1007,7 +1007,7 @@ bool EV_DoElevator (line_t *line, DElevator::EElevator elevtype,
sec = &sectors[secnum];
// If either floor or ceiling is already activated, skip it
if (sec->floordata || sec->ceilingdata) //jff 2/22/98
if (sec->PlaneMoving(sector_t::floor) || sec->ceilingdata) //jff 2/22/98
continue;
// create and initialize new elevator thinker
@ -1225,7 +1225,8 @@ bool EV_StartWaggle (int tag, int height, int speed, int offset,
while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
{
sector = &sectors[sectorIndex];
if ((!ceiling && sector->floordata) || (ceiling && sector->ceilingdata))
if ((!ceiling && sector->PlaneMoving(sector_t::floor)) ||
(ceiling && sector->PlaneMoving(sector_t::ceiling)))
{ // Already busy with another thinker
continue;
}

View File

@ -882,6 +882,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
int painchance = 0;
FState * woundstate = NULL;
PainChanceList * pc = NULL;
bool justhit = false;
if (target == NULL || !((target->flags & MF_SHOOTABLE) || (target->flags6 & MF6_VULNERABLE)))
{ // Shouldn't happen
@ -893,12 +894,6 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
{
if (inflictor == NULL || !(inflictor->flags4 & MF4_SPECTRAL))
{
/*
if (target->MissileState != NULL)
{
target->SetState (target->MissileState);
}
*/
return;
}
}
@ -1285,7 +1280,7 @@ dopain:
{
if (pr_lightning() < 96)
{
target->flags |= MF_JUSTHIT; // fight back!
justhit = true;
FState * painstate = target->FindState(NAME_Pain, mod);
if (painstate != NULL) target->SetState (painstate);
}
@ -1300,7 +1295,7 @@ dopain:
}
else
{
target->flags |= MF_JUSTHIT; // fight back!
justhit = true;
FState * painstate = target->FindState(NAME_Pain, mod);
if (painstate != NULL) target->SetState (painstate);
if (mod == NAME_PoisonCloud)
@ -1345,6 +1340,11 @@ dopain:
}
}
}
// killough 11/98: Don't attack a friend, unless hit by that friend.
if (justhit && (target->target == source || !target->target || !target->IsFriend(target->target)))
target->flags |= MF_JUSTHIT; // fight back!
}
bool AActor::OkayToSwitchTarget (AActor *other)

View File

@ -300,7 +300,8 @@ bool P_AddSectorLinks(sector_t *control, int tag, INTBOOL ceiling, int movetype)
int param = movetype;
// can't be done if the control sector is moving.
if ((ceiling && control->ceilingdata) || (!ceiling && control->floordata)) return false;
if ((ceiling && control->PlaneMoving(sector_t::ceiling)) ||
(!ceiling && control->PlaneMoving(sector_t::floor))) return false;
// Make sure we have only valid combinations
movetype &= LINK_FLAGMASK;

View File

@ -2532,7 +2532,10 @@ FUNC(LS_SetPlayerProperty)
if (power != 4)
{
APowerup *item = static_cast<APowerup*>(it->GiveInventoryType (*powers[power]));
if (item != NULL && power == 0) item->BlendColor = INVERSECOLOR;
if (item != NULL && power == 0 && arg1 == 1)
{
item->BlendColor = MakeSpecialColormap(INVERSECOLORMAP);
}
}
else if (it->player - players == consoleplayer)
{
@ -2568,7 +2571,11 @@ FUNC(LS_SetPlayerProperty)
{ // Give power
if (power != 4)
{
players[i].mo->GiveInventoryType (*powers[power]);
APowerup *item = static_cast<APowerup*>(players[i].mo->GiveInventoryType (*powers[power]));
if (item != NULL && power == 0 && arg1 == 1)
{
item->BlendColor = MakeSpecialColormap(INVERSECOLORMAP);
}
}
else if (i == consoleplayer)
{

View File

@ -320,7 +320,7 @@ public:
#define PT_ADDLINES 1
#define PT_ADDTHINGS 2
AActor *P_BlockmapSearch (AActor *origin, int distance, AActor *(*func)(AActor *, int));
AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, int, void *), void *params = NULL);
AActor *P_RoughMonsterSearch (AActor *mo, int distance);
//

View File

@ -40,7 +40,7 @@
#include "r_state.h"
#include "templates.h"
static AActor *RoughBlockCheck (AActor *mo, int index);
static AActor *RoughBlockCheck (AActor *mo, int index, void *);
//==========================================================================
@ -1278,7 +1278,7 @@ AActor *P_RoughMonsterSearch (AActor *mo, int distance)
return P_BlockmapSearch (mo, distance, RoughBlockCheck);
}
AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, int))
AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, int, void *), void *params)
{
int blockX;
int blockY;
@ -1297,7 +1297,7 @@ AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, in
if (startX >= 0 && startX < bmapwidth && startY >= 0 && startY < bmapheight)
{
if ( (target = check (mo, startY*bmapwidth+startX)) )
if ( (target = check (mo, startY*bmapwidth+startX, params)) )
{ // found a target right away
return target;
}
@ -1334,7 +1334,7 @@ AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, in
// Trace the first block section (along the top)
for (; blockIndex <= firstStop; blockIndex++)
{
if ( (target = check (mo, blockIndex)) )
if ( (target = check (mo, blockIndex, params)) )
{
return target;
}
@ -1342,7 +1342,7 @@ AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, in
// Trace the second block section (right edge)
for (blockIndex--; blockIndex <= secondStop; blockIndex += bmapwidth)
{
if ( (target = check (mo, blockIndex)) )
if ( (target = check (mo, blockIndex, params)) )
{
return target;
}
@ -1350,7 +1350,7 @@ AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, in
// Trace the third block section (bottom edge)
for (blockIndex -= bmapwidth; blockIndex >= thirdStop; blockIndex--)
{
if ( (target = check (mo, blockIndex)) )
if ( (target = check (mo, blockIndex, params)) )
{
return target;
}
@ -1358,7 +1358,7 @@ AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, in
// Trace the final block section (left edge)
for (blockIndex++; blockIndex > finalStop; blockIndex -= bmapwidth)
{
if ( (target = check (mo, blockIndex)) )
if ( (target = check (mo, blockIndex, params)) )
{
return target;
}
@ -1373,7 +1373,7 @@ AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, in
//
//===========================================================================
static AActor *RoughBlockCheck (AActor *mo, int index)
static AActor *RoughBlockCheck (AActor *mo, int index, void *)
{
FBlockNode *link;

View File

@ -240,6 +240,7 @@ void AActor::Serialize (FArchive &arc)
<< movedir
<< visdir
<< movecount
<< strafecount
<< target
<< lastenemy
<< LastHeard
@ -3898,7 +3899,8 @@ APlayerPawn *P_SpawnPlayer (FMapThing *mthing, bool tempplayer)
p->MorphStyle = 0;
p->MorphExitFlash = NULL;
p->extralight = 0;
p->fixedcolormap = 0;
p->fixedcolormap = NOFIXEDCOLORMAP;
p->fixedlightlevel = -1;
p->viewheight = mobj->ViewHeight;
p->inconsistant = 0;
p->attacker = NULL;
@ -5475,10 +5477,7 @@ void PrintMiscActorInfo(AActor * query)
static const char * renderstyles[]= {"None", "Normal", "Fuzzy", "SoulTrans",
"OptFuzzy", "Stencil", "Translucent", "Add", "Shaded", "TranslucentStencil"};
/*
Printf("%s %x has the following flags:\n\tflags1: %x",
query->GetNameTag().GetChars(), query, query->flags);
*/
Printf("%s has the following flags:\n\tflags: %x", query->GetTag(), query->flags);
for (flagi = 0; flagi < 31; flagi++)
if (query->flags & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags));
Printf("\n\tflags2: %x", query->flags2);
@ -5496,25 +5495,20 @@ void PrintMiscActorInfo(AActor * query)
Printf("\n\tflags6: %x", query->flags6);
for (flagi = 0; flagi < 31; flagi++)
if (query->flags6 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags6));
/*
Printf("\nIts bounce style and factors are %s and f:%f, w:%f; its bounce flags are:\n\tflagsb: %x",
bouncestyles[bt], FIXED2FLOAT(query->bouncefactor),
Printf("\nIts bounce style and factors are %x and f:%f, w:%f; its bounce flags are:\n\tflagsb: %x",
query->BounceFlags, FIXED2FLOAT(query->bouncefactor),
FIXED2FLOAT(query->wallbouncefactor), query->BounceFlags);
for (flagi = 0; flagi < 31; flagi++)
if (query->BounceFlags & 1<<flagi) Printf(" %s", flagnamesb[flagi]);
*/
/*for (flagi = 0; flagi < 31; flagi++)
if (query->BounceFlags & 1<<flagi) Printf(" %s", flagnamesb[flagi]);*/
Printf("\nIts render style is %i:%s with alpha %f and the following render flags:\n\tflagsr: %x",
querystyle, (querystyle < STYLE_Count ? renderstyles[querystyle] : "Unknown"),
FIXED2FLOAT(query->alpha), query->renderflags);
/*
for (flagi = 0; flagi < 31; flagi++)
if (query->renderflags & 1<<flagi) Printf(" %s", flagnamesr[flagi]);
*/
/*for (flagi = 0; flagi < 31; flagi++)
if (query->renderflags & 1<<flagi) Printf(" %s", flagnamesr[flagi]);*/
Printf("\nIts thing special and arguments are %s(%i, %i, %i, %i, %i), and its specials are %i and %i.",
LineSpecialsInfo[query->special]->name, query->args[0], query->args[1],
query->args[2], query->args[3], query->args[4],
query->special1, query->special2);
(query->special ? LineSpecialsInfo[query->special]->name : "None"),
query->args[0], query->args[1], query->args[2], query->args[3],
query->args[4], query->special1, query->special2);
Printf("\nIts coordinates are x: %f, y: %f, z:%f, floor:%f, ceiling:%f.",
FIXED2FLOAT(query->x), FIXED2FLOAT(query->y), FIXED2FLOAT(query->z),
FIXED2FLOAT(query->floorz), FIXED2FLOAT(query->ceilingz));

View File

@ -205,7 +205,7 @@ bool EV_DoPillar (DPillar::EPillar type, int tag, fixed_t speed, fixed_t height,
{
sector_t *sec = &sectors[secnum];
if (sec->floordata || sec->ceilingdata)
if (sec->PlaneMoving(sector_t::floor) || sec->PlaneMoving(sector_t::ceiling))
continue;
fixed_t flor, ceil;

View File

@ -91,7 +91,10 @@ void DPlat::Tick ()
switch (m_Type)
{
case platRaiseAndStayLockout:
break;
// Instead of keeping the dead thinker like Heretic did let's
// better use a flag to avoid problems elsewhere. For example,
// keeping the thinker would make tagwait wait indefinitely.
m_Sector->planes[sector_t::floor].Flags |= PLANEF_BLOCKED;
case platRaiseAndStay:
case platDownByValue:
case platDownWaitUpStay:
@ -236,7 +239,7 @@ bool EV_DoPlat (int tag, line_t *line, DPlat::EPlatType type, int height,
sec = &sectors[secnum];
manual_plat:
if (sec->floordata)
if (sec->PlaneMoving(sector_t::floor))
{
if (!manual)
continue;

View File

@ -761,3 +761,12 @@ void sector_t::ClosestPoint(fixed_t fx, fixed_t fy, fixed_t &ox, fixed_t &oy) co
ox = fixed_t(bestx);
oy = fixed_t(besty);
}
bool sector_t::PlaneMoving(int pos)
{
if (pos == floor)
return (floordata != NULL || (planes[floor].Flags & PLANEF_BLOCKED));
else
return (ceilingdata != NULL || (planes[ceiling].Flags & PLANEF_BLOCKED));
}

View File

@ -692,12 +692,12 @@ DLightTransfer::DLightTransfer (sector_t *srcSec, int target, bool copyFloor)
if (copyFloor)
{
for (secnum = -1; (secnum = P_FindSectorFromTag (target, secnum)) >= 0; )
sectors[secnum].ChangeFlags(sector_t::floor, 0, SECF_ABSLIGHTING);
sectors[secnum].ChangeFlags(sector_t::floor, 0, PLANEF_ABSLIGHTING);
}
else
{
for (secnum = -1; (secnum = P_FindSectorFromTag (target, secnum)) >= 0; )
sectors[secnum].ChangeFlags(sector_t::ceiling, 0, SECF_ABSLIGHTING);
sectors[secnum].ChangeFlags(sector_t::ceiling, 0, PLANEF_ABSLIGHTING);
}
ChangeStatNum (STAT_LIGHTTRANSFER);
}

View File

@ -1125,13 +1125,13 @@ struct UDMFParser
continue;
case NAME_Lightfloorabsolute:
if (CheckBool(key)) sec->ChangeFlags(sector_t::floor, 0, SECF_ABSLIGHTING);
else sec->ChangeFlags(sector_t::floor, SECF_ABSLIGHTING, 0);
if (CheckBool(key)) sec->ChangeFlags(sector_t::floor, 0, PLANEF_ABSLIGHTING);
else sec->ChangeFlags(sector_t::floor, PLANEF_ABSLIGHTING, 0);
continue;
case NAME_Lightceilingabsolute:
if (CheckBool(key)) sec->ChangeFlags(sector_t::ceiling, 0, SECF_ABSLIGHTING);
else sec->ChangeFlags(sector_t::ceiling, SECF_ABSLIGHTING, 0);
if (CheckBool(key)) sec->ChangeFlags(sector_t::ceiling, 0, PLANEF_ABSLIGHTING);
else sec->ChangeFlags(sector_t::ceiling, PLANEF_ABSLIGHTING, 0);
continue;
case NAME_Gravity:

View File

@ -2508,9 +2508,27 @@ void player_t::Serialize (FArchive &arc)
<< poisoncount
<< poisoner
<< attacker
<< extralight
<< fixedcolormap
<< morphTics
<< extralight;
if (SaveVersion < 1858)
{
int fixedmap;
arc << fixedmap;
fixedcolormap = NOFIXEDCOLORMAP;
fixedlightlev = -1;
if (fixedmap >= NUMCOLORMAPS)
{
fixedcolormap = fixedmap - NUMCOLORMAPS;
}
else if (fixedmap > 0)
{
fixedlightlev = fixedmap;
}
}
else
{
arc << fixedcolormap << fixedlightlev;
}
arc << morphTics
<< MorphedPlayerClass
<< MorphStyle
<< MorphExitFlash
@ -2532,7 +2550,7 @@ void player_t::Serialize (FArchive &arc)
<< ConversationPC
<< ConversationNPCAngle
<< ConversationFaceTalker;
for (i = 0; i < MAXPLAYERS; i++)
arc << frags[i];
for (i = 0; i < NUMPSPRITES; i++)

View File

@ -114,10 +114,10 @@ union FRenderStyle
BYTE DestAlpha; // Of ERenderAlpha type
BYTE Flags;
};
DWORD AsDWORD;
uint32 AsDWORD;
inline FRenderStyle &operator= (ERenderStyle legacy);
operator DWORD() const { return AsDWORD; }
operator uint32() const { return AsDWORD; }
bool operator==(const FRenderStyle &o) const { return AsDWORD == o.AsDWORD; }
void CheckFuzz();
bool IsVisible(fixed_t alpha) const throw();

View File

@ -270,7 +270,7 @@ void R_ClearClipSegs (short left, short right)
int GetFloorLight (const sector_t *sec)
{
if (sec->GetFlags(sector_t::floor) & SECF_ABSLIGHTING)
if (sec->GetFlags(sector_t::floor) & PLANEF_ABSLIGHTING)
{
return sec->GetPlaneLight(sector_t::floor);
}
@ -282,7 +282,7 @@ int GetFloorLight (const sector_t *sec)
int GetCeilingLight (const sector_t *sec)
{
if (sec->GetFlags(sector_t::ceiling) & SECF_ABSLIGHTING)
if (sec->GetFlags(sector_t::ceiling) & PLANEF_ABSLIGHTING)
{
return sec->GetPlaneLight(sector_t::ceiling);
}

View File

@ -299,7 +299,8 @@ inline FArchive &operator<< (FArchive &arc, secplane_t &plane)
// Ceiling/floor flags
enum
{
SECF_ABSLIGHTING = 1 // floor/ceiling light is absolute, not relative
PLANEF_ABSLIGHTING = 1, // floor/ceiling light is absolute, not relative
PLANEF_BLOCKED = 2 // can not be moved anymore.
};
// Internal sector flags
@ -605,6 +606,8 @@ struct sector_t
return lightlevel;
}
bool PlaneMoving(int pos);
// Member variables
fixed_t CenterFloor () const { return floorplane.ZatPoint (soundorg[0], soundorg[1]); }

View File

@ -2205,7 +2205,7 @@ ESPSResult R_SetPatchStyle (FRenderStyle style, fixed_t alpha, int translation,
hcolfunc_post4 = rt_shaded4cols;
dc_color = fixedcolormap ? fixedcolormap[APART(color)] : basecolormap->Maps[APART(color)];
dc_colormap = (basecolormap = &ShadeFakeColormap[16-alpha])->Maps;
if (fixedlightlev && !fixedcolormap)
if (fixedlightlev >= 0 && fixedcolormap == NULL)
{
dc_colormap += fixedlightlev;
}

View File

@ -140,6 +140,7 @@ int validcount = 1; // increment every time a check is made
FDynamicColormap*basecolormap; // [RH] colormap currently drawing with
int fixedlightlev;
lighttable_t *fixedcolormap;
FSpecialColormap *realfixedcolormap;
float WallTMapScale;
float WallTMapScale2;
@ -1158,46 +1159,36 @@ void R_SetupFrame (AActor *actor)
}
}
realfixedcolormap = NULL;
fixedcolormap = NULL;
fixedlightlev = 0;
fixedlightlev = -1;
if (player != NULL && camera == player->mo && player->fixedcolormap)
if (player != NULL && camera == player->mo)
{
if (player->fixedcolormap < NUMCOLORMAPS)
if (player->fixedcolormap >= 0 && player->fixedcolormap < (int)SpecialColormaps.Size())
{
fixedlightlev = player->fixedcolormap*256;
fixedcolormap = NormalLight.Maps;
realfixedcolormap = &SpecialColormaps[player->fixedcolormap];
if (RenderTarget == screen && (DFrameBuffer *)screen->Accel2D)
{
// Render everything fullbright. The copy to video memory will
// apply the special colormap, so it won't be restricted to the
// palette.
fixedcolormap = realcolormaps;
}
else
{
fixedcolormap = SpecialColormaps[player->fixedcolormap].Colormap;
}
}
else switch (player->fixedcolormap)
else if (player->fixedlightlevel >= 0 && player->fixedlightlevel < NUMCOLORMAPS)
{
case INVERSECOLORMAP:
fixedcolormap = InverseColormap;
break;
case REDCOLORMAP:
fixedcolormap = RedColormap;
break;
case GREENCOLORMAP:
fixedcolormap = GreenColormap;
break;
case BLUECOLORMAP:
fixedcolormap = BlueColormap;
break;
case GOLDCOLORMAP:
fixedcolormap = GoldColormap;
break;
default:
break;
fixedlightlev = player->fixedlightlevel * 256;
}
}
// [RH] Inverse light for shooting the Sigil
else if (extralight == INT_MIN)
if (fixedcolormap == NULL && extralight == INT_MIN)
{
fixedcolormap = InverseColormap;
fixedcolormap = SpecialColormaps[INVERSECOLORMAP].Colormap;
extralight = 0;
}

View File

@ -30,6 +30,7 @@
#include "d_player.h"
#include "r_data.h"
#include "r_state.h"
#include "v_palette.h"
//
@ -88,12 +89,6 @@ extern bool r_dontmaplines;
// 16 discrete light levels. The terminology I use is borrowed from Build.
//
#define INVERSECOLORMAP 32
#define GOLDCOLORMAP 33
#define REDCOLORMAP 34
#define GREENCOLORMAP 35
#define BLUECOLORMAP 36
// The size of a single colormap, in bits
#define COLORMAPSHIFT 8
@ -126,6 +121,7 @@ extern int extralight, r_actualextralight;
extern bool foggy;
extern int fixedlightlev;
extern lighttable_t* fixedcolormap;
extern FSpecialColormap*realfixedcolormap;
//

View File

@ -1407,7 +1407,7 @@ void R_DrawNormalPlane (visplane_t *pl, fixed_t alpha, bool masked)
planeheight = abs (FixedMul (pl->height.d, -pl->height.ic) - viewz);
GlobVis = FixedDiv (r_FloorVisibility, planeheight);
if (fixedlightlev)
if (fixedlightlev >= 0)
ds_colormap = basecolormap->Maps + fixedlightlev, plane_shade = false;
else if (fixedcolormap)
ds_colormap = fixedcolormap, plane_shade = false;
@ -1545,7 +1545,7 @@ void R_DrawTiltedPlane (visplane_t *pl, fixed_t alpha, bool masked)
if (pl->height.c > 0)
planelightfloat = -planelightfloat;
if (fixedlightlev)
if (fixedlightlev >= 0)
ds_colormap = basecolormap->Maps + fixedlightlev, plane_shade = false;
else if (fixedcolormap)
ds_colormap = fixedcolormap, plane_shade = false;

View File

@ -154,7 +154,7 @@ CVAR(Bool, r_fogboundary, true, 0)
inline bool IsFogBoundary (sector_t *front, sector_t *back)
{
return r_fogboundary && !fixedcolormap && front->ColorMap->Fade &&
return r_fogboundary && fixedcolormap == NULL && front->ColorMap->Fade &&
front->ColorMap->Fade != back->ColorMap->Fade &&
(front->GetTexture(sector_t::ceiling) != skyflatnum || back->GetTexture(sector_t::ceiling) != skyflatnum);
}
@ -179,7 +179,7 @@ static void BlastMaskedColumn (void (*blastfunc)(const BYTE *pixels, const FText
if (maskedtexturecol[dc_x] != FIXED_MAX)
{
// calculate lighting
if (!fixedcolormap)
if (fixedcolormap == NULL && fixedlightlev < 0)
{
dc_colormap = basecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT);
}
@ -298,9 +298,9 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
}
}
if (fixedlightlev)
if (fixedlightlev >= 0)
dc_colormap = basecolormap->Maps + fixedlightlev;
else if (fixedcolormap)
else if (fixedcolormap != NULL)
dc_colormap = fixedcolormap;
if (!(curline->linedef->flags & ML_WRAP_MIDTEX) &&
@ -453,7 +453,8 @@ void wallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixed_t
x = x1;
//while ((umost[x] > dmost[x]) && (x <= x2)) x++;
if (fixedcolormap)
bool fixed = (fixedcolormap != NULL || fixedlightlev >= 0);
if (fixed)
{
palookupoffse[0] = dc_colormap;
palookupoffse[1] = dc_colormap;
@ -470,7 +471,7 @@ void wallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixed_t
assert (y1ve[0] < viewheight);
assert (y2ve[0] <= viewheight);
if (!fixedcolormap)
if (!fixed)
{ // calculate lighting
dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
}
@ -505,7 +506,7 @@ void wallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixed_t
continue;
}
if (!fixedcolormap)
if (!fixed)
{
for (z = 0; z < 4; ++z)
{
@ -563,7 +564,7 @@ void wallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixed_t
assert (y1ve[0] < viewheight);
assert (y2ve[0] <= viewheight);
if (!fixedcolormap)
if (!fixed)
{ // calculate lighting
dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
}
@ -700,7 +701,8 @@ void maskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixe
x = startx = x1;
p = x + dc_destorg;
if (fixedcolormap)
bool fixed = (fixedcolormap != NULL || fixedlightlev >= 0);
if (fixed)
{
palookupoffse[0] = dc_colormap;
palookupoffse[1] = dc_colormap;
@ -715,7 +717,7 @@ void maskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixe
y2ve[0] = dwal[x];//min(dwal[x],dmost[x]);
if (y2ve[0] <= y1ve[0]) continue;
if (!fixedcolormap)
if (!fixed)
{ // calculate lighting
dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
}
@ -748,7 +750,7 @@ void maskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixe
continue;
}
if (!fixedcolormap)
if (!fixed)
{
for (z = 0; z < 4; ++z)
{
@ -804,7 +806,7 @@ void maskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixe
y2ve[0] = dwal[x];
if (y2ve[0] <= y1ve[0]) continue;
if (!fixedcolormap)
if (!fixed)
{ // calculate lighting
dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
}
@ -872,7 +874,8 @@ void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal,
x = startx = x1;
p = x + dc_destorg;
if (fixedcolormap)
bool fixed = (fixedcolormap != NULL || fixedlightlev >= 0);
if (fixed)
{
palookupoffse[0] = dc_colormap;
palookupoffse[1] = dc_colormap;
@ -887,7 +890,7 @@ void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal,
y2ve[0] = dwal[x];//min(dwal[x],dmost[x]);
if (y2ve[0] <= y1ve[0]) continue;
if (!fixedcolormap)
if (!fixed)
{ // calculate lighting
dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
}
@ -920,7 +923,7 @@ void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal,
continue;
}
if (!fixedcolormap)
if (!fixed)
{
for (z = 0; z < 4; ++z)
{
@ -979,7 +982,7 @@ void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal,
y2ve[0] = dwal[x];
if (y2ve[0] <= y1ve[0]) continue;
if (!fixedcolormap)
if (!fixed)
{ // calculate lighting
dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
}
@ -1016,9 +1019,9 @@ void R_RenderSegLoop ()
fixed_t xscale, yscale;
fixed_t xoffset = rw_offset;
if (fixedlightlev)
if (fixedlightlev >= 0)
dc_colormap = basecolormap->Maps + fixedlightlev;
else if (fixedcolormap)
else if (fixedcolormap != NULL)
dc_colormap = fixedcolormap;
// clip wall to the floor and ceiling
@ -1087,7 +1090,7 @@ void R_RenderSegLoop ()
{
rw_offset = rw_offset_mid;
}
if (fixedlightlev || fixedcolormap || !frontsector->ExtraLights)
if (fixedcolormap != NULL || !frontsector->ExtraLights)
{
wallscan (x1, x2-1, walltop, wallbottom, swall, lwall, yscale);
}
@ -1126,7 +1129,7 @@ void R_RenderSegLoop ()
{
rw_offset = rw_offset_top;
}
if (fixedlightlev || fixedcolormap || !frontsector->ExtraLights)
if (fixedcolormap != NULL || !frontsector->ExtraLights)
{
wallscan (x1, x2-1, walltop, wallupper, swall, lwall, yscale);
}
@ -1168,7 +1171,7 @@ void R_RenderSegLoop ()
{
rw_offset = rw_offset_bottom;
}
if (fixedlightlev || fixedcolormap || !frontsector->ExtraLights)
if (fixedcolormap != NULL || !frontsector->ExtraLights)
{
wallscan (x1, x2-1, walllower, wallbottom, swall, lwall, yscale);
}
@ -1434,7 +1437,7 @@ void R_NewWall (bool needlights)
PrepWall (swall, lwall, sidedef->TexelLength * lwallscale);
if (!fixedcolormap)
if (fixedcolormap == NULL && fixedlightlev < 0)
{
wallshade = LIGHT2SHADE(curline->sidedef->GetLightLevel(foggy, frontsector->lightlevel)
+ r_actualextralight);
@ -2421,9 +2424,9 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
bool calclighting = false;
rw_light = rw_lightleft + (x1 - WallSX1) * rw_lightstep;
if (fixedlightlev)
if (fixedlightlev >= 0)
dc_colormap = basecolormap->Maps + fixedlightlev;
else if (fixedcolormap)
else if (fixedcolormap != NULL)
dc_colormap = fixedcolormap;
else if (!foggy && (decal->RenderFlags & RF_FULLBRIGHT))
dc_colormap = basecolormap->Maps;

View File

@ -50,6 +50,7 @@
#include "r_plane.h"
#include "r_segs.h"
#include "v_palette.h"
#include "r_translate.h"
extern fixed_t globaluclip, globaldclip;
@ -74,6 +75,10 @@ fixed_t pspritexiscale;
fixed_t sky1scale; // [RH] Sky 1 scale factor
fixed_t sky2scale; // [RH] Sky 2 scale factor
vissprite_t *VisPSprites[NUMPSPRITES];
int VisPSpritesX1[NUMPSPRITES];
FDynamicColormap *VisPSpritesBaseColormap[NUMPSPRITES];
static int spriteshade;
TArray<WORD> ParticlesInSubsec;
@ -1430,50 +1435,40 @@ void R_ProjectSprite (AActor *thing, int fakeside)
if (vis->RenderStyle.Flags & STYLEF_FadeToBlack)
{
if (invertcolormap)
{
// Fade to white
{ // Fade to white
mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(255,255,255), mybasecolormap->Desaturate);
invertcolormap = false;
}
else
{
// Fade to black
{ // Fade to black
mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(0,0,0), mybasecolormap->Desaturate);
}
}
// get light level
if (fixedlightlev)
{
if (invertcolormap)
{
mybasecolormap = GetSpecialLights(mybasecolormap->Color, mybasecolormap->Fade.InverseColor(), mybasecolormap->Desaturate);
}
vis->colormap = mybasecolormap->Maps + fixedlightlev;
}
else if (fixedcolormap)
{
// fixed map
if (fixedcolormap != NULL)
{ // fixed map
vis->colormap = fixedcolormap;
}
else if (!foggy && ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT)))
{
// full bright
if (invertcolormap)
{
mybasecolormap = GetSpecialLights(mybasecolormap->Color, mybasecolormap->Fade.InverseColor(), mybasecolormap->Desaturate);
}
vis->colormap = mybasecolormap->Maps;
}
else
{
// diminished light
if (invertcolormap)
{
mybasecolormap = GetSpecialLights(mybasecolormap->Color, mybasecolormap->Fade.InverseColor(), mybasecolormap->Desaturate);
}
vis->colormap = mybasecolormap->Maps + (GETPALOOKUP (
(fixed_t)DivScale12 (r_SpriteVisibility, tz), spriteshade) << COLORMAPSHIFT);
if (fixedlightlev >= 0)
{
vis->colormap = mybasecolormap->Maps + fixedlightlev;
}
else if (!foggy && ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT)))
{ // full bright
vis->colormap = mybasecolormap->Maps;
}
else
{ // diminished light
vis->colormap = mybasecolormap->Maps + (GETPALOOKUP (
(fixed_t)DivScale12 (r_SpriteVisibility, tz), spriteshade) << COLORMAPSHIFT);
}
}
}
@ -1522,7 +1517,10 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, fixed_t sx, fixed_
WORD flip;
FTexture* tex;
vissprite_t* vis;
vissprite_t avis;
static vissprite_t avis[NUMPSPRITES];
bool noaccel;
assert(pspnum >= 0 && pspnum < NUMPSPRITES);
// decide which patch to use
if ( (unsigned)psp->state->sprite >= (unsigned)sprites.Size ())
@ -1550,7 +1548,7 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, fixed_t sx, fixed_
tx -= tex->GetScaledLeftOffset() << FRACBITS;
x1 = (centerxfrac + FixedMul (tx, pspritexscale)) >>FRACBITS;
VisPSpritesX1[pspnum] = x1;
// off the right side
if (x1 > viewwidth)
@ -1564,7 +1562,7 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, fixed_t sx, fixed_
return;
// store information in a vissprite
vis = &avis;
vis = &avis[pspnum];
vis->renderflags = owner->renderflags;
vis->floorclip = 0;
@ -1619,6 +1617,7 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, fixed_t sx, fixed_
if (vis->x1 > x1)
vis->startfrac += vis->xiscale*(vis->x1-x1);
noaccel = false;
if (pspnum <= ps_flash)
{
vis->alpha = owner->alpha;
@ -1639,67 +1638,93 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, fixed_t sx, fixed_
if (vis->RenderStyle.Flags & STYLEF_FadeToBlack)
{
if (invertcolormap)
{
// Fade to white
{ // Fade to white
mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(255,255,255), mybasecolormap->Desaturate);
invertcolormap = false;
}
else
{
// Fade to black
{ // Fade to black
mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(0,0,0), mybasecolormap->Desaturate);
}
}
if (fixedlightlev)
{
if (invertcolormap)
{
mybasecolormap = GetSpecialLights(mybasecolormap->Color, mybasecolormap->Fade.InverseColor(), mybasecolormap->Desaturate);
}
vis->colormap = mybasecolormap->Maps + fixedlightlev;
}
else if (fixedcolormap)
{
// fixed color
vis->colormap = fixedcolormap;
}
else if (!foggy && psp->state->GetFullbright())
{
// full bright
if (invertcolormap)
{
mybasecolormap = GetSpecialLights(mybasecolormap->Color, mybasecolormap->Fade.InverseColor(), mybasecolormap->Desaturate);
}
vis->colormap = mybasecolormap->Maps; // [RH] use basecolormap
if (realfixedcolormap != NULL)
{ // fixed color
vis->colormap = realfixedcolormap->Colormap;
}
else
{
// local light
if (invertcolormap)
{
mybasecolormap = GetSpecialLights(mybasecolormap->Color, mybasecolormap->Fade.InverseColor(), mybasecolormap->Desaturate);
}
vis->colormap = mybasecolormap->Maps + (GETPALOOKUP (0, spriteshade) << COLORMAPSHIFT);
if (fixedlightlev >= 0)
{
vis->colormap = mybasecolormap->Maps + fixedlightlev;
}
else if (!foggy && psp->state->GetFullbright())
{ // full bright
vis->colormap = mybasecolormap->Maps; // [RH] use basecolormap
}
else
{ // local light
vis->colormap = mybasecolormap->Maps + (GETPALOOKUP (0, spriteshade) << COLORMAPSHIFT);
}
}
if (camera->Inventory != NULL)
{
lighttable_t *oldcolormap = vis->colormap;
camera->Inventory->AlterWeaponSprite (vis);
if (vis->colormap != oldcolormap)
{
// The colormap has changed. Is it one we can easily identify?
// If not, then don't bother trying to identify it for
// hardware accelerated drawing.
if (vis->colormap < SpecialColormaps[0].Colormap ||
vis->colormap >= SpecialColormaps[SpecialColormaps.Size()].Colormap)
{
noaccel = true;
}
// Has the basecolormap changed? If so, we can't hardware accelerate it,
// since we don't know what it is anymore.
else if (vis->colormap < mybasecolormap->Maps ||
vis->colormap >= mybasecolormap->Maps + NUMCOLORMAPS*256)
{
noaccel = true;
}
}
}
VisPSpritesBaseColormap[pspnum] = mybasecolormap;
}
else
{
VisPSpritesBaseColormap[pspnum] = basecolormap;
vis->RenderStyle = STYLE_Normal;
}
// Check for hardware-assisted 2D. If it's available, and this sprite is not
// fuzzy, don't draw it until after the switch to 2D mode.
if (!noaccel && RenderTarget == screen && (DFrameBuffer *)screen->Accel2D)
{
FRenderStyle style = vis->RenderStyle;
style.CheckFuzz();
if (style.BlendOp != STYLEOP_Fuzz)
{
VisPSprites[pspnum] = vis;
return;
}
}
R_DrawVisSprite (vis);
}
//==========================================================================
//
// R_DrawPlayerSprites
//
//==========================================================================
void R_DrawPlayerSprites (void)
{
int i;
@ -1708,7 +1733,7 @@ void R_DrawPlayerSprites (void)
sector_t* sec;
static sector_t tempsec;
int floorlight, ceilinglight;
if (!r_drawplayersprites ||
!camera->player ||
(players[consoleplayer].cheats & CF_CHASECAM))
@ -1766,6 +1791,78 @@ void R_DrawPlayerSprites (void)
}
}
//==========================================================================
//
// R_DrawRemainingPlayerSprites
//
// Called from D_Display to draw sprites that were not drawn by
// R_DrawPlayerSprites().
//
//==========================================================================
void R_DrawRemainingPlayerSprites()
{
for (int i = 0; i < NUMPSPRITES; ++i)
{
vissprite_t *vis;
vis = VisPSprites[i];
VisPSprites[i] = NULL;
if (vis != NULL)
{
FDynamicColormap *colormap = VisPSpritesBaseColormap[i];
bool flip = vis->xiscale < 0;
FSpecialColormap *special = NULL;
PalEntry overlay = 0;
FColormapStyle colormapstyle;
bool usecolormapstyle = false;
if (vis->colormap >= SpecialColormaps[0].Colormap &&
vis->colormap < SpecialColormaps[SpecialColormaps.Size()].Colormap)
{
// Yuck! There needs to be a better way to store colormaps in the vissprite... :(
ptrdiff_t specialmap = (vis->colormap - SpecialColormaps[0].Colormap) / sizeof(FSpecialColormap);
special = &SpecialColormaps[specialmap];
}
else if (colormap->Color == PalEntry(255,255,255) &&
colormap->Desaturate == 0)
{
overlay = colormap->Fade;
overlay.a = BYTE(((vis->colormap - colormap->Maps) >> 8) * 255 / NUMCOLORMAPS);
}
else
{
usecolormapstyle = true;
colormapstyle.Color = colormap->Color;
colormapstyle.Fade = colormap->Fade;
colormapstyle.Desaturate = colormap->Desaturate;
colormapstyle.FadeLevel = ((vis->colormap - colormap->Maps) >> 8) / float(NUMCOLORMAPS);
}
screen->DrawTexture(vis->pic,
viewwindowx + VisPSpritesX1[i],
viewwindowy + viewheight/2 - MulScale32(vis->texturemid, vis->yscale) - 1,
DTA_DestWidth, FixedMul(vis->pic->GetWidth(), vis->xscale),
DTA_DestHeight, FixedMul(vis->pic->GetHeight(), vis->yscale),
DTA_Translation, TranslationToTable(vis->Translation),
DTA_FlipX, flip,
DTA_TopOffset, 0,
DTA_LeftOffset, 0,
DTA_ClipLeft, viewwindowx,
DTA_ClipTop, viewwindowy,
DTA_ClipRight, viewwindowx + viewwidth,
DTA_ClipBottom, viewwindowy + viewheight,
DTA_Alpha, vis->alpha,
DTA_RenderStyle, vis->RenderStyle,
DTA_FillColor, vis->FillColor,
DTA_SpecialColormap, special,
DTA_ColorOverlay, overlay,
DTA_ColormapStyle, usecolormapstyle ? &colormapstyle : NULL,
TAG_DONE);
}
}
}
@ -2423,7 +2520,7 @@ void R_ProjectParticle (particle_t *particle, const sector_t *sector, int shade,
vis->floorclip = 0;
vis->heightsec = heightsec;
if (fixedlightlev)
if (fixedlightlev >= 0)
{
vis->colormap = map + fixedlightlev;
}

View File

@ -102,6 +102,7 @@ void R_InitSprites ();
void R_DeinitSprites ();
void R_ClearSprites ();
void R_DrawMasked ();
void R_DrawRemainingPlayerSprites ();
void R_ClipVisSprite (vissprite_t *vis, int xl, int xh);

View File

@ -120,12 +120,12 @@ public:
}
}
// Return a reference to an element
T &operator[] (unsigned int index) const
T &operator[] (size_t index) const
{
return Array[index];
}
// Returns the value of an element
TT operator() (unsigned int index) const
TT operator() (size_t index) const
{
return Array[index];
}

View File

@ -35,6 +35,7 @@
#include "bitmap.h"
#include "templates.h"
#include "r_translate.h"
#include "v_palette.h"
//===========================================================================
@ -70,86 +71,6 @@ void iCopyColors(BYTE *pout, const BYTE *pin, int count, int step, FCopyInfo *in
}
break;
case BLEND_INVERSEMAP:
// Doom's inverted invulnerability map
for(i=0;i<count;i++)
{
a = TSrc::A(pin);
if (TBlend::ProcessAlpha0() || a)
{
gray = clamp<int>(255 - TSrc::Gray(pin),0,255);
TBlend::OpC(pout[TDest::RED], gray, a, inf);
TBlend::OpC(pout[TDest::GREEN], gray, a, inf);
TBlend::OpC(pout[TDest::BLUE], gray, a, inf);
TBlend::OpA(pout[TDest::ALPHA], a, inf);
}
pout+=4;
pin+=step;
}
break;
case BLEND_GOLDMAP:
// Heretic's golden invulnerability map
for(i=0;i<count;i++)
{
a = TSrc::A(pin);
if (TBlend::ProcessAlpha0() || a)
{
gray = TSrc::Gray(pin);
r=clamp<int>(gray+(gray>>1),0,255);
g=clamp<int>(gray-(gray>>2),0,255);
TBlend::OpC(pout[TDest::RED], r, a, inf);
TBlend::OpC(pout[TDest::GREEN], g, a, inf);
TBlend::OpC(pout[TDest::BLUE], 0, a, inf);
TBlend::OpA(pout[TDest::ALPHA], a, inf);
}
pout+=4;
pin+=step;
}
break;
case BLEND_REDMAP:
// Skulltag's red Doomsphere map
for(i=0;i<count;i++)
{
a = TSrc::A(pin);
if (TBlend::ProcessAlpha0() || a)
{
gray = TSrc::Gray(pin);
r=clamp<int>(gray+(gray>>1),0,255);
TBlend::OpC(pout[TDest::RED], r, a, inf);
TBlend::OpC(pout[TDest::GREEN], 0, a, inf);
TBlend::OpC(pout[TDest::BLUE], 0, a, inf);
TBlend::OpA(pout[TDest::ALPHA], a, inf);
}
pout+=4;
pin+=step;
}
break;
case BLEND_GREENMAP:
// Skulltag's Guardsphere map
for(i=0;i<count;i++)
{
a = TSrc::A(pin);
if (TBlend::ProcessAlpha0() || a)
{
gray = TSrc::Gray(pin);
r=clamp<int>(gray+(gray>>1),0,255);
TBlend::OpC(pout[TDest::RED], r, a, inf);
TBlend::OpC(pout[TDest::GREEN], r, a, inf);
TBlend::OpC(pout[TDest::BLUE], gray, a, inf);
TBlend::OpA(pout[TDest::ALPHA], a, inf);
}
pout+=4;
pin+=step;
}
break;
case BLEND_ICEMAP:
// Create the ice translation table, based on Hexen's.
// Since this is done in True Color the purplish tint is fully preserved - even in Doom!
@ -171,7 +92,28 @@ void iCopyColors(BYTE *pout, const BYTE *pin, int count, int step, FCopyInfo *in
break;
default:
if (inf->blend >= BLEND_DESATURATE1 && inf->blend<=BLEND_DESATURATE31)
if (inf->blend >= BLEND_SPECIALCOLORMAP1)
{
FSpecialColormap *cm = &SpecialColormaps[inf->blend - BLEND_SPECIALCOLORMAP1];
for(i=0;i<count;i++)
{
a = TSrc::A(pin);
if (TBlend::ProcessAlpha0() || a)
{
gray = clamp<int>(255 - TSrc::Gray(pin),0,255);
PalEntry pe = cm->GrayscaleToColor[gray];
TBlend::OpC(pout[TDest::RED], pe.r , a, inf);
TBlend::OpC(pout[TDest::GREEN], pe.g, a, inf);
TBlend::OpC(pout[TDest::BLUE], pe.b, a, inf);
TBlend::OpA(pout[TDest::ALPHA], a, inf);
}
pout+=4;
pin+=step;
}
}
else if (inf->blend >= BLEND_DESATURATE1 && inf->blend<=BLEND_DESATURATE31)
{
// Desaturated light settings.
fac=inf->blend-BLEND_DESATURATE1+1;

View File

@ -262,13 +262,10 @@ enum ColorType
enum EBlend
{
BLEND_NONE = 0,
BLEND_INVERSEMAP = 1,
BLEND_GOLDMAP = 2,
BLEND_REDMAP = 3,
BLEND_GREENMAP = 4,
BLEND_ICEMAP = 5,
BLEND_DESATURATE1 = 6,
BLEND_DESATURATE31 = 36,
BLEND_ICEMAP = 1,
BLEND_DESATURATE1 = 2,
BLEND_DESATURATE31 = 32,
BLEND_SPECIALCOLORMAP1 = 33,
BLEND_MODULATE = -1,
BLEND_OVERLAY = -2,
};

View File

@ -423,27 +423,19 @@ const BYTE *FMultiPatchTexture::GetColumn (unsigned int column, const Span **spa
BYTE *GetBlendMap(PalEntry blend, BYTE *blendwork)
{
switch (blend.a==0 ? blend.r : -1)
switch (blend.a==0 ? int(blend) : -1)
{
case BLEND_INVERSEMAP:
return InverseColormap;
case BLEND_GOLDMAP:
return GoldColormap;
case BLEND_REDMAP:
return RedColormap;
case BLEND_GREENMAP:
return GreenColormap;
case BLEND_ICEMAP:
return TranslationToTable(TRANSLATION(TRANSLATION_Standard, 7))->Remap;
default:
if (blend.r >= BLEND_DESATURATE1 && blend.r <= BLEND_DESATURATE31)
if (blend >= BLEND_SPECIALCOLORMAP1)
{
return DesaturateColormap[blend.r - BLEND_DESATURATE1];
return SpecialColormaps[blend - BLEND_SPECIALCOLORMAP1].Colormap;
}
else if (blend >= BLEND_DESATURATE1 && blend <= BLEND_DESATURATE31)
{
return DesaturateColormap[blend - BLEND_DESATURATE1];
}
else
{
@ -1044,22 +1036,29 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
}
else if (sc.Compare("Translation"))
{
int match;
bComplex = true;
if (part.Translation != NULL) delete part.Translation;
part.Translation = NULL;
part.Blend = 0;
static const char *maps[] = { "inverse", "gold", "red", "green", "ice", "desaturate", NULL };
static const char *maps[] = { "inverse", "gold", "red", "green", "blue", NULL };
sc.MustGetString();
int match = sc.MatchString(maps);
match = sc.MatchString(maps);
if (match >= 0)
{
part.Blend.r = 1 + match;
if (part.Blend.r == BLEND_DESATURATE1)
{
sc.MustGetStringName(",");
sc.MustGetNumber();
part.Blend.r += clamp(sc.Number-1, 0, 30);
}
part.Blend = BLEND_SPECIALCOLORMAP1 + match;
}
else if (sc.Compare("ICE"))
{
part.Blend = BLEND_ICEMAP;
}
else if (sc.Compare("DESATURATE"))
{
sc.MustGetStringName(",");
sc.MustGetNumber();
part.Blend = BLEND_DESATURATE1 + clamp(sc.Number-1, 0, 30);
}
else
{
@ -1075,6 +1074,36 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
}
}
else if (sc.Compare("Colormap"))
{
float r1,g1,b1;
float r2,g2,b2;
sc.MustGetFloat();
r1 = (float)sc.Float;
sc.MustGetStringName(",");
sc.MustGetFloat();
g1 = (float)sc.Float;
sc.MustGetStringName(",");
sc.MustGetFloat();
b1 = (float)sc.Float;
if (!sc.CheckString(","))
{
part.Blend = AddSpecialColormap(0,0,0, r1, g1, b1);
}
else
{
sc.MustGetFloat();
r2 = (float)sc.Float;
sc.MustGetStringName(",");
sc.MustGetFloat();
g2 = (float)sc.Float;
sc.MustGetStringName(",");
sc.MustGetFloat();
b2 = (float)sc.Float;
part.Blend = AddSpecialColormap(r1, g1, b1, r2, g2, b2);
}
}
else if (sc.Compare("Blend"))
{
bComplex = true;
@ -1101,10 +1130,14 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
sc.MustGetStringName(",");
part.Blend = MAKERGB(r, g, b);
}
// Blend.a may never be 0 here.
if (sc.CheckString(","))
{
sc.MustGetFloat();
part.Blend.a = clamp<int>(int(sc.Float*255), 1, 254);
if (sc.Float > 0.f)
part.Blend.a = clamp<int>(int(sc.Float*255), 1, 254);
else
part.Blend = 0;
}
else part.Blend.a = 255;
}

View File

@ -354,12 +354,14 @@ void FTGATexture::MakeTexture ()
int step_x = (hdr.bpp>>3);
int Pitch = Width * step_x;
/*
if (hdr.img_desc&32)
{
ptr += (Width-1) * step_x;
step_x =- step_x;
}
if (!(hdr.img_desc&64))
*/
if (!(hdr.img_desc&32))
{
ptr += (Height-1) * Pitch;
Pitch = -Pitch;
@ -557,12 +559,14 @@ int FTGATexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, i
int step_x = (hdr.bpp>>3);
int Pitch = Width * step_x;
/*
if (hdr.img_desc&32)
{
ptr += (Width-1) * step_x;
step_x =- step_x;
}
if (!(hdr.img_desc&64))
*/
if (!(hdr.img_desc&32))
{
ptr += (Height-1) * Pitch;
Pitch = -Pitch;

View File

@ -141,6 +141,7 @@ static FFlagDef ActorFlags[]=
DEFINE_FLAG(MF3, NOTARGET, AActor, flags3),
DEFINE_FLAG(MF3, DONTGIB, AActor, flags3),
DEFINE_FLAG(MF3, NOBLOCKMONST, AActor, flags3),
DEFINE_FLAG(MF3, AVOIDMELEE, AActor, flags3),
DEFINE_FLAG(MF3, FULLVOLDEATH, AActor, flags3),
DEFINE_FLAG(MF3, FOILINVUL, AActor, flags3),
DEFINE_FLAG(MF3, NOTELEOTHER, AActor, flags3),
@ -239,6 +240,7 @@ static FFlagDef ActorFlags[]=
DEFINE_FLAG2(BOUNCE_Quiet, NOBOUNCESOUND, AActor, BounceFlags),
DEFINE_FLAG2(BOUNCE_AllActors, BOUNCEONACTORS, AActor, BounceFlags),
DEFINE_FLAG2(BOUNCE_ExplodeOnWater, EXPLODEONWATER, AActor, BounceFlags),
DEFINE_FLAG2(BOUNCE_MBF, MBFBOUNCER, AActor, BounceFlags),
// Deprecated flags. Handling must be performed in HandleDeprecatedFlags
DEFINE_DEPRECATED_FLAG(FIREDAMAGE),
@ -295,7 +297,7 @@ static FFlagDef WeaponFlags[] =
DEFINE_FLAG(WIF, POWERED_UP, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF, STAFF2_KICKBACK, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF_BOT, EXPLOSIVE, AWeapon, WeaponFlags),
DEFINE_FLAG2(WIF_BOT_MELEE, MELEEWEAPON, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF, MELEEWEAPON, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF_BOT, BFG, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF, CHEATNOTWEAPON, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF, NO_AUTO_SWITCH, AWeapon, WeaponFlags),

View File

@ -617,6 +617,10 @@ static bool ParsePropertyParams(FScanner &sc, FPropertyInfo *prop, AActor *defau
case 'M': // special case. An expression-aware parser will not need this.
conv.i = ParseMorphStyle(sc);
break;
case 'N': // special case. An expression-aware parser will not need this.
conv.i = ParseThingActivation(sc);
break;
case 'L': // Either a number or a list of strings
if (sc.CheckNumber())

View File

@ -130,15 +130,15 @@ void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set, int ind
break;
// the bounce flags will set the compatibility bounce modes to remain compatible
case DEPF_HERETICBOUNCE:
defaults->BounceFlags &= ~BOUNCE_TypeMask;
defaults->BounceFlags &= ~(BOUNCE_TypeMask|BOUNCE_UseSeeSound);
if (set) defaults->BounceFlags |= BOUNCE_HereticCompat;
break;
case DEPF_HEXENBOUNCE:
defaults->BounceFlags &= ~BOUNCE_TypeMask;
defaults->BounceFlags &= ~(BOUNCE_TypeMask|BOUNCE_UseSeeSound);
if (set) defaults->BounceFlags |= BOUNCE_HexenCompat;
break;
case DEPF_DOOMBOUNCE:
defaults->BounceFlags &= ~BOUNCE_TypeMask;
defaults->BounceFlags &= ~(BOUNCE_TypeMask|BOUNCE_UseSeeSound);
if (set) defaults->BounceFlags |= BOUNCE_DoomCompat;
break;
case DEPF_PICKUPFLASH:
@ -1556,7 +1556,8 @@ DEFINE_CLASS_PROPERTY(weapon, S, WeaponPiece)
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(powerup, color, C_f, Inventory)
{
PROP_INT_PARM(i, 0);
static const char *specialcolormapnames[] = {
"INVERSEMAP", "GOLDMAP", "REDMAP", "GREENMAP", "BLUEMAP", NULL };
int alpha;
PalEntry * pBlendColor;
@ -1582,30 +1583,11 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, color, C_f, Inventory)
{
PROP_STRING_PARM(name, 1);
if (!stricmp(name, "INVERSEMAP"))
// We must check the old special colormap names for compatibility
int v = MatchString(name, specialcolormapnames);
if (v >= 0)
{
*pBlendColor = INVERSECOLOR;
return;
}
else if (!stricmp(name, "GOLDMAP"))
{
*pBlendColor = GOLDCOLOR;
return;
}
// [BC] Yay, more hacks.
else if (!stricmp(name, "REDMAP" ))
{
*pBlendColor = REDCOLOR;
return;
}
else if (!stricmp(name, "GREENMAP" ))
{
*pBlendColor = GREENCOLOR;
return;
}
else if (!stricmp(name, "BLUEMAP"))
{
*pBlendColor = BLUECOLOR;
*pBlendColor = MakeSpecialColormap(v);
return;
}
@ -1619,10 +1601,54 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, color, C_f, Inventory)
else alpha = 255/3;
alpha=clamp<int>(alpha, 0, 255);
if (alpha!=0) *pBlendColor = MAKEARGB(alpha, 0, 0, 0) | color;
if (alpha != 0) *pBlendColor = MAKEARGB(alpha, 0, 0, 0) | color;
else *pBlendColor = 0;
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(powerup, colormap, FFFfff, Inventory)
{
PalEntry * pBlendColor;
if (info->Class->IsDescendantOf(RUNTIME_CLASS(APowerup)))
{
pBlendColor = &((APowerup*)defaults)->BlendColor;
}
else if (info->Class->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
{
pBlendColor = &((APowerupGiver*)defaults)->BlendColor;
}
else
{
I_Error("\"powerup.colormap\" requires an actor of type \"Powerup\"\n");
return;
}
if (PROP_PARM_COUNT == 3)
{
PROP_FLOAT_PARM(r, 0);
PROP_FLOAT_PARM(g, 1);
PROP_FLOAT_PARM(b, 2);
*pBlendColor = MakeSpecialColormap(AddSpecialColormap(0, 0, 0, r, g, b));
}
else if (PROP_PARM_COUNT == 6)
{
PROP_FLOAT_PARM(r1, 0);
PROP_FLOAT_PARM(g1, 1);
PROP_FLOAT_PARM(b1, 2);
PROP_FLOAT_PARM(r2, 3);
PROP_FLOAT_PARM(g2, 4);
PROP_FLOAT_PARM(b2, 5);
*pBlendColor = MakeSpecialColormap(AddSpecialColormap(r1, g1, b1, r2, g2, b2));
}
else
{
I_Error("\"power.colormap\" must have either 3 or 6 parameters\n");
}
}
//==========================================================================
//
//==========================================================================

View File

@ -341,6 +341,8 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
parms->style.BlendOp = 255; // Dummy "not set" value
parms->masked = true;
parms->bilinear = false;
parms->specialcolormap = NULL;
parms->colormapstyle = NULL;
parms->x = x << FRACBITS;
parms->y = y << FRACBITS;
@ -580,6 +582,14 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
case DTA_RenderStyle:
parms->style.AsDWORD = va_arg (tags, DWORD);
break;
case DTA_SpecialColormap:
parms->specialcolormap = va_arg (tags, FSpecialColormap *);
break;
case DTA_ColormapStyle:
parms->colormapstyle = va_arg (tags, FColormapStyle *);
break;
}
tag = va_arg (tags, DWORD);
}

View File

@ -35,6 +35,7 @@
#include <stddef.h>
#include <string.h>
#include <math.h>
#include <float.h>
#ifdef _WIN32
#include <io.h>
#else
@ -61,15 +62,34 @@ extern "C" {
FDynamicColormap NormalLight;
}
FPalette GPalette;
BYTE InverseColormap[256];
BYTE GoldColormap[256];
// [BC] New Skulltag colormaps.
BYTE RedColormap[256];
BYTE GreenColormap[256];
BYTE BlueColormap[256];
TArray<FSpecialColormap> SpecialColormaps;
BYTE DesaturateColormap[31][256];
static void FreeSpecialLights();;
struct FSpecialColormapParameters
{
float Start[3], End[3];
};
static FSpecialColormapParameters SpecialColormapParms[] =
{
// Doom invulnerability is an inverted grayscale.
// Strife uses it when firing the Sigil
{ { 1, 1, 1 }, { 0, 0, 0 } },
// Heretic invulnerability is a golden shade.
{ { 0, 0, 0 }, { 1.5, 0.75, 0 }, },
// [BC] Build the Doomsphere colormap. It is red!
{ { 0, 0, 0 }, { 1.5, 0, 0 } },
// [BC] Build the Guardsphere colormap. It's a greenish-white kind of thing.
{ { 0, 0, 0 }, { 1.25, 1.5, 1 } },
// Build a blue colormap.
{{ 0, 0, 0 }, { 0, 0, 1.5 } },
};
static void FreeSpecialLights();
FColorMatcher ColorMatcher;
@ -341,10 +361,72 @@ static bool FixBuildPalette (BYTE *opal, int lump, bool blood)
return true;
}
int AddSpecialColormap(float r1, float g1, float b1, float r2, float g2, float b2)
{
// Clamp these in range for the hardware shader.
r1 = clamp(r1, 0.0f, 2.0f);
g1 = clamp(g1, 0.0f, 2.0f);
b1 = clamp(b1, 0.0f, 2.0f);
r2 = clamp(r2, 0.0f, 2.0f);
g2 = clamp(g2, 0.0f, 2.0f);
b2 = clamp(b2, 0.0f, 2.0f);
for(unsigned i=0; i<SpecialColormaps.Size(); i++)
{
// Avoid precision issues here when trying to find a proper match.
if (fabs(SpecialColormaps[i].ColorizeStart[0]- r1) < FLT_EPSILON &&
fabs(SpecialColormaps[i].ColorizeStart[1]- g1) < FLT_EPSILON &&
fabs(SpecialColormaps[i].ColorizeStart[2]- b1) < FLT_EPSILON &&
fabs(SpecialColormaps[i].ColorizeEnd[0]- r2) < FLT_EPSILON &&
fabs(SpecialColormaps[i].ColorizeEnd[1]- g2) < FLT_EPSILON &&
fabs(SpecialColormaps[i].ColorizeEnd[2]- b2) < FLT_EPSILON)
{
return i; // The map already exists
}
}
FSpecialColormap *cm = &SpecialColormaps[SpecialColormaps.Reserve(1)];
cm->ColorizeStart[0] = float(r1);
cm->ColorizeStart[1] = float(g1);
cm->ColorizeStart[2] = float(b1);
cm->ColorizeEnd[0] = float(r2);
cm->ColorizeEnd[1] = float(g2);
cm->ColorizeEnd[2] = float(b2);
r2 -= r1;
g2 -= g1;
b2 -= b1;
r1 *= 255;
g1 *= 255;
b1 *= 255;
for (int c = 0; c < 256; c++)
{
double intensity = (GPalette.BaseColors[c].r * 77 +
GPalette.BaseColors[c].g * 143 +
GPalette.BaseColors[c].b * 37) / 256.0;
PalEntry pe = PalEntry( MIN(255, int(r1 + intensity*r2)),
MIN(255, int(g1 + intensity*g2)),
MIN(255, int(b1 + intensity*b2)));
cm->Colormap[c] = ColorMatcher.Pick(pe);
}
// This table is used by the texture composition code
for(int i = 0;i < 256; i++)
{
cm->GrayscaleToColor[i] = PalEntry( MIN(255, int(r1 + i*r2)),
MIN(255, int(g1 + i*g2)),
MIN(255, int(b1 + i*b2)));
}
return SpecialColormaps.Size() - 1;
}
void InitPalette ()
{
BYTE pal[768];
BYTE *shade;
int c;
bool usingBuild = false;
int lump;
@ -384,76 +466,22 @@ void InitPalette ()
NormalLight.Fade = 0;
// NormalLight.Maps is set by R_InitColormaps()
// build special maps (e.g. invulnerability)
int intensity;
// build default special maps (e.g. invulnerability)
SpecialColormaps.Clear();
// Doom invulnerability is an inverted grayscale.
// Strife uses it when firing the Sigil
shade = InverseColormap;
for (c = 0; c < 256; c++)
for (int i = 0; i < countof(SpecialColormapParms); ++i)
{
intensity = (65535 -
(GPalette.BaseColors[c].r * 77 +
GPalette.BaseColors[c].g * 143 +
GPalette.BaseColors[c].b * 37)) >> 8;
shade[c] = ColorMatcher.Pick (intensity, intensity, intensity);
AddSpecialColormap(SpecialColormapParms[i].Start[0], SpecialColormapParms[i].Start[1],
SpecialColormapParms[i].Start[2], SpecialColormapParms[i].End[0],
SpecialColormapParms[i].End[1], SpecialColormapParms[i].End[2]);
}
// Heretic invulnerability is a golden shade.
shade = GoldColormap;
for (c = 0; c < 256; c++)
{
intensity = GPalette.BaseColors[c].r * 77 +
GPalette.BaseColors[c].g * 143 +
GPalette.BaseColors[c].b * 37;
shade[c] = ColorMatcher.Pick (
MIN (255, (intensity+intensity/2)>>8), intensity>>8, 0);
}
// [BC] Build the Doomsphere colormap. It is red!
shade = RedColormap;
for (c = 0; c < 256; c++)
{
intensity = ((GPalette.BaseColors[c].r * 77 +
GPalette.BaseColors[c].g * 143 +
GPalette.BaseColors[c].b * 37));
shade[c] = ColorMatcher.Pick (
MIN( 255, ( intensity + ( intensity / 2 )) >> 8 ), 0, 0 );
}
// [BC] Build the Guardsphere colormap. It's a greenish-white kind of thing.
shade = GreenColormap;
for (c = 0; c < 256; c++)
{
intensity = GPalette.BaseColors[c].r * 77 +
GPalette.BaseColors[c].g * 143 +
GPalette.BaseColors[c].b * 37;
shade[c] = ColorMatcher.Pick (
MIN( 255, ( intensity + ( intensity / 2 )) >> 8 ),
MIN( 255, ( intensity + ( intensity / 2 )) >> 8 ),
intensity>>8 );
}
// Build a blue colormap.
shade = BlueColormap;
for (c = 0; c < 256; c++)
{
intensity = ((GPalette.BaseColors[c].r * 77 +
GPalette.BaseColors[c].g * 143 +
GPalette.BaseColors[c].b * 37));
shade[c] = ColorMatcher.Pick (0, 0,
MIN( 255, ( intensity + ( intensity / 2 )) >> 8 ));
}
// desaturated colormaps
for(int m = 0; m < 31; m++)
{
shade = DesaturateColormap[m];
BYTE *shade = DesaturateColormap[m];
for (c = 0; c < 256; c++)
{
intensity = (GPalette.BaseColors[c].r * 77 +
int intensity = (GPalette.BaseColors[c].r * 77 +
GPalette.BaseColors[c].g * 143 +
GPalette.BaseColors[c].b * 37) / 255;

View File

@ -79,18 +79,60 @@ struct FDynamicColormap
FDynamicColormap *Next;
};
extern BYTE InverseColormap[256];
extern BYTE GoldColormap[256];
// [BC] New Skulltag colormaps.
extern BYTE RedColormap[256];
extern BYTE GreenColormap[256];
extern BYTE BlueColormap[256];
// For hardware-accelerated weapon sprites in colored sectors
struct FColormapStyle
{
PalEntry Color;
PalEntry Fade;
int Desaturate;
float FadeLevel;
};
enum
{
NOFIXEDCOLORMAP = -1,
INVERSECOLORMAP, // the inverse map is used explicitly in a few places.
};
struct FSpecialColormap
{
float ColorizeStart[3];
float ColorizeEnd[3];
BYTE Colormap[256];
PalEntry GrayscaleToColor[256];
};
extern TArray<FSpecialColormap> SpecialColormaps;
// some utility functions to store special colormaps in powerup blends
#define SPECIALCOLORMAP_MASK 0x00b60000
inline int MakeSpecialColormap(int index)
{
assert(index >= 0 && index < 65536);
return index | SPECIALCOLORMAP_MASK;
}
inline bool IsSpecialColormap(int map)
{
return (map & 0xFFFF0000) == SPECIALCOLORMAP_MASK;
}
inline int GetSpecialColormap(int blend)
{
return IsSpecialColormap(blend) ? blend & 0xFFFF : NOFIXEDCOLORMAP;
}
int AddSpecialColormap(float r1, float g1, float b1, float r2, float g2, float b2);
extern BYTE DesaturateColormap[31][256];
extern FPalette GPalette;
extern "C" {
extern FDynamicColormap NormalLight;
}
// The color overlay to use for depleted items
#define DIM_OVERLAY MAKEARGB(170,0,0,0)
@ -110,7 +152,7 @@ void V_SetBlend (int blendr, int blendg, int blendb, int blenda);
// V_ForceBlend()
//
// Normally, V_SetBlend() does nothing if the new blend is the
// same as the old. This function will performing the blending
// same as the old. This function will perform the blending
// even if the blend hasn't changed.
void V_ForceBlend (int blendr, int blendg, int blendb, int blenda);

View File

@ -1099,6 +1099,20 @@ bool DFrameBuffer::Begin2D (bool copy3d)
return false;
}
//==========================================================================
//
// DFrameBuffer :: DrawBlendingRect
//
// In hardware 2D modes, the blending rect needs to be drawn separately
// from transferring the 3D scene to video memory, because the weapon
// sprite is drawn on top of that.
//
//==========================================================================
void DFrameBuffer::DrawBlendingRect()
{
}
//==========================================================================
//
// DFrameBuffer :: CreateTexture
@ -1244,6 +1258,17 @@ void DFrameBuffer::WriteSavePic (player_t *player, FILE *file, int width, int he
delete pic;
}
//===========================================================================
//
//
//
//===========================================================================
void DFrameBuffer::DrawRemainingPlayerSprites()
{
R_DrawRemainingPlayerSprites();
}
FNativePalette::~FNativePalette()

View File

@ -101,6 +101,8 @@ enum
DTA_RenderStyle, // same as render style for actors
DTA_ColorOverlay, // DWORD: ARGB to overlay on top of image; limited to black for software
DTA_BilinearFilter, // bool: apply bilinear filtering to the image
DTA_SpecialColormap,// pointer to FSpecialColormapParameters (likely to be forever hardware-only)
DTA_ColormapStyle, // pointer to FColormapStyle (hardware-only)
// For DrawText calls:
DTA_TextLen, // stop after this many characters, even if \0 not hit
@ -225,6 +227,8 @@ public:
INTBOOL masked;
INTBOOL bilinear;
FRenderStyle style;
struct FSpecialColormap *specialcolormap;
struct FColormapStyle *colormapstyle;
};
protected:
@ -344,17 +348,24 @@ public:
// renders view to a savegame picture
virtual void WriteSavePic (player_t *player, FILE *file, int width, int height);
// draws player sprites with hardware acceleration (only useful for software rendering)
virtual void DrawRemainingPlayerSprites();
bool Accel2D; // If true, 2D drawing can be accelerated.
// Begin 2D drawing operations. This is like Update, but it doesn't end
// the scene, and it doesn't present the image yet. If you are going to
// be covering the entire screen with 2D elements, then pass false to
// avoid copying the software bufferer to the screen.
// avoid copying the software buffer to the screen.
// Returns true if hardware-accelerated 2D has been entered, false if not.
virtual bool Begin2D(bool copy3d);
// DrawTexture calls after Begin2D use native textures.
// Draws the blending rectangle over the viewwindow if in hardware-
// accelerated 2D mode.
virtual void DrawBlendingRect();
// Create a native texture from a game texture.
virtual FNativeTexture *CreateTexture(FTexture *gametex, bool wrapping);

View File

@ -75,7 +75,7 @@
// SAVESIG should match SAVEVER.
// MINSAVEVER is the minimum level snapshot version that can be loaded.
#define MINSAVEVER 1823
#define MINSAVEVER 1848
#if SVN_REVISION_NUMBER < MINSAVEVER
// Never write a savegame with a version lower than what we need

View File

@ -61,13 +61,14 @@
#include "v_pfx.h"
#include "stats.h"
#include "doomerrors.h"
#include "r_draw.h"
#include "r_main.h"
#include "r_translate.h"
#include "f_wipe.h"
#include "st_stuff.h"
#include "win32iface.h"
#include "doomstat.h"
#include "v_palette.h"
#include "w_wad.h"
// MACROS ------------------------------------------------------------------
@ -168,6 +169,7 @@ enum
BQF_WrapUV = 16,
BQF_InvertSource = 32,
BQF_DisableAlphaTest= 64,
BQF_Desaturated = 128,
};
// Shaders for a buffered quad
@ -176,7 +178,9 @@ enum
BQS_PalTex,
BQS_Plain,
BQS_RedToAlpha,
BQS_ColorOnly
BQS_ColorOnly,
BQS_SpecialColormap,
BQS_InGameColormap,
};
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
@ -207,7 +211,33 @@ extern cycle_t BlitCycles;
// PRIVATE DATA DEFINITIONS ------------------------------------------------
#include "fb_d3d9_shaders.h"
const char *const D3DFB::ShaderNames[D3DFB::NUM_SHADERS] =
{
"NormalColor.pso",
"NormalColorPal.pso",
"NormalColorInv.pso",
"NormalColorPalInv.pso",
"RedToAlpha.pso",
"RedToAlphaInv.pso",
"VertexColor.pso",
"SpecialColormap.pso",
"SpecialColorMapPal.pso",
"InGameColormap.pso",
"InGameColormapDesat.pso",
"InGameColormapInv.pso",
"InGameColormapInvDesat.pso",
"InGameColormapPal.pso",
"InGameColormapPalDesat.pso",
"InGameColormapPalInv.pso",
"InGameColormapPalInvDesat.pso",
"BurnWipe.pso",
"GammaCorrection.pso",
};
// PUBLIC DATA DEFINITIONS -------------------------------------------------
@ -216,11 +246,18 @@ CUSTOM_CVAR(Bool, vid_hw2d, true, CVAR_NOINITCALL)
BorderNeedRefresh = SB_state = screen->GetPageCount();
}
CVAR(Bool, d3d_antilag, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR(Int, d3d_showpacks, 0, 0)
CVAR(Bool, vid_hwaalines, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
// CODE --------------------------------------------------------------------
//==========================================================================
//
// D3DFB - Constructor
//
//==========================================================================
D3DFB::D3DFB (int width, int height, bool fullscreen)
: BaseWinFB (width, height)
{
@ -236,15 +273,12 @@ D3DFB::D3DFB (int width, int height, bool fullscreen)
ScreenshotSurface = NULL;
FinalWipeScreen = NULL;
PaletteTexture = NULL;
PalTexShader = NULL;
InvPalTexShader = NULL;
PalTexBilinearShader = NULL;
PlainShader = NULL;
InvPlainShader = NULL;
RedToAlphaShader = NULL;
ColorOnlyShader = NULL;
GammaFixerShader = NULL;
BurnShader = NULL;
for (int i = 0; i < NUM_SHADERS; ++i)
{
Shaders[i] = NULL;
}
BlockSurface[0] = NULL;
BlockSurface[1] = NULL;
FBFormat = D3DFMT_UNKNOWN;
PalFormat = D3DFMT_UNKNOWN;
VSync = vid_vsync;
@ -350,6 +384,12 @@ D3DFB::D3DFB (int width, int height, bool fullscreen)
}
}
//==========================================================================
//
// D3DFB - Destructor
//
//==========================================================================
D3DFB::~D3DFB ()
{
ReleaseResources();
@ -357,8 +397,15 @@ D3DFB::~D3DFB ()
delete[] QuadExtra;
}
//==========================================================================
//
// D3DFB :: SetInitialState
//
// Called after initial device creation and reset, when everything is set
// to D3D's defaults.
//
//==========================================================================
void D3DFB::SetInitialState()
{
AlphaBlendEnabled = FALSE;
@ -398,9 +445,9 @@ void D3DFB::SetInitialState()
D3DDevice->SetGammaRamp(0, 0, &ramp);
}
// Used by the inverse color shaders
float ones[4] = { 1, 1, 1, 1 };
D3DDevice->SetPixelShaderConstantF(6, ones, 1);
// This constant is used for grayscaling weights (.xyz) and color inversion (.w)
float weights[4] = { 77/256.f, 143/256.f, 37/256.f, 1 };
D3DDevice->SetPixelShaderConstantF(PSCONST_Weights, weights, 1);
// D3DRS_ALPHATESTENABLE defaults to FALSE
// D3DRS_ALPHAREF defaults to 0
@ -410,6 +457,12 @@ void D3DFB::SetInitialState()
CurBorderColor = 0;
}
//==========================================================================
//
// D3DFB :: FillPresentParameters
//
//==========================================================================
void D3DFB::FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, bool vsync)
{
memset (pp, 0, sizeof(*pp));
@ -427,7 +480,13 @@ void D3DFB::FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, b
}
}
bool D3DFB::CreateResources ()
//==========================================================================
//
// D3DFB :: CreateResources
//
//==========================================================================
bool D3DFB::CreateResources()
{
Packs = NULL;
if (!Windowed)
@ -444,56 +503,28 @@ bool D3DFB::CreateResources ()
LOG2 ("Resize window to %dx%d\n", sizew, sizeh);
VidResizing = true;
// Make sure the window has a border in windowed mode
SetWindowLong (Window, GWL_STYLE, WS_VISIBLE|WS_OVERLAPPEDWINDOW);
if (GetWindowLong (Window, GWL_EXSTYLE) & WS_EX_TOPMOST)
SetWindowLong(Window, GWL_STYLE, WS_VISIBLE|WS_OVERLAPPEDWINDOW);
if (GetWindowLong(Window, GWL_EXSTYLE) & WS_EX_TOPMOST)
{
// Direct3D 9 will apparently add WS_EX_TOPMOST to fullscreen windows,
// and removing it is a little tricky. Using SetWindowLongPtr to clear it
// will not do the trick, but sending the window behind everything will.
SetWindowPos (Window, HWND_BOTTOM, 0, 0, sizew, sizeh,
SetWindowPos(Window, HWND_BOTTOM, 0, 0, sizew, sizeh,
SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOMOVE);
SetWindowPos (Window, HWND_TOP, 0, 0, 0, 0, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE);
SetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE);
}
else
{
SetWindowPos (Window, NULL, 0, 0, sizew, sizeh,
SetWindowPos(Window, NULL, 0, 0, sizew, sizeh,
SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER);
}
I_RestoreWindowedPos ();
I_RestoreWindowedPos();
VidResizing = false;
}
SM14 = false;
if (FAILED(D3DDevice->CreatePixelShader (PalTexShader20Def, &PalTexShader)) &&
(SM14 = true, FAILED(D3DDevice->CreatePixelShader (PalTexShader14Def, &PalTexShader))))
if (!LoadShaders())
{
return false;
}
if (FAILED(D3DDevice->CreatePixelShader (InvPalTexShader20Def, &InvPalTexShader)) &&
(SM14 = true, FAILED(D3DDevice->CreatePixelShader (InvPalTexShader14Def, &InvPalTexShader))))
{
return false;
}
if (FAILED(D3DDevice->CreatePixelShader (PlainShaderDef, &PlainShader)) ||
FAILED(D3DDevice->CreatePixelShader (InvPlainShaderDef, &InvPlainShader)) ||
FAILED(D3DDevice->CreatePixelShader (RedToAlphaDef, &RedToAlphaShader)) ||
FAILED(D3DDevice->CreatePixelShader (ColorOnlyDef, &ColorOnlyShader)))
{
return false;
}
if (FAILED(D3DDevice->CreatePixelShader (GammaFixerDef, &GammaFixerShader)))
{
// Cannot print during screen creation.
// Printf ("Using Shader Model 1.4: Windowed mode gamma will not work.\n");
GammaFixerShader = NULL;
}
if (FAILED(D3DDevice->CreatePixelShader(PalTexBilinearDef, &PalTexBilinearShader)))
{
PalTexBilinearShader = PalTexShader;
}
if (FAILED(D3DDevice->CreatePixelShader (BurnShaderDef, &BurnShader)))
{
BurnShader = NULL;
}
if (!CreateFBTexture() ||
!CreatePaletteTexture())
{
@ -503,9 +534,66 @@ bool D3DFB::CreateResources ()
{
return false;
}
CreateBlockSurfaces();
return true;
}
//==========================================================================
//
// D3DFB :: LoadShaders
//
// Returns true if all required shaders were loaded. (Gamma and burn wipe
// are the only ones not considered "required".)
//
//==========================================================================
bool D3DFB::LoadShaders()
{
static const char *const models[] = { "30/", "20/", "14/" };
FString shaderdir, shaderpath;
int model, i, lump;
// We determine the best available model simply by trying them all in
// order of decreasing preference.
for (model = 0; model < countof(models); ++model)
{
shaderdir = "shaders/d3d/sm";
shaderdir += models[model];
for (i = 0; i < NUM_SHADERS; ++i)
{
shaderpath = shaderdir;
shaderpath += ShaderNames[i];
lump = Wads.CheckNumForFullName(shaderpath);
if (lump >= 0)
{
FMemLump data = Wads.ReadLump(lump);
if (FAILED(D3DDevice->CreatePixelShader((DWORD *)data.GetMem(), &Shaders[i])) &&
i != SHADER_GammaCorrection && i != SHADER_BurnWipe)
{
break;
}
}
}
if (i == NUM_SHADERS)
{ // Success!
SM14 = (model == countof(models) - 1);
return true;
}
// Failure. Release whatever managed to load (which is probably nothing.)
for (i = 0; i < NUM_SHADERS; ++i)
{
SAFE_RELEASE( Shaders[i] );
}
}
return false;
}
//==========================================================================
//
// D3DFB :: ReleaseResources
//
//==========================================================================
void D3DFB::ReleaseResources ()
{
I_SaveWindowedPos ();
@ -515,22 +603,10 @@ void D3DFB::ReleaseResources ()
SAFE_RELEASE( ScreenshotSurface );
SAFE_RELEASE( ScreenshotTexture );
SAFE_RELEASE( PaletteTexture );
if (PalTexBilinearShader != NULL)
for (int i = 0; i < NUM_SHADERS; ++i)
{
if (PalTexBilinearShader != PalTexShader)
{
PalTexBilinearShader->Release();
}
PalTexBilinearShader = NULL;
SAFE_RELEASE( Shaders[i] );
}
SAFE_RELEASE( PalTexShader );
SAFE_RELEASE( InvPalTexShader );
SAFE_RELEASE( PlainShader );
SAFE_RELEASE( InvPlainShader );
SAFE_RELEASE( RedToAlphaShader );
SAFE_RELEASE( ColorOnlyShader );
SAFE_RELEASE( GammaFixerShader );
SAFE_RELEASE( BurnShader );
if (ScreenWipe != NULL)
{
delete ScreenWipe;
@ -545,7 +621,14 @@ void D3DFB::ReleaseResources ()
GatheringWipeScreen = false;
}
//==========================================================================
//
// D3DFB :: ReleaseDefaultPoolItems
//
// Free resources created with D3DPOOL_DEFAULT.
//
//==========================================================================
void D3DFB::ReleaseDefaultPoolItems()
{
SAFE_RELEASE( FBTexture );
@ -561,8 +644,16 @@ void D3DFB::ReleaseDefaultPoolItems()
SAFE_RELEASE( InitialWipeScreen );
SAFE_RELEASE( VertexBuffer );
SAFE_RELEASE( IndexBuffer );
SAFE_RELEASE( BlockSurface[0] );
SAFE_RELEASE( BlockSurface[1] );
}
//==========================================================================
//
// D3DFB :: Reset
//
//==========================================================================
bool D3DFB::Reset ()
{
D3DPRESENT_PARAMETERS d3dpp;
@ -589,10 +680,35 @@ bool D3DFB::Reset ()
{
return false;
}
CreateBlockSurfaces();
SetInitialState();
return true;
}
//==========================================================================
//
// D3DFB :: CreateBlockSurfaces
//
// Create blocking surfaces for antilag. It's okay if these can't be
// created; antilag just won't work.
//
//==========================================================================
void D3DFB::CreateBlockSurfaces()
{
BlockNum = 0;
if (SUCCEEDED(D3DDevice->CreateOffscreenPlainSurface(16, 16, D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT, &BlockSurface[0], 0)))
{
if (FAILED(D3DDevice->CreateOffscreenPlainSurface(16, 16, D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT, &BlockSurface[1], 0)))
{
BlockSurface[0]->Release();
BlockSurface[0] = NULL;
}
}
}
//==========================================================================
//
// D3DFB :: KillNativePals
@ -836,10 +952,7 @@ void D3DFB::Update ()
DrawRateStuff();
DrawPackedTextures(d3d_showpacks);
EndBatch(); // Make sure all batched primitives are drawn.
DoWindowedGamma();
D3DDevice->EndScene();
D3DDevice->Present(NULL, NULL, NULL, NULL);
InScene = false;
Flip();
}
In2D = 0;
return;
@ -881,7 +994,7 @@ void D3DFB::Update ()
}
psgamma[2] = psgamma[1] = psgamma[0] = igamma;
psgamma[3] = 1;
D3DDevice->SetPixelShaderConstantF(7, psgamma, 1);
D3DDevice->SetPixelShaderConstantF(PSCONST_Gamma, psgamma, 1);
}
if (NeedPalUpdate)
@ -902,10 +1015,7 @@ void D3DFB::Update ()
Draw3DPart(In2D <= 1);
if (In2D == 0)
{
DoWindowedGamma();
D3DDevice->EndScene();
D3DDevice->Present(NULL, NULL, NULL, NULL);
InScene = false;
Flip();
}
BlitCycles.Unclock();
@ -915,6 +1025,30 @@ void D3DFB::Update ()
UpdatePending = false;
}
void D3DFB::Flip()
{
assert(InScene);
DoWindowedGamma();
D3DDevice->EndScene();
// Attempt to counter input lag.
if (d3d_antilag && BlockSurface[0] != NULL)
{
D3DLOCKED_RECT lr;
volatile int dummy;
D3DDevice->ColorFill(BlockSurface[BlockNum], NULL, D3DCOLOR_ARGB(0xFF,0,0x20,0x50));
BlockNum ^= 1;
if (!FAILED((BlockSurface[BlockNum]->LockRect(&lr, NULL, D3DLOCK_READONLY))))
{
dummy = *(int *)lr.pBits;
BlockSurface[BlockNum]->UnlockRect();
}
}
D3DDevice->Present(NULL, NULL, NULL, NULL);
InScene = false;
}
bool D3DFB::PaintToWindow ()
{
HRESULT hr;
@ -971,7 +1105,7 @@ void D3DFB::Draw3DPart(bool copy3d)
D3DDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, vid_hwaalines);
assert(OldRenderTarget == NULL);
if (TempRenderTexture != NULL &&
((Windowed && GammaFixerShader && TempRenderTexture != FinalWipeScreen) || GatheringWipeScreen || PixelDoubling))
((Windowed && Shaders[SHADER_GammaCorrection] && TempRenderTexture != FinalWipeScreen) || GatheringWipeScreen || PixelDoubling))
{
IDirect3DSurface9 *targetsurf;
if (SUCCEEDED(TempRenderTexture->GetSurfaceLevel(0, &targetsurf)))
@ -989,17 +1123,40 @@ void D3DFB::Draw3DPart(bool copy3d)
SetTexture (0, FBTexture);
SetPaletteTexture(PaletteTexture, 256, BorderColor);
SetPixelShader(PalTexShader);
D3DDevice->SetFVF (D3DFVF_FBVERTEX);
memset(Constant, 0, sizeof(Constant));
SetAlphaBlend(D3DBLENDOP(0));
EnableAlphaTest(FALSE);
SetPixelShader(Shaders[SHADER_NormalColorPal]);
if (copy3d)
{
FBVERTEX verts[4];
CalcFullscreenCoords(verts, Accel2D, false, FlashColor0, FlashColor1);
D3DCOLOR color0, color1;
if (Accel2D)
{
if (realfixedcolormap == NULL)
{
color0 = 0;
color1 = 0xFFFFFFF;
}
else
{
color0 = D3DCOLOR_COLORVALUE(realfixedcolormap->ColorizeStart[0]/2,
realfixedcolormap->ColorizeStart[1]/2, realfixedcolormap->ColorizeStart[2]/2, 0);
color1 = D3DCOLOR_COLORVALUE(realfixedcolormap->ColorizeEnd[0]/2,
realfixedcolormap->ColorizeEnd[1]/2, realfixedcolormap->ColorizeEnd[2]/2, 1);
SetPixelShader(Shaders[SHADER_SpecialColormapPal]);
}
}
else
{
color0 = FlashColor0;
color1 = FlashColor1;
}
CalcFullscreenCoords(verts, Accel2D, false, color0, color1);
D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX));
}
SetPixelShader(Shaders[SHADER_NormalColorPal]);
}
//==========================================================================
@ -1039,7 +1196,7 @@ void D3DFB::DoWindowedGamma()
D3DDevice->SetRenderTarget(0, OldRenderTarget);
D3DDevice->SetFVF(D3DFVF_FBVERTEX);
SetTexture(0, TempRenderTexture);
SetPixelShader((Windowed && GammaFixerShader != NULL) ? GammaFixerShader : PlainShader);
SetPixelShader(Shaders[(Windowed && Shaders[SHADER_GammaCorrection]) ? SHADER_GammaCorrection : SHADER_NormalColor]);
SetAlphaBlend(D3DBLENDOP(0));
EnableAlphaTest(FALSE);
D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX));
@ -2148,6 +2305,23 @@ bool D3DFB::Begin2D(bool copy3d)
return true;
}
//==========================================================================
//
// D3DFB :: DrawBlendingRect
//
// Call after Begin2D to blend the 3D view.
//
//==========================================================================
void D3DFB::DrawBlendingRect()
{
if (!In2D || !Accel2D)
{
return;
}
Dim(FlashColor, FlashAmount / 256.f, viewwindowx, viewwindowy, viewwidth, viewheight);
}
//==========================================================================
//
// D3DFB :: CreateTexture
@ -2278,7 +2452,7 @@ void D3DFB::EndLineBatch()
VertexBuffer->Unlock();
if (VertexPos > 0)
{
SetPixelShader(ColorOnlyShader);
SetPixelShader(Shaders[SHADER_VertexColor]);
SetAlphaBlend(D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
D3DDevice->SetStreamSource(0, VertexBuffer, 0, sizeof(FBVERTEX));
D3DDevice->DrawPrimitive(D3DPT_LINELIST, 0, VertexPos / 2);
@ -2357,7 +2531,7 @@ void D3DFB::DrawPixel(int x, int y, int palcolor, uint32 color)
float(x), float(y), 0, 1, color
};
EndBatch(); // Draw out any batched operations.
SetPixelShader(ColorOnlyShader);
SetPixelShader(Shaders[SHADER_VertexColor]);
SetAlphaBlend(D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
D3DDevice->DrawPrimitiveUP(D3DPT_POINTLIST, 1, &pt, sizeof(FBVERTEX));
}
@ -2454,7 +2628,10 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi
EndQuadBatch();
BeginQuadBatch();
}
RECT scissor = { parms.lclip, parms.uclip, parms.rclip, parms.dclip };
RECT scissor = {
parms.lclip, parms.uclip + LBOffsetI,
parms.rclip, parms.dclip + LBOffsetI
};
D3DDevice->SetScissorRect(&scissor);
D3DDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
}
@ -2845,26 +3022,38 @@ void D3DFB::EndQuadBatch()
// Set the pixel shader
if (quad->ShaderNum == BQS_PalTex)
{
if (!(quad->Flags & BQF_Bilinear))
{
SetPixelShader((quad->Flags & BQF_InvertSource) ? InvPalTexShader : PalTexShader);
}
else
{
SetPixelShader(PalTexBilinearShader);
}
SetPixelShader(Shaders[(quad->Flags & BQF_InvertSource) ?
SHADER_NormalColorPalInv : SHADER_NormalColorPal]);
}
else if (quad->ShaderNum == BQS_Plain)
{
SetPixelShader((quad->Flags & BQF_InvertSource) ? InvPlainShader : PlainShader);
SetPixelShader(Shaders[(quad->Flags & BQF_InvertSource) ?
SHADER_NormalColorInv : SHADER_NormalColor]);
}
else if (quad->ShaderNum == BQS_RedToAlpha)
{
SetPixelShader(RedToAlphaShader);
SetPixelShader(Shaders[(quad->Flags & BQF_InvertSource) ?
SHADER_RedToAlphaInv : SHADER_RedToAlpha]);
}
else if (quad->ShaderNum == BQS_ColorOnly)
{
SetPixelShader(ColorOnlyShader);
SetPixelShader(Shaders[SHADER_VertexColor]);
}
else if (quad->ShaderNum == BQS_SpecialColormap)
{
int select;
select = !!(quad->Flags & BQF_Paletted);
SetPixelShader(Shaders[SHADER_SpecialColormap + select]);
}
else if (quad->ShaderNum == BQS_InGameColormap)
{
int select;
select = !!(quad->Flags & BQF_Desaturated);
select |= !!(quad->Flags & BQF_InvertSource) << 1;
select |= !!(quad->Flags & BQF_Paletted) << 2;
SetPixelShader(Shaders[SHADER_InGameColormap + select]);
}
// Set the texture clamp addressing mode
@ -2961,6 +3150,7 @@ bool D3DFB::SetStyle(D3DTex *tex, DrawParms &parms, D3DCOLOR &color0, D3DCOLOR &
stencilling = false;
quad.Palette = NULL;
quad.Flags = 0;
switch (style.BlendOp)
{
@ -3047,10 +3237,42 @@ bool D3DFB::SetStyle(D3DTex *tex, DrawParms &parms, D3DCOLOR &color0, D3DCOLOR &
{
quad.Flags |= BQF_InvertSource;
}
if (parms.specialcolormap != NULL)
{ // Emulate an invulnerability or similar colormap.
float *start, *end;
start = parms.specialcolormap->ColorizeStart;
end = parms.specialcolormap->ColorizeEnd;
if (quad.Flags & BQF_InvertSource)
{
quad.Flags &= ~BQF_InvertSource;
swap(start, end);
}
quad.ShaderNum = BQS_SpecialColormap;
color0 = D3DCOLOR_RGBA(DWORD(start[0]/2*255), DWORD(start[1]/2*255), DWORD(start[2]/2*255), color0 >> 24);
color1 = D3DCOLOR_RGBA(DWORD(end[0]/2*255), DWORD(end[1]/2*255), DWORD(end[2]/2*255), color1 >> 24);
}
else if (parms.colormapstyle != NULL)
{ // Emulate the fading from an in-game colormap (colorized, faded, and desaturated)
if (parms.colormapstyle->Desaturate != 0)
{
quad.Flags |= BQF_Desaturated;
}
quad.ShaderNum = BQS_InGameColormap;
color0 = D3DCOLOR_ARGB(parms.colormapstyle->Desaturate,
parms.colormapstyle->Color.r,
parms.colormapstyle->Color.g,
parms.colormapstyle->Color.b);
double fadelevel = parms.colormapstyle->FadeLevel;
color1 = D3DCOLOR_ARGB(DWORD((1 - fadelevel) * 255),
DWORD(parms.colormapstyle->Fade.r * fadelevel),
DWORD(parms.colormapstyle->Fade.g * fadelevel),
DWORD(parms.colormapstyle->Fade.b * fadelevel));
}
}
// For unmasked images, force the alpha from the image data to be ignored.
if (!parms.masked)
if (!parms.masked && quad.ShaderNum != BQS_InGameColormap)
{
color0 = (color0 & D3DCOLOR_RGBA(255, 255, 255, 0)) | D3DCOLOR_COLORVALUE(0, 0, 0, alpha);
color1 &= D3DCOLOR_RGBA(255, 255, 255, 0);
@ -3187,7 +3409,7 @@ void D3DFB::SetPaletteTexture(IDirect3DTexture9 *texture, int count, D3DCOLOR bo
if (SM14)
{
// Shader Model 1.4 only uses 256-color palettes.
SetConstant(2, 1.f, 0.5f / 256.f, 0, 0);
SetConstant(PSCONST_PaletteMod, 1.f, 0.5f / 256.f, 0, 0);
if (border_color != 0 && CurBorderColor != border_color)
{
CurBorderColor = border_color;
@ -3208,13 +3430,14 @@ void D3DFB::SetPaletteTexture(IDirect3DTexture9 *texture, int count, D3DCOLOR bo
// The constant register c2 is used to hold the multiplier in the
// x part and the adder in the y part.
float fcount = 1 / float(count);
SetConstant(2, pc * fcount, pal * fcount, 0, 0);
SetConstant(PSCONST_PaletteMod, pc * fcount, pal * fcount, 0, 0);
}
SetTexture(1, texture);
}
void D3DFB::SetPalTexBilinearConstants(PackingTexture *tex)
{
#if 0
float con[8];
// Don't bother doing anything if the constants won't be used.
@ -3233,4 +3456,5 @@ void D3DFB::SetPalTexBilinearConstants(PackingTexture *tex)
con[7] = con[3];
D3DDevice->SetPixelShaderConstantF(3, con, 2);
#endif
}

View File

@ -1,665 +0,0 @@
#define HLSL_SOURCE_CODE 0
#define SHADER_ASSEMBLY_CODE 0
// A paletted texture shader ------------------------------------------------
#if HLSL_SOURCE_CODE
sampler2D Image : register(s0);
sampler1D Palette : register(s1);
float4 PaletteMod : register(c2);
float4 main (float2 texCoord : TEXCOORD0, float4 Flash : COLOR0, float4 InvFlash : COLOR1) : COLOR
{
float index = tex2D (Image, texCoord).x;
index = index * PaletteMod.x + PaletteMod.y;
float4 rgb = tex1D (Palette, index);
return Flash + rgb * InvFlash;
}
#elif SHADER_ASSEMBLY_CODE
//
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
//
// fxc paltex.ps /Tps_1_4 /LD /VnPalTexShader14Def /Fhpaltex.h
//
//
// Parameters:
//
// sampler2D Image;
// sampler1D Palette;
// float4 PaletteMod;
//
//
// Registers:
//
// Name Reg Size
// ------------ ----- ----
// PaletteMod c2 1
// Image s0 1
// Palette s1 1
//
ps_1_4
texld r0, t0
mad r0.xy, r0.x, c2.x, c2.y
phase
texld r1, r0
mad r0, r1, v1, v0
// approximately 4 instruction slots used (2 texture, 2 arithmetic)
#endif
const DWORD PalTexShader14Def[] =
{
0xffff0104, 0x0039fffe, 0x42415443, 0x0000001c, 0x000000ab, 0xffff0104,
0x00000003, 0x0000001c, 0x00000100, 0x000000a4, 0x00000058, 0x00000003,
0x00000001, 0x00000060, 0x00000000, 0x00000070, 0x00010003, 0x00000001,
0x00000078, 0x00000000, 0x00000088, 0x00020002, 0x00020001, 0x00000094,
0x00000000, 0x67616d49, 0xabab0065, 0x000c0004, 0x00010001, 0x00000001,
0x00000000, 0x656c6150, 0x00657474, 0x000b0004, 0x00010001, 0x00000001,
0x00000000, 0x656c6150, 0x4d657474, 0xab00646f, 0x00030001, 0x00040001,
0x00000001, 0x00000000, 0x315f7370, 0x4d00345f, 0x6f726369, 0x74666f73,
0x29522820, 0x44334420, 0x53203958, 0x65646168, 0x6f432072, 0x6c69706d,
0x39207265, 0x2e35312e, 0x2e393737, 0x30303030, 0xababab00, 0x00000042,
0x800f0000, 0xb0e40000, 0x00000004, 0x80030000, 0x80000000, 0xa0000002,
0xa0550002, 0x0000fffd, 0x00000042, 0x800f0001, 0x80e40000, 0x00000004,
0x800f0000, 0x80e40001, 0x90e40001, 0x90e40000, 0x0000ffff
};
#if SHADER_ASSEMBLY_CODE
ps_2_0
dcl t0.xy
dcl v0
dcl v1
dcl_2d s0
dcl_2d s1
texld r0, t0, s0
mad r0.xy, r0.x, c2.x, c2.y
texld r0, r0, s1
mov r1, v1
mad r0, r0, r1, v0
mov oC0, r0
// approximately 6 instruction slots used (2 texture, 4 arithmetic)
#endif
const DWORD PalTexShader20Def[] =
{
0xffff0200, 0x0039fffe, 0x42415443, 0x0000001c, 0x000000ab, 0xffff0200,
0x00000003, 0x0000001c, 0x00000100, 0x000000a4, 0x00000058, 0x00000003,
0x00000001, 0x00000060, 0x00000000, 0x00000070, 0x00010003, 0x00000001,
0x00000078, 0x00000000, 0x00000088, 0x00020002, 0x00020001, 0x00000094,
0x00000000, 0x67616d49, 0xabab0065, 0x000c0004, 0x00010001, 0x00000001,
0x00000000, 0x656c6150, 0x00657474, 0x000b0004, 0x00010001, 0x00000001,
0x00000000, 0x656c6150, 0x4d657474, 0xab00646f, 0x00030001, 0x00040001,
0x00000001, 0x00000000, 0x325f7370, 0x4d00305f, 0x6f726369, 0x74666f73,
0x29522820, 0x44334420, 0x53203958, 0x65646168, 0x6f432072, 0x6c69706d,
0x39207265, 0x2e35312e, 0x2e393737, 0x30303030, 0xababab00, 0x0200001f,
0x80000000, 0xb0030000, 0x0200001f, 0x80000000, 0x900f0000, 0x0200001f,
0x80000000, 0x900f0001, 0x0200001f, 0x90000000, 0xa00f0800, 0x0200001f,
0x90000000, 0xa00f0801, 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800,
0x04000004, 0x80030000, 0x80000000, 0xa0000002, 0xa0550002, 0x03000042,
0x800f0000, 0x80e40000, 0xa0e40801, 0x02000001, 0x800f0001, 0x90e40001,
0x04000004, 0x800f0000, 0x80e40000, 0x80e40001, 0x90e40000, 0x02000001,
0x800f0800, 0x80e40000, 0x0000ffff
};
// An inverted paletted texture shader --------------------------------------
#if HLSL_SOURCE_CODE
sampler2D Image : register(s0);
sampler1D Palette : register(s1);
float4 PaletteMod : register(c2);
float4 White : register(c6); // Preloaded with (1,1,1,0)
float4 main (float2 texCoord : TEXCOORD0, float4 Flash : COLOR0, float4 InvFlash : COLOR1) : COLOR
{
float index = tex2D (Image, texCoord).x;
index = index * PaletteMod.x + PaletteMod.y;
float4 rgb = tex1D (Palette, index);
rgb.xyz = White.xyz - rgb.xyz;
return Flash + rgb * InvFlash;
}
#elif SHADER_ASSEMBLY_CODE
//
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
//
// fxc paltex.ps /Tps_1_4 /LD /VnInvPalTexShader14Def /Fhinvpaltex.h
//
//
// Parameters:
//
// sampler2D Image;
// sampler1D Palette;
// float4 PaletteMod;
// float4 White;
//
//
// Registers:
//
// Name Reg Size
// ------------ ----- ----
// PaletteMod c2 1
// White c6 1
// Image s0 1
// Palette s1 1
//
ps_1_4
texld r0, t0
mad r0.xy, r0.x, c2.x, c2.y
phase
texld r1, r0
add r1.xyz, -r1, c6
mad r0, r1, v1, v0
// approximately 5 instruction slots used (2 texture, 3 arithmetic)
#endif
const DWORD InvPalTexShader14Def[] =
{
0xffff0104, 0x003ffffe, 0x42415443, 0x0000001c, 0x000000c5, 0xffff0104,
0x00000004, 0x0000001c, 0x00000100, 0x000000be, 0x0000006c, 0x00000003,
0x00000001, 0x00000074, 0x00000000, 0x00000084, 0x00010003, 0x00000001,
0x0000008c, 0x00000000, 0x0000009c, 0x00020002, 0x00020001, 0x000000a8,
0x00000000, 0x000000b8, 0x00060002, 0x00020001, 0x000000a8, 0x00000000,
0x67616d49, 0xabab0065, 0x000c0004, 0x00010001, 0x00000001, 0x00000000,
0x656c6150, 0x00657474, 0x000b0004, 0x00010001, 0x00000001, 0x00000000,
0x656c6150, 0x4d657474, 0xab00646f, 0x00030001, 0x00040001, 0x00000001,
0x00000000, 0x74696857, 0x73700065, 0x345f315f, 0x63694d00, 0x6f736f72,
0x28207466, 0x44202952, 0x39584433, 0x61685320, 0x20726564, 0x706d6f43,
0x72656c69, 0x312e3920, 0x37372e35, 0x30302e39, 0xab003030, 0x00000042,
0x800f0000, 0xb0e40000, 0x00000004, 0x80030000, 0x80000000, 0xa0000002,
0xa0550002, 0x0000fffd, 0x00000042, 0x800f0001, 0x80e40000, 0x00000002,
0x80070001, 0x81e40001, 0xa0e40006, 0x00000004, 0x800f0000, 0x80e40001,
0x90e40001, 0x90e40000, 0x0000ffff
};
#if SHADER_ASSEMBLY_CODE
ps_2_0
dcl t0.xy
dcl v0
dcl v1
dcl_2d s0
dcl_2d s1
texld r0, t0, s0
mad r0.xy, r0.x, c2.x, c2.y
texld r0, r0, s1
add r0.xyz, -r0, c6
mov r1, v1
mad r0, r0, r1, v0
mov oC0, r0
// approximately 7 instruction slots used (2 texture, 5 arithmetic)
#endif
const DWORD InvPalTexShader20Def[] =
{
0xffff0200, 0x003ffffe, 0x42415443, 0x0000001c, 0x000000c5, 0xffff0200,
0x00000004, 0x0000001c, 0x20000100, 0x000000be, 0x0000006c, 0x00000003,
0x00020001, 0x00000074, 0x00000000, 0x00000084, 0x00010003, 0x00060001,
0x0000008c, 0x00000000, 0x0000009c, 0x00020002, 0x000a0001, 0x000000a8,
0x00000000, 0x000000b8, 0x00060002, 0x001a0001, 0x000000a8, 0x00000000,
0x67616d49, 0xabab0065, 0x000c0004, 0x00010001, 0x00000001, 0x00000000,
0x656c6150, 0x00657474, 0x000b0004, 0x00010001, 0x00000001, 0x00000000,
0x656c6150, 0x4d657474, 0xab00646f, 0x00030001, 0x00040001, 0x00000001,
0x00000000, 0x74696857, 0x73700065, 0x305f325f, 0x63694d00, 0x6f736f72,
0x28207466, 0x48202952, 0x204c534c, 0x64616853, 0x43207265, 0x69706d6f,
0x2072656c, 0x39312e39, 0x3934392e, 0x3131322e, 0xabab0031, 0x0200001f,
0x80000000, 0xb0030000, 0x0200001f, 0x80000000, 0x900f0000, 0x0200001f,
0x80000000, 0x900f0001, 0x0200001f, 0x90000000, 0xa00f0800, 0x0200001f,
0x90000000, 0xa00f0801, 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800,
0x04000004, 0x80030000, 0x80000000, 0xa0000002, 0xa0550002, 0x03000042,
0x800f0000, 0x80e40000, 0xa0e40801, 0x03000002, 0x80070000, 0x81e40000,
0xa0e40006, 0x02000001, 0x800f0001, 0x90e40001, 0x04000004, 0x800f0000,
0x80e40000, 0x80e40001, 0x90e40000, 0x02000001, 0x800f0800, 0x80e40000,
0x0000ffff
};
// A paletted texture shader that does bilinear filtering -------------------
#if HLSL_SOURCE_CODE
sampler2D Image : register(s0);
sampler2D Palette : register(s1);
float4 PaletteMod : register(c2);
//#define texture_size_x 512.0f
//#define texture_size_y 256.0f
//#define texel_size_x 1.0f / 512.0f
//#define texel_size_y 1.0f / 256.0f
// texture_size_x, texture_size_y, 0, texel_size_x
float4 size_a : register(c3);
// 0, texel_size_y, texel_size_y, texel_size_x
float4 size_b : register(c4);
float4 main (float2 texCoord : TEXCOORD0, float4 Flash : COLOR0, float4 InvFlash : COLOR1) : COLOR
{
float2 f = frac (texCoord.xy * size_a/*float2(texture_size_x, texture_size_y)*/);
float4 t00 = tex2D(Image, texCoord);
float4 t10 = tex2D(Image, texCoord + size_a.wz/*float2(texel_size_x, 0)*/);
t00.x = t00.x * PaletteMod.x + PaletteMod.y;
t10.x = t10.x * PaletteMod.x + PaletteMod.y;
float4 c00 = tex2D(Palette, t00);
float4 c10 = tex2D(Palette, t10);
float4 cA = lerp(c00, c10, f.x);
float4 t01 = tex2D(Image, texCoord + size_b.xy/*float2(0, texel_size_y)*/);
float4 t11 = tex2D(Image, texCoord + size_b.wz/*float2(texel_size_x, texel_size_y)*/);
t01.x = t01.x * PaletteMod.x + PaletteMod.y;
t11.x = t11.x * PaletteMod.x + PaletteMod.y;
float4 c01 = tex2D(Palette, t01);
float4 c11 = tex2D(Palette, t11);
float4 cB = lerp(c01, c11, f.x);
return Flash + lerp(cA, cB, f.y) * InvFlash;
}
#elif SHADER_ASSEMBLY_CODE
//
// Generated by Microsoft (R) HLSL Shader Compiler 9.19.949.2111
//
// fxc paltex_bilinear.ps /Tps_2_0 /VnPalTexBilinearDef /Fhpaltex_bilinear.h
//
//
// Parameters:
//
// sampler2D Image;
// sampler2D Palette;
// float4 PaletteMod;
// float4 size_a;
// float4 size_b;
//
//
// Registers:
//
// Name Reg Size
// ------------ ----- ----
// PaletteMod c2 1
// size_a c3 1
// size_b c4 1
// Image s0 1
// Palette s1 1
//
ps_2_0
dcl t0.xy
dcl v0
dcl v1
dcl_2d s0
dcl_2d s1
add r0.xy, t0, c4
add r1.xy, t0, c4.wzyx
add r2.xy, t0, c3.wzyx
texld r0, r0, s0
texld r1, r1, s0
texld r2, r2, s0
texld r3, t0, s0
mad r0.x, r0.x, c2.x, c2.y
mad r1.x, r1.x, c2.x, c2.y
mad r2.x, r2.x, c2.x, c2.y
mad r3.x, r3.x, c2.x, c2.y
texld r0, r0, s1
texld r1, r1, s1
texld r2, r2, s1
texld r3, r3, s1
mul r4.xy, t0, c3
frc r4.xy, r4
lrp r5, r4.x, r1, r0
lrp r0, r4.x, r2, r3
lrp r1, r4.y, r5, r0
mov r0, v1
mad r0, r1, r0, v0
mov oC0, r0
// approximately 23 instruction slots used (8 texture, 15 arithmetic)
#endif
const DWORD PalTexBilinearDef[] =
{
0xffff0200, 0x0042fffe, 0x42415443, 0x0000001c, 0x000000d1, 0xffff0200,
0x00000005, 0x0000001c, 0x20000100, 0x000000ca, 0x00000080, 0x00000003,
0x00020001, 0x00000088, 0x00000000, 0x00000098, 0x00010003, 0x00060001,
0x00000088, 0x00000000, 0x000000a0, 0x00020002, 0x000a0001, 0x000000ac,
0x00000000, 0x000000bc, 0x00030002, 0x000e0001, 0x000000ac, 0x00000000,
0x000000c3, 0x00040002, 0x00120001, 0x000000ac, 0x00000000, 0x67616d49,
0xabab0065, 0x000c0004, 0x00010001, 0x00000001, 0x00000000, 0x656c6150,
0x00657474, 0x656c6150, 0x4d657474, 0xab00646f, 0x00030001, 0x00040001,
0x00000001, 0x00000000, 0x657a6973, 0x7300615f, 0x5f657a69, 0x73700062,
0x305f325f, 0x63694d00, 0x6f736f72, 0x28207466, 0x48202952, 0x204c534c,
0x64616853, 0x43207265, 0x69706d6f, 0x2072656c, 0x39312e39, 0x3934392e,
0x3131322e, 0xabab0031, 0x0200001f, 0x80000000, 0xb0030000, 0x0200001f,
0x80000000, 0x900f0000, 0x0200001f, 0x80000000, 0x900f0001, 0x0200001f,
0x90000000, 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x03000002,
0x80030000, 0xb0e40000, 0xa0e40004, 0x03000002, 0x80030001, 0xb0e40000,
0xa01b0004, 0x03000002, 0x80030002, 0xb0e40000, 0xa01b0003, 0x03000042,
0x800f0000, 0x80e40000, 0xa0e40800, 0x03000042, 0x800f0001, 0x80e40001,
0xa0e40800, 0x03000042, 0x800f0002, 0x80e40002, 0xa0e40800, 0x03000042,
0x800f0003, 0xb0e40000, 0xa0e40800, 0x04000004, 0x80010000, 0x80000000,
0xa0000002, 0xa0550002, 0x04000004, 0x80010001, 0x80000001, 0xa0000002,
0xa0550002, 0x04000004, 0x80010002, 0x80000002, 0xa0000002, 0xa0550002,
0x04000004, 0x80010003, 0x80000003, 0xa0000002, 0xa0550002, 0x03000042,
0x800f0000, 0x80e40000, 0xa0e40801, 0x03000042, 0x800f0001, 0x80e40001,
0xa0e40801, 0x03000042, 0x800f0002, 0x80e40002, 0xa0e40801, 0x03000042,
0x800f0003, 0x80e40003, 0xa0e40801, 0x03000005, 0x80030004, 0xb0e40000,
0xa0e40003, 0x02000013, 0x80030004, 0x80e40004, 0x04000012, 0x800f0005,
0x80000004, 0x80e40001, 0x80e40000, 0x04000012, 0x800f0000, 0x80000004,
0x80e40002, 0x80e40003, 0x04000012, 0x800f0001, 0x80550004, 0x80e40005,
0x80e40000, 0x02000001, 0x800f0000, 0x90e40001, 0x04000004, 0x800f0000,
0x80e40001, 0x80e40000, 0x90e40000, 0x02000001, 0x800f0800, 0x80e40000,
0x0000ffff
};
// A shader that doesn't look up colors from a palette. ---------------------
// Can be used for RGB textures.
#if HLSL_SOURCE_CODE
sampler2D Image : register(s0);
float4 main (float2 texCoord : TEXCOORD0, float4 Flash : COLOR0, float4 InvFlash : COLOR1) : COLOR
{
float4 index = tex2D (Image, texCoord);
return Flash + index * InvFlash;
}
#elif SHADER_ASSEMBLY_CODE
//
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
//
// fxc plain.ps /Tps_1_1 /LD /VnPlainShaderDef /Fhplain.h
//
//
// Parameters:
//
// sampler2D Image;
//
//
// Registers:
//
// Name Reg Size
// ------------ ----- ----
// Image s0 1
//
ps_1_1
tex t0
mad r0, t0, v1, v0
// approximately 2 instruction slots used (1 texture, 1 arithmetic)
#endif
const DWORD PlainShaderDef[] =
{
0xffff0101, 0x0022fffe, 0x42415443, 0x0000001c, 0x0000004f, 0xffff0101,
0x00000001, 0x0000001c, 0x00000100, 0x00000048, 0x00000030, 0x00000003,
0x00000001, 0x00000038, 0x00000000, 0x67616d49, 0xabab0065, 0x000c0004,
0x00010001, 0x00000001, 0x00000000, 0x315f7370, 0x4d00315f, 0x6f726369,
0x74666f73, 0x29522820, 0x44334420, 0x53203958, 0x65646168, 0x6f432072,
0x6c69706d, 0x39207265, 0x2e35312e, 0x2e393737, 0x30303030, 0xababab00,
0x00000042, 0xb00f0000, 0x00000004, 0x800f0000, 0xb0e40000, 0x90e40001,
0x90e40000, 0x0000ffff
};
// A shader that inverts the source's colors --------------------------------
#if HLSL_SOURCE_CODE
sampler2D Image : register(s0);
float4 White : register(c6); // Preloaded with (1,1,1,0)
float4 main (float2 texCoord : TEXCOORD0, float4 Flash : COLOR0, float4 InvFlash : COLOR1) : COLOR
{
float4 rgb = tex2D (Image, texCoord);
rgb.xyz = White.xyz - rgb.xyz;
return Flash + rgb * InvFlash;
}
#elif SHADER_ASSEMBLY_CODE
//
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
//
// fxc plain.ps /Tps_1_1 /LD /VnInvPlainShaderDef /Fhinvplain.h
//
//
// Parameters:
//
// sampler2D Image;
// float4 White;
//
//
// Registers:
//
// Name Reg Size
// ------------ ----- ----
// White c6 1
// Image s0 1
//
ps_1_1
tex t0
add t0.xyz, -t0, c6
mad r0, t0, v1, v0
// approximately 3 instruction slots used (1 texture, 2 arithmetic)
#endif
const DWORD InvPlainShaderDef[] =
{
0xffff0101, 0x002dfffe, 0x42415443, 0x0000001c, 0x0000007b, 0xffff0101,
0x00000002, 0x0000001c, 0x00000100, 0x00000074, 0x00000044, 0x00000003,
0x00000001, 0x0000004c, 0x00000000, 0x0000005c, 0x00060002, 0x00020001,
0x00000064, 0x00000000, 0x67616d49, 0xabab0065, 0x000c0004, 0x00010001,
0x00000001, 0x00000000, 0x74696857, 0xabab0065, 0x00030001, 0x00040001,
0x00000001, 0x00000000, 0x315f7370, 0x4d00315f, 0x6f726369, 0x74666f73,
0x29522820, 0x44334420, 0x53203958, 0x65646168, 0x6f432072, 0x6c69706d,
0x39207265, 0x2e35312e, 0x2e393737, 0x30303030, 0xababab00, 0x00000042,
0xb00f0000, 0x00000002, 0xb0070000, 0xb1e40000, 0xa0e40006, 0x00000004,
0x800f0000, 0xb0e40000, 0x90e40001, 0x90e40000, 0x0000ffff
};
// A shader that copies the red component to the alpha component ------------
#if HLSL_SOURCE_CODE
sampler2D Image : register(s0);
float4 main (float2 texCoord : TEXCOORD0, float4 Flash : COLOR0, float4 InvFlash : COLOR1) : COLOR
{
float4 color = tex2D (Image, texCoord);
color.a = color.r;
return Flash + color * InvFlash;
}
#elif SHADER_ASSEMBLY_CODE
//
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
//
// fxc redtoalpha.ps /Tps_1_4 /LD /VnRedToAlphaDef /Fhredtoalpha.h
//
//
// Parameters:
//
// sampler2D Image;
//
//
// Registers:
//
// Name Reg Size
// ------------ ----- ----
// Image s0 1
//
ps_1_4
texld r0, t0
mad r1.xyz, r0, v1, v0
+ mad r1.w, r0.x, v1.w, v0.w
mov r0, r1
// approximately 3 instruction slots used (1 texture, 2 arithmetic)
#endif
const DWORD RedToAlphaDef[] =
{
0xffff0104, 0x0022fffe, 0x42415443, 0x0000001c, 0x0000004f, 0xffff0104,
0x00000001, 0x0000001c, 0x00000100, 0x00000048, 0x00000030, 0x00000003,
0x00000001, 0x00000038, 0x00000000, 0x67616d49, 0xabab0065, 0x000c0004,
0x00010001, 0x00000001, 0x00000000, 0x315f7370, 0x4d00345f, 0x6f726369,
0x74666f73, 0x29522820, 0x44334420, 0x53203958, 0x65646168, 0x6f432072,
0x6c69706d, 0x39207265, 0x2e35312e, 0x2e393737, 0x30303030, 0xababab00,
0x00000042, 0x800f0000, 0xb0e40000, 0x00000004, 0x80070001, 0x80e40000,
0x90e40001, 0x90e40000, 0x40000004, 0x80080001, 0x80000000, 0x90ff0001,
0x90ff0000, 0x00000001, 0x800f0000, 0x80e40001, 0x0000ffff
};
// A shader that just returns the first color component from the vertex -----
#if HLSL_SOURCE_CODE
float4 main (float4 color : COLOR0) : COLOR
{
return color;
}
#elif SHADER_ASSEMBLY_CODE
//
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
//
// fxc coloronlyshader.ps /Tps_1_1 /LD /VnColorOnlyDef /Fhcoloronly.h
//
ps_1_1
mov r0, v0
// approximately 1 instruction slot used
#endif
const DWORD ColorOnlyDef[] =
{
0xffff0101, 0x0017fffe, 0x42415443, 0x0000001c, 0x00000023, 0xffff0101,
0x00000000, 0x00000000, 0x00000100, 0x0000001c, 0x315f7370, 0x4d00315f,
0x6f726369, 0x74666f73, 0x29522820, 0x44334420, 0x53203958, 0x65646168,
0x6f432072, 0x6c69706d, 0x39207265, 0x2e35312e, 0x2e393737, 0x30303030,
0xababab00, 0x00000001, 0x800f0000, 0x90e40000, 0x0000ffff
};
// A shader that just corrects gamma for windowed mode ----------------------
#if HLSL_SOURCE_CODE
sampler2D Image : register(s0);
float4 Gamma : register(c7);
float4 main (float2 texCoord : TEXCOORD0) : COLOR
{
float4 color = tex2D (Image, texCoord);
color.xyz = pow(color.xyz, Gamma.xyz);
return color;
}
#elif SHADER_ASSEMBLY_CODE
//
// Generated by Microsoft (R) HLSL Shader Compiler 9.19.949.2111
//
// fxc gammafixer.ps /Tps_2_0 /VnGammaFixerDef /Fhgammafixer.h
//
//
// Parameters:
//
// float4 Gamma;
// sampler2D Image;
//
//
// Registers:
//
// Name Reg Size
// ------------ ----- ----
// Gamma c7 1
// Image s0 1
//
ps_2_0
dcl t0.xy
dcl_2d s0
texld r0, t0, s0
log r1.x, r0.x
log r1.y, r0.y
log r1.z, r0.z
mul r1.xyz, r1, c7
exp r0.x, r1.x
exp r0.y, r1.y
exp r0.z, r1.z
mov oC0, r0
// approximately 9 instruction slots used (1 texture, 8 arithmetic)
#endif
const DWORD GammaFixerDef[] =
{
0xffff0200, 0x002cfffe, 0x42415443, 0x0000001c, 0x0000007b, 0xffff0200,
0x00000002, 0x0000001c, 0x20000100, 0x00000074, 0x00000044, 0x00070002,
0x001e0001, 0x0000004c, 0x00000000, 0x0000005c, 0x00000003, 0x00020001,
0x00000064, 0x00000000, 0x6d6d6147, 0xabab0061, 0x00030001, 0x00040001,
0x00000001, 0x00000000, 0x67616d49, 0xabab0065, 0x000c0004, 0x00010001,
0x00000001, 0x00000000, 0x325f7370, 0x4d00305f, 0x6f726369, 0x74666f73,
0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970,
0x2e392072, 0x392e3931, 0x322e3934, 0x00313131, 0x0200001f, 0x80000000,
0xb0030000, 0x0200001f, 0x90000000, 0xa00f0800, 0x03000042, 0x800f0000,
0xb0e40000, 0xa0e40800, 0x0200000f, 0x80010001, 0x80000000, 0x0200000f,
0x80020001, 0x80550000, 0x0200000f, 0x80040001, 0x80aa0000, 0x03000005,
0x80070001, 0x80e40001, 0xa0e40007, 0x0200000e, 0x80010000, 0x80000001,
0x0200000e, 0x80020000, 0x80550001, 0x0200000e, 0x80040000, 0x80aa0001,
0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff
};
// The shader used by the burn effect screen wipe ---------------------------
#if HLSL_SOURCE_CODE
sampler2D NewScreen : register(s0);
sampler2D Burn : register(s1);
float4 main (float2 coord[2] : TEXCOORD0) : COLOR
{
float4 color = tex2D(NewScreen, coord[0]);
float4 alpha = tex2D(Burn, coord[1]);
color.a = alpha.r * 2;
return color;
}
#elif SHADER_ASSEMBLY_CODE
//
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
//
// fxc burn.ps /Tps_1_4 /VnBurnShaderDef /Fhburn.h /LD
//
//
// Parameters:
//
// sampler2D Burn;
// sampler2D NewScreen;
//
//
// Registers:
//
// Name Reg Size
// ------------ ----- ----
// NewScreen s0 1
// Burn s1 1
//
ps_1_4
texld r0, t0
texld r1, t1
add r0.w, r1.x, r1.x
+ mov r0.xyz, r0
// approximately 3 instruction slots used (2 texture, 1 arithmetic)
#endif
const DWORD BurnShaderDef[] =
{
0xffff0104, 0x0029fffe, 0x42415443, 0x0000001c, 0x0000006d, 0xffff0104,
0x00000002, 0x0000001c, 0x00000100, 0x00000066, 0x00000044, 0x00010003,
0x00000001, 0x0000004c, 0x00000000, 0x0000005c, 0x00000003, 0x00000001,
0x0000004c, 0x00000000, 0x6e727542, 0xababab00, 0x000c0004, 0x00010001,
0x00000001, 0x00000000, 0x5377654e, 0x65657263, 0x7370006e, 0x345f315f,
0x63694d00, 0x6f736f72, 0x28207466, 0x44202952, 0x39584433, 0x61685320,
0x20726564, 0x706d6f43, 0x72656c69, 0x312e3920, 0x37372e35, 0x30302e39,
0xab003030, 0x00000042, 0x800f0000, 0xb0e40000, 0x00000042, 0x800f0001,
0xb0e40001, 0x00000002, 0x80080000, 0x80000001, 0x80000001, 0x40000001,
0x80070000, 0x80e40000, 0x0000ffff
};

View File

@ -164,7 +164,7 @@ bool D3DFB::WipeStartScreen(int type)
// Create another texture to copy the final wipe screen to so
// we can still gamma correct the wipe. Since this is just for
// gamma correction, it's okay to fail (though not desirable.)
if (PixelDoubling || (GammaFixerShader != NULL && Windowed))
if (PixelDoubling || (Shaders[SHADER_GammaCorrection] != NULL && Windowed))
{
if (SUCCEEDED(TempRenderTexture->GetSurfaceLevel(0, &tsurf)))
{
@ -384,7 +384,7 @@ bool D3DFB::Wiper_Crossfade::Run(int ticks, D3DFB *fb)
fb->D3DDevice->SetFVF(D3DFVF_FBVERTEX);
fb->SetTexture(0, fb->FinalWipeScreen);
fb->SetAlphaBlend(D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
fb->SetPixelShader(fb->PlainShader);
fb->SetPixelShader(fb->Shaders[SHADER_NormalColor]);
fb->D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX));
return Clock >= 32;
@ -442,7 +442,7 @@ bool D3DFB::Wiper_Melt::Run(int ticks, D3DFB *fb)
fb->D3DDevice->SetFVF(D3DFVF_FBVERTEX);
fb->SetTexture(0, fb->FinalWipeScreen);
fb->SetAlphaBlend(D3DBLENDOP(0));
fb->SetPixelShader(fb->PlainShader);
fb->SetPixelShader(fb->Shaders[SHADER_NormalColor]);
fb->D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX));
int i, dy;
@ -504,7 +504,7 @@ D3DFB::Wiper_Burn::Wiper_Burn(D3DFB *fb)
Density = 4;
BurnTime = 0;
memset(BurnArray, 0, sizeof(BurnArray));
if (fb->BurnShader == NULL || FAILED(fb->D3DDevice->CreateTexture(WIDTH, HEIGHT, 1,
if (fb->Shaders[SHADER_BurnWipe] == NULL || FAILED(fb->D3DDevice->CreateTexture(WIDTH, HEIGHT, 1,
D3DUSAGE_DYNAMIC, D3DFMT_L8, D3DPOOL_DEFAULT, &BurnTexture, NULL)))
{
BurnTexture = NULL;
@ -593,7 +593,7 @@ bool D3DFB::Wiper_Burn::Run(int ticks, D3DFB *fb)
fb->SetTexture(0, fb->FinalWipeScreen);
fb->SetTexture(1, BurnTexture);
fb->SetAlphaBlend(D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
fb->SetPixelShader(fb->BurnShader);
fb->SetPixelShader(fb->Shaders[SHADER_BurnWipe]);
fb->D3DDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
if (fb->SM14)
{

View File

@ -226,6 +226,7 @@ public:
bool Lock (bool buffered);
void Unlock ();
void Update ();
void Flip ();
PalEntry *GetPalette ();
void GetFlashedPalette (PalEntry palette[256]);
void UpdatePalette ();
@ -244,6 +245,7 @@ public:
void ReleaseScreenshotBuffer();
void SetBlendingRect (int x1, int y1, int x2, int y2);
bool Begin2D (bool copy3d);
void DrawBlendingRect ();
FNativeTexture *CreateTexture (FTexture *gametex, bool wrapping);
FNativePalette *CreatePalette (FRemapTable *remap);
void STACK_ARGS DrawTextureV (FTexture *img, int x, int y, uint32 tag, va_list tags);
@ -290,9 +292,48 @@ private:
PackingTexture *Texture;
};
enum
{
PSCONST_PaletteMod = 2,
PSCONST_Weights = 6,
PSCONST_Gamma = 7,
};
enum
{
SHADER_NormalColor,
SHADER_NormalColorPal,
SHADER_NormalColorInv,
SHADER_NormalColorPalInv,
SHADER_RedToAlpha,
SHADER_RedToAlphaInv,
SHADER_VertexColor,
SHADER_SpecialColormap,
SHADER_SpecialColormapPal,
SHADER_InGameColormap,
SHADER_InGameColormapDesat,
SHADER_InGameColormapInv,
SHADER_InGameColormapInvDesat,
SHADER_InGameColormapPal,
SHADER_InGameColormapPalDesat,
SHADER_InGameColormapPalInv,
SHADER_InGameColormapPalInvDesat,
SHADER_BurnWipe,
SHADER_GammaCorrection,
NUM_SHADERS
};
static const char *const ShaderNames[NUM_SHADERS];
void SetInitialState();
bool CreateResources();
void ReleaseResources();
bool LoadShaders();
void CreateBlockSurfaces();
bool CreateFBTexture();
bool CreatePaletteTexture();
bool CreateGrayPaletteTexture();
@ -365,6 +406,7 @@ private:
bool SM14;
bool GatheringWipeScreen;
bool AALines;
BYTE BlockNum;
D3DPal *Palettes;
D3DTex *Textures;
PackingTexture *Packs;
@ -386,13 +428,9 @@ private:
int QuadBatchPos;
enum { BATCH_None, BATCH_Quads, BATCH_Lines } BatchType;
IDirect3DPixelShader9 *PalTexShader, *PalTexBilinearShader, *InvPalTexShader;
IDirect3DPixelShader9 *PlainShader, *InvPlainShader;
IDirect3DPixelShader9 *RedToAlphaShader;
IDirect3DPixelShader9 *ColorOnlyShader;
IDirect3DPixelShader9 *GammaFixerShader;
IDirect3DPixelShader9 *BurnShader;
IDirect3DPixelShader9 *Shaders[NUM_SHADERS];
IDirect3DSurface9 *BlockSurface[2];
IDirect3DSurface9 *OldRenderTarget;
IDirect3DTexture9 *InitialWipeScreen, *FinalWipeScreen;

View File

@ -260,7 +260,7 @@ ACTOR Actor native //: Thinker
action native A_ChangeVelocity(float x = 0, float y = 0, float z = 0, int flags = 0);
action native A_SetArg(int pos, int value);
action native A_SetUserVar(int pos, int value);
action native A_SetSpecial(int spec, int arg0, int arg1, int arg2, int arg3, int arg4);
action native A_SetSpecial(int spec, int arg0 = 0, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0);
States
{

View File

@ -63,9 +63,15 @@ const int MRF_UNDOBYDEATH = 512;
const int MRF_UNDOBYDEATHFORCED = 1024;
const int MRF_UNDOBYDEATHSAVES = 2048;
// Flags for A_RailAttack and A_CustomRailgun
const int RGF_SILENT = 1;
const int RGF_NOPIERCING = 2;
// Flags for A_Mushroom
const int MSF_Standard = 0;
const int MSF_Classic = 1;
// Activation flags
enum
{
THINGSPEC_Default = 0,
@ -77,7 +83,6 @@ enum
THINGSPEC_ClearSpecial = 32,
};
// constants for A_PlaySound
enum
{

View File

@ -1,4 +1,4 @@
ACTOR Dog 888
ACTOR MBFHelperDog 888
{
Game Doom
Health 500

View File

@ -1034,6 +1034,7 @@ ACTOR PhoenixRodPowered : PhoenixRod native
{
Game Heretic
+WEAPON.POWERED_UP
+WEAPON.MELEEWEAPON
Weapon.SisterWeapon "PhoenixRod"
Weapon.AmmoGive 0

View File

@ -177,6 +177,7 @@ ACTOR ExplosiveBarrel2 94
Height 32
ConversationID 204, -1, -1
+SOLID +SHOOTABLE +NOBLOOD +OLDRADIUSDMG
DeathSound "world/barrelx"
+INCOMBAT
States
{

View File

@ -414,7 +414,7 @@ StateMap
DoomUnusedStates, TNT, 1, // [MBF] S_TNT1 967
Grenade, Grenade, 1, // [MBF] S_GRENADE 968
Grenade, Detonate, 3, // [MBF] S_DETONATE - S_DETONATE3 969-971
Dog, Spawn, 27, // [MBF] S_DOGS_STND - S_DOGS_RAISE6 972-998
MBFHelperDog, Spawn, 27, // [MBF] S_DOGS_STND - S_DOGS_RAISE6 972-998
BFG9000, OldFire, 43, // [MBF] S_OLDBFG1 - S_OLDBFG43 999-1041
PlasmaBall1, Spawn, 7, // [MBF] S_PLS1BALL - S_PLS1EXP5 1042-1048
PlasmaBall2, Spawn, 5, // [MBF] S_PLS2BALL - S_PLS2BALLX3 1049-1053
@ -681,7 +681,7 @@ InfoNames
PointPusher,
PointPuller,
// MBF additional actors:
Dog,
MBFHelperDog,
PlasmaBall1,
PlasmaBall2,
EvilSceptre,

View File

@ -0,0 +1,10 @@
cd sm14
call build.bat
cd ..\sm20
call build.bat
cd ..\sm30
call build.bat
cd ..

View File

@ -0,0 +1,118 @@
sampler2D Image : register(s0);
sampler1D Palette : register(s1);
float4 PaletteMod : register(c2);
float4 Weights : register(c6); // RGB->Gray weighting { 77/256.0, 143/256.0, 37/256.0, 1 }
float4 Gamma : register(c7);
float4 TextureLookup(float2 tex_coord)
{
#if PALTEX
float index = tex2D(Image, tex_coord).x;
index = index * PaletteMod.x + PaletteMod.y;
return tex1D(Palette, index);
#else
return tex2D(Image, tex_coord);
#endif
}
float4 Invert(float4 rgb)
{
#if INVERT
rgb.rgb = Weights.www - rgb.xyz;
#endif
return rgb;
}
float Grayscale(float4 rgb)
{
return dot(rgb.rgb, Weights.rgb);
}
float4 SampleTexture(float2 tex_coord)
{
return Invert(TextureLookup(tex_coord));
}
// Normal color calculation for most drawing modes.
float4 NormalColor(float2 tex_coord : TEXCOORD0, float4 Flash : COLOR0, float4 InvFlash : COLOR1) : COLOR
{
return Flash + SampleTexture(tex_coord) * InvFlash;
}
// Copy the red channel to the alpha channel. Pays no attention to palettes.
float4 RedToAlpha(float2 tex_coord : TEXCOORD0, float4 Flash : COLOR0, float4 InvFlash : COLOR1) : COLOR
{
float4 color = Invert(tex2D(Image, tex_coord));
color.a = color.r;
return Flash + color * InvFlash;
}
// Just return the value of c0.
float4 VertexColor(float4 color : COLOR0) : COLOR
{
return color;
}
// Emulate one of the special colormaps. (Invulnerability, gold, etc.)
float4 SpecialColormap(float2 tex_coord : TEXCOORD0, float4 start : COLOR0, float4 end : COLOR1) : COLOR
{
float4 color = SampleTexture(tex_coord);
float4 range = end - start;
// We can't store values greater than 1.0 in a color register, so we multiply
// the final result by 2 and expect the caller to divide the start and end by 2.
color.rgb = 2 * (start + Grayscale(color) * range);
// Duplicate alpha semantics of NormalColor.
color.a = start.a + color.a * end.a;
return color;
}
// In-game colormap effect: fade to a particular color and multiply by another, with
// optional desaturation of the original color. Desaturation is packed into color.a.
// Fade level is packed int fade.a. Fade.rgb has been premultiplied by alpha.
float4 InGameColormap(float2 tex_coord : TEXCOORD0, float4 color : COLOR0, float4 fade : COLOR1) : COLOR
{
float4 rgb = SampleTexture(tex_coord);
// Desaturate
#if DESAT
float3 intensity;
float invdesat;
intensity.rgb = Grayscale(rgb) * color.a;
invdesat = Weights.w - color.a;
rgb.rgb = intensity + rgb * invdesat;
#endif
// Fade
rgb.rgb = rgb.rgb * fade.aaa + fade.rgb;
// Shade
rgb.rgb = rgb.rgb * color.rgb;
return rgb;
}
// Windowed gamma correction.
float4 GammaCorrection(float2 tex_coord : TEXCOORD0) : COLOR
{
float4 color = tex2D(Image, tex_coord);
color.rgb = pow(color.rgb, Gamma.rgb);
return color;
}
// The burn wipe effect.
sampler2D NewScreen : register(s0);
sampler2D Burn : register(s1);
float4 BurnWipe(float2 coord[2] : TEXCOORD0) : COLOR
{
float4 color = tex2D(NewScreen, coord[0]);
float4 alpha = tex2D(Burn, coord[1]);
color.a = alpha.r * 2;
return color;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More