mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-01-18 15:42:34 +00:00
- Sync with trunk.
SVN r1872 (scripting)
This commit is contained in:
commit
1a442742f7
167 changed files with 1887 additions and 2342 deletions
100
docs/rh-log.txt
100
docs/rh-log.txt
|
@ -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. :-(
|
||||
|
|
|
@ -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
|
||||
|
|
13
src/actor.h
13
src/actor.h
|
@ -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
|
||||
|
||||
|
|
|
@ -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" },
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -778,7 +778,6 @@ CCMD(linetarget)
|
|||
linetarget->GetClass()->TypeName.GetChars(),
|
||||
linetarget->health,
|
||||
linetarget->SpawnHealth());
|
||||
PrintMiscActorInfo(linetarget);
|
||||
}
|
||||
else Printf("No target found\n");
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -213,7 +213,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DragonFlight)
|
|||
}
|
||||
else
|
||||
{
|
||||
P_LookForPlayers (self, true);
|
||||
P_LookForPlayers (self, true, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -73,7 +73,8 @@ struct F3DFloor
|
|||
const FTextureID * texture;
|
||||
const fixed_t * texheight;
|
||||
sector_t * model;
|
||||
bool isceiling;
|
||||
int isceiling;
|
||||
int vindex;
|
||||
};
|
||||
|
||||
planeref bottom;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -232,7 +232,7 @@ bool EV_DoCeiling (DCeiling::ECeiling type, line_t *line,
|
|||
sec = §ors[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;
|
||||
|
|
|
@ -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 = §ors[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))
|
||||
|
|
505
src/p_enemy.cpp
505
src/p_enemy.cpp
|
@ -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, ¶ms))
|
||||
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, ¶ms))
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 ***
|
|
@ -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 = §ors[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 = §ors[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 = §ors[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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -205,7 +205,7 @@ bool EV_DoPillar (DPillar::EPillar type, int tag, fixed_t speed, fixed_t height,
|
|||
{
|
||||
sector_t *sec = §ors[secnum];
|
||||
|
||||
if (sec->floordata || sec->ceilingdata)
|
||||
if (sec->PlaneMoving(sector_t::floor) || sec->PlaneMoving(sector_t::ceiling))
|
||||
continue;
|
||||
|
||||
fixed_t flor, ceil;
|
||||
|
|
|
@ -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 = §ors[secnum];
|
||||
|
||||
manual_plat:
|
||||
if (sec->floordata)
|
||||
if (sec->PlaneMoving(sector_t::floor))
|
||||
{
|
||||
if (!manual)
|
||||
continue;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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]); }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
217
src/r_things.cpp
217
src/r_things.cpp
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
};
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
ACTOR Dog 888
|
||||
ACTOR MBFHelperDog 888
|
||||
{
|
||||
Game Doom
|
||||
Health 500
|
||||
|
|
|
@ -1034,6 +1034,7 @@ ACTOR PhoenixRodPowered : PhoenixRod native
|
|||
{
|
||||
Game Heretic
|
||||
+WEAPON.POWERED_UP
|
||||
+WEAPON.MELEEWEAPON
|
||||
Weapon.SisterWeapon "PhoenixRod"
|
||||
Weapon.AmmoGive 0
|
||||
|
||||
|
|
|
@ -177,6 +177,7 @@ ACTOR ExplosiveBarrel2 94
|
|||
Height 32
|
||||
ConversationID 204, -1, -1
|
||||
+SOLID +SHOOTABLE +NOBLOOD +OLDRADIUSDMG
|
||||
DeathSound "world/barrelx"
|
||||
+INCOMBAT
|
||||
States
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
10
wadsrc/static/shaders/d3d/build.bat
Normal file
10
wadsrc/static/shaders/d3d/build.bat
Normal file
|
@ -0,0 +1,10 @@
|
|||
cd sm14
|
||||
call build.bat
|
||||
|
||||
cd ..\sm20
|
||||
call build.bat
|
||||
|
||||
cd ..\sm30
|
||||
call build.bat
|
||||
|
||||
cd ..
|
118
wadsrc/static/shaders/d3d/shaders.ps
Normal file
118
wadsrc/static/shaders/d3d/shaders.ps
Normal 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;
|
||||
}
|
BIN
wadsrc/static/shaders/d3d/sm14/BurnWipe.pso
Normal file
BIN
wadsrc/static/shaders/d3d/sm14/BurnWipe.pso
Normal file
Binary file not shown.
BIN
wadsrc/static/shaders/d3d/sm14/InGameColormap.pso
Normal file
BIN
wadsrc/static/shaders/d3d/sm14/InGameColormap.pso
Normal file
Binary file not shown.
BIN
wadsrc/static/shaders/d3d/sm14/InGameColormapDesat.pso
Normal file
BIN
wadsrc/static/shaders/d3d/sm14/InGameColormapDesat.pso
Normal file
Binary file not shown.
BIN
wadsrc/static/shaders/d3d/sm14/InGameColormapInv.pso
Normal file
BIN
wadsrc/static/shaders/d3d/sm14/InGameColormapInv.pso
Normal file
Binary file not shown.
BIN
wadsrc/static/shaders/d3d/sm14/InGameColormapInvDesat.pso
Normal file
BIN
wadsrc/static/shaders/d3d/sm14/InGameColormapInvDesat.pso
Normal file
Binary file not shown.
BIN
wadsrc/static/shaders/d3d/sm14/InGameColormapPal.pso
Normal file
BIN
wadsrc/static/shaders/d3d/sm14/InGameColormapPal.pso
Normal file
Binary file not shown.
BIN
wadsrc/static/shaders/d3d/sm14/InGameColormapPalDesat.pso
Normal file
BIN
wadsrc/static/shaders/d3d/sm14/InGameColormapPalDesat.pso
Normal file
Binary file not shown.
BIN
wadsrc/static/shaders/d3d/sm14/InGameColormapPalInv.pso
Normal file
BIN
wadsrc/static/shaders/d3d/sm14/InGameColormapPalInv.pso
Normal file
Binary file not shown.
BIN
wadsrc/static/shaders/d3d/sm14/InGameColormapPalInvDesat.pso
Normal file
BIN
wadsrc/static/shaders/d3d/sm14/InGameColormapPalInvDesat.pso
Normal file
Binary file not shown.
BIN
wadsrc/static/shaders/d3d/sm14/NormalColor.pso
Normal file
BIN
wadsrc/static/shaders/d3d/sm14/NormalColor.pso
Normal file
Binary file not shown.
BIN
wadsrc/static/shaders/d3d/sm14/NormalColorInv.pso
Normal file
BIN
wadsrc/static/shaders/d3d/sm14/NormalColorInv.pso
Normal file
Binary file not shown.
BIN
wadsrc/static/shaders/d3d/sm14/NormalColorPal.pso
Normal file
BIN
wadsrc/static/shaders/d3d/sm14/NormalColorPal.pso
Normal file
Binary file not shown.
BIN
wadsrc/static/shaders/d3d/sm14/NormalColorPalInv.pso
Normal file
BIN
wadsrc/static/shaders/d3d/sm14/NormalColorPalInv.pso
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue