Update to ZDoom r1669:

- added a compatibility option to restore the original Heretic bug where
  a Minotaur couldn't spawn floor flames when standing in water having its
  feet clipped.
- added vid_vsync to display options.
- fixed: Animations of type 'Range' must be disabled if the textures don't
  come from the same definition unit (i.e both containing file and use type
  are identical.)
- changed: Item pushing is now only done once per P_XYMovement call.
- Increased the push factor of Heretic's pod to 0.5 so that its behavior
  more closely matches the original which depended on several bugs in the engine.
- Removed damage thrust clamping in P_DamageMobj and changed the thrust calculation
  to use floats to prevent overflows. The prevention of the overflows was the
  only reason the clamping was done.
- Added Raven's dagger-like vector sprite for the player to the automap code.
- Changed wad namespacing so that wads with a missing end marker will be
  loaded as if they had one more lump with that end marker. This matches the
  behaviour of previously released ZDooms. (The warning is still present, so
  there's no excuse to release more wads like this.)
- Moved Raw Input processing into a seperate method of FInputDevice so that
  all the devices can share the same setup code.
- Removed F16 mapping for SDL, because I guess it's not present in SDL 1.2.
- Added Gez's Skulltag feature patch, including:
    * BUMPSPECIAL flag: actors with this flag will run their special if collided on by a player
    * WEAPON.NOAUTOAIM flag, though it is restricted to attacks that spawn a missile (it will 
	  not affect autoaim settings for a hitscan or railgun, and that's deliberate)
    * A_FireSTGrenade codepointer, extended to be parameterizable
    * The grenade (as the default actor for A_FireSTGrenade)
    * Protective armors à la RedArmor: they work with a DamageFactor; for example to 
	  recreate the RedArmor from Skulltag, copy its code from skulltag.pk3 but remove 
	  the "native" keyword and add DamageFactor "Fire" 0.1 to its properties.
- Fixed: I_ShutdownInput must NULL all pointers because it can be called twice
  if an ENDOOM screen is displayed.
- Fixed: R_DrawSkyStriped used frontyScale without initializing it first.
- Fixed: P_LineAttack may not check the puff actor for MF6_FORCEPAIN because
  it's not necessarily spawned yet. 
- Fixed: FWeaponSlots::PickNext/PrevWeapon must be limited to one iteration
  through the weapon slots. Otherwise they will hang if there's no weapons
  in a player's inventory.
- Added Line_SetTextureScale.
- Fixed: sv_smartaim 3 treated the player like a shootable decoration.
- Added A_CheckIfInTargetLOS
- Removed redundant A_CheckIfTargetInSight.
- Fixed: The initial play of a GME song always started track 0.
- Fixed: The RAWINPUT buffer that GetRawInputData() fills in is 40 bytes on
  Win32 but 48 bytes on Win64, so Raw Mouse on x64 builds was getting random
  data off the stack because I also interpreted the error return incorrectly.
- added parameter to A_FadeOut so that removing the actor can be made an option.


git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@344 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
Christoph Oelckers 2009-06-14 18:05:00 +00:00
parent 63e67d4a29
commit 169965ea9f
43 changed files with 672 additions and 277 deletions

View file

@ -1,4 +1,61 @@
June 7, 2009 (Changes by Graf Zahl) June 14, 2009 (Changes by Graf Zahl)
- added a compatibility option to restore the original Heretic bug where
a Minotaur couldn't spawn floor flames when standing in water having its
feet clipped.
- added vid_vsync to display options.
- fixed: Animations of type 'Range' must be disabled if the textures don't
come from the same definition unit (i.e both containing file and use type
are identical.)
- changed: Item pushing is now only done once per P_XYMovement call.
- Increased the push factor of Heretic's pod to 0.5 so that its behavior
more closely matches the original which depended on several bugs in the engine.
- Removed damage thrust clamping in P_DamageMobj and changed the thrust calculation
to use floats to prevent overflows. The prevention of the overflows was the
only reason the clamping was done.
- Added Raven's dagger-like vector sprite for the player to the automap code.
June 10, 2009
- Changed wad namespacing so that wads with a missing end marker will be
loaded as if they had one more lump with that end marker. This matches the
behaviour of previously released ZDooms. (The warning is still present, so
there's no excuse to release more wads like this.)
- Moved Raw Input processing into a seperate method of FInputDevice so that
all the devices can share the same setup code.
June 9, 2009
- Removed F16 mapping for SDL, because I guess it's not present in SDL 1.2.
June 9, 2009 (Changes by Graf Zahl)
- Added Gez's Skulltag feature patch, including:
* BUMPSPECIAL flag: actors with this flag will run their special if collided on by a player
* WEAPON.NOAUTOAIM flag, though it is restricted to attacks that spawn a missile (it will
not affect autoaim settings for a hitscan or railgun, and that's deliberate)
* A_FireSTGrenade codepointer, extended to be parameterizable
* The grenade (as the default actor for A_FireSTGrenade)
* Protective armors à la RedArmor: they work with a DamageFactor; for example to
recreate the RedArmor from Skulltag, copy its code from skulltag.pk3 but remove
the "native" keyword and add DamageFactor "Fire" 0.1 to its properties.
- Fixed: I_ShutdownInput must NULL all pointers because it can be called twice
if an ENDOOM screen is displayed.
- Fixed: R_DrawSkyStriped used frontyScale without initializing it first.
- Fixed: P_LineAttack may not check the puff actor for MF6_FORCEPAIN because
it's not necessarily spawned yet.
- Fixed: FWeaponSlots::PickNext/PrevWeapon must be limited to one iteration
through the weapon slots. Otherwise they will hang if there's no weapons
in a player's inventory.
- Added Line_SetTextureScale.
- Fixed: sv_smartaim 3 treated the player like a shootable decoration.
- Added A_CheckIfInTargetLOS
- Removed redundant A_CheckIfTargetInSight.
June 8, 2009
- Fixed: The initial play of a GME song always started track 0.
- Fixed: The RAWINPUT buffer that GetRawInputData() fills in is 40 bytes on
Win32 but 48 bytes on Win64, so Raw Mouse on x64 builds was getting random
data off the stack because I also interpreted the error return incorrectly.
June 7, 2009 (Changes by Graf Zahl)
- added parameter to A_FadeOut so that removing the actor can be made an option.
- added PERSISTENTPOWER and TRANSFERPOINTERS submissions by Gez. - added PERSISTENTPOWER and TRANSFERPOINTERS submissions by Gez.
- fixed FORCEPAIN logic. - fixed FORCEPAIN logic.
- added Gez's infinite ammo powerup and random spawner fix patches. - added Gez's infinite ammo powerup and random spawner fix patches.

View file

@ -310,6 +310,7 @@ enum
MF6_MTHRUSPECIES = 0x00000004, // Missile passes through actors of its shooter's species. MF6_MTHRUSPECIES = 0x00000004, // Missile passes through actors of its shooter's species.
MF6_FORCEPAIN = 0x00000008, // forces target into painstate (unless it has the NOPAIN flag) MF6_FORCEPAIN = 0x00000008, // forces target into painstate (unless it has the NOPAIN flag)
MF6_NOFEAR = 0x00000010, // Not scared of frightening players MF6_NOFEAR = 0x00000010, // Not scared of frightening players
MF6_BUMPSPECIAL = 0x00000020, // Actor executes its special when being collided (as the ST flag)
// --- mobj.renderflags --- // --- mobj.renderflags ---
@ -740,6 +741,7 @@ public:
fixed_t gravity; // [GRB] Gravity factor fixed_t gravity; // [GRB] Gravity factor
int FastChaseStrafeCount; int FastChaseStrafeCount;
fixed_t pushfactor; fixed_t pushfactor;
int lastpush;
AActor *BlockingMobj; // Actor that blocked the last move AActor *BlockingMobj; // Actor that blocked the last move
line_t *BlockingLine; // Line that blocked the last move line_t *BlockingLine; // Line that blocked the last move

View file

@ -35,6 +35,7 @@
#include "statnums.h" #include "statnums.h"
#include "r_translate.h" #include "r_translate.h"
#include "d_event.h" #include "d_event.h"
#include "gi.h"
#include "m_cheat.h" #include "m_cheat.h"
#include "i_system.h" #include "i_system.h"
@ -251,8 +252,23 @@ mline_t player_arrow[] = {
{ { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>---> { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>--->
{ { -R+3*R/8, 0 }, { -R+R/8, -R/4 } } { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } }
}; };
mline_t player_arrow_raven[] = {
{ { -R+R/4, 0 }, { 0, 0} }, // center line.
{ { -R+R/4, R/8 }, { R, 0} }, // blade
{ { -R+R/4, -R/8 }, { R, 0 } },
{ { -R+R/4, -R/4 }, { -R+R/4, R/4 } }, // crosspiece
{ { -R+R/8, -R/4 }, { -R+R/8, R/4 } },
{ { -R+R/8, -R/4 }, { -R+R/4, -R/4} }, //crosspiece connectors
{ { -R+R/8, R/4 }, { -R+R/4, R/4} },
{ { -R-R/4, R/8 }, { -R-R/4, -R/8 } }, //pommel
{ { -R-R/4, R/8 }, { -R+R/8, R/8 } },
{ { -R-R/4, -R/8}, { -R+R/8, -R/8 } }
};
#undef R #undef R
#define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t)) #define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t))
#define NUMPLYRLINES_RAVEN (sizeof(player_arrow_raven)/sizeof(mline_t))
#define R ((8*PLAYERRADIUS)/7) #define R ((8*PLAYERRADIUS)/7)
mline_t cheat_player_arrow[] = { mline_t cheat_player_arrow[] = {
@ -273,6 +289,7 @@ mline_t cheat_player_arrow[] = {
{ { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } }, { { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } },
{ { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } } { { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } }
}; };
#undef R #undef R
#define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t)) #define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t))
@ -1632,7 +1649,13 @@ void AM_drawPlayers ()
{ {
angle = players[consoleplayer].camera->angle; angle = players[consoleplayer].camera->angle;
} }
if (am_cheat != 0)
if (gameinfo.gametype & GAME_Raven)
{
arrow = player_arrow_raven;
numarrowlines = NUMPLYRLINES_RAVEN;
}
else if (am_cheat != 0)
{ {
arrow = cheat_player_arrow; arrow = cheat_player_arrow;
numarrowlines = NUMCHEATPLYRLINES; numarrowlines = NUMCHEATPLYRLINES;

View file

@ -491,6 +491,7 @@ CVAR (Flag, compat_sectorsounds,compatflags, COMPATF_SECTORSOUNDS);
CVAR (Flag, compat_missileclip, compatflags, COMPATF_MISSILECLIP); CVAR (Flag, compat_missileclip, compatflags, COMPATF_MISSILECLIP);
CVAR (Flag, compat_crossdropoff,compatflags, COMPATF_CROSSDROPOFF); CVAR (Flag, compat_crossdropoff,compatflags, COMPATF_CROSSDROPOFF);
CVAR (Flag, compat_anybossdeath,compatflags, COMPATF_ANYBOSSDEATH); CVAR (Flag, compat_anybossdeath,compatflags, COMPATF_ANYBOSSDEATH);
CVAR (Flag, compat_minotaur, compatflags, COMPATF_MINOTAUR);
//========================================================================== //==========================================================================
// //

View file

@ -271,6 +271,7 @@ enum
COMPATF_MISSILECLIP = 1 << 19, // Use original Doom heights for clipping against projectiles COMPATF_MISSILECLIP = 1 << 19, // Use original Doom heights for clipping against projectiles
COMPATF_CROSSDROPOFF = 1 << 20, // monsters can't be pushed over dropoffs COMPATF_CROSSDROPOFF = 1 << 20, // monsters can't be pushed over dropoffs
COMPATF_ANYBOSSDEATH = 1 << 21, // [GZ] Any monster which calls BOSSDEATH counts for level specials COMPATF_ANYBOSSDEATH = 1 << 21, // [GZ] Any monster which calls BOSSDEATH counts for level specials
COMPATF_MINOTAUR = 1 << 22, // Minotaur's floor flame is exploded immediately when feet are clipped
}; };
// Emulate old bugs for select maps. These are not exposed by a cvar // Emulate old bugs for select maps. These are not exposed by a cvar

View file

@ -361,6 +361,34 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMissile)
P_SpawnPlayerMissile (self, PClass::FindClass("Rocket")); P_SpawnPlayerMissile (self, PClass::FindClass("Rocket"));
} }
//
// A_FireSTGrenade: not exactly backported from ST, but should work the same
//
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireSTGrenade)
{
player_t *player;
ACTION_PARAM_START(1);
ACTION_PARAM_CLASS(grenade, 0);
if (grenade == NULL) return;
if (NULL == (player = self->player))
{
return;
}
AWeapon *weapon = self->player->ReadyWeapon;
if (weapon != NULL)
{
if (!weapon->DepleteAmmo (weapon->bAltFire))
return;
}
// Temporarily raise the pitch to send the grenade slightly upwards
fixed_t SavedPlayerPitch = self->pitch;
self->pitch -= (1152 << FRACBITS);
P_SpawnPlayerMissile(self, grenade);
self->pitch = SavedPlayerPitch;
}
// //
// A_FirePlasma // A_FirePlasma
// //

View file

@ -1337,6 +1337,7 @@ MapFlagHandlers[] =
{ "compat_sectorsounds", MITYPE_COMPATFLAG, COMPATF_SECTORSOUNDS}, { "compat_sectorsounds", MITYPE_COMPATFLAG, COMPATF_SECTORSOUNDS},
{ "compat_missileclip", MITYPE_COMPATFLAG, COMPATF_MISSILECLIP}, { "compat_missileclip", MITYPE_COMPATFLAG, COMPATF_MISSILECLIP},
{ "compat_crossdropoff", MITYPE_COMPATFLAG, COMPATF_CROSSDROPOFF}, { "compat_crossdropoff", MITYPE_COMPATFLAG, COMPATF_CROSSDROPOFF},
{ "compat_minotaur", MITYPE_COMPATFLAG, COMPATF_MINOTAUR},
{ "cd_start_track", MITYPE_EATNEXT, 0, 0 }, { "cd_start_track", MITYPE_EATNEXT, 0, 0 },
{ "cd_end1_track", MITYPE_EATNEXT, 0, 0 }, { "cd_end1_track", MITYPE_EATNEXT, 0, 0 },
{ "cd_end2_track", MITYPE_EATNEXT, 0, 0 }, { "cd_end2_track", MITYPE_EATNEXT, 0, 0 },

View file

@ -379,10 +379,18 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk3)
} }
else else
{ {
mo = P_SpawnMissile (self, self->target, PClass::FindClass("MinotaurFX2")); if (self->floorclip > 0 && (i_compatflags & COMPATF_MINOTAUR))
if (mo != NULL)
{ {
S_Sound (mo, CHAN_WEAPON, "minotaur/attack1", 1, ATTN_NORM); // only play the sound.
S_Sound (self, CHAN_WEAPON, "minotaur/fx2hit", 1, ATTN_NORM);
}
else
{
mo = P_SpawnMissile (self, self->target, PClass::FindClass("MinotaurFX2"));
if (mo != NULL)
{
S_Sound (mo, CHAN_WEAPON, "minotaur/attack1", 1, ATTN_NORM);
}
} }
} }
if (pr_minotauratk3() < 192 && self->special2 == 0) if (pr_minotauratk3() < 192 && self->special2 == 0)

View file

@ -139,6 +139,7 @@ void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
{ {
// The armor has become useless // The armor has become useless
SavePercent = 0; SavePercent = 0;
ArmorType = NAME_None; // Not NAME_BasicArmor.
// Now see if the player has some more armor in their inventory // Now see if the player has some more armor in their inventory
// and use it if so. As in Strife, the best armor is used up first. // and use it if so. As in Strife, the best armor is used up first.
ABasicArmorPickup *best = NULL; ABasicArmorPickup *best = NULL;
@ -162,6 +163,24 @@ void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
} }
damage = newdamage; damage = newdamage;
} }
// Once the armor has absorbed its part of the damage, then apply its damage factor, if any, to the player
if ((damage > 0) && (ArmorType != NAME_None)) // BasicArmor is not going to have any damage factor, so skip it.
{
// This code is taken and adapted from APowerProtection::ModifyDamage().
// The differences include not checking for the NAME_None key (doesn't seem appropriate here),
// not using a default value, and of course the way the damage factor info is obtained.
const fixed_t *pdf = NULL;
DmgFactors *df = PClass::FindClass(ArmorType)->ActorInfo->DamageFactors;
if (df != NULL && df->CountUsed() != 0)
{
pdf = df->CheckKey(damageType);
if (pdf != NULL)
{
damage = newdamage = FixedMul(damage, *pdf);
}
}
}
if (Inventory != NULL) if (Inventory != NULL)
{ {
Inventory->AbsorbDamage (damage, damageType, newdamage); Inventory->AbsorbDamage (damage, damageType, newdamage);

View file

@ -1387,7 +1387,7 @@ IMPLEMENT_CLASS (AHealth)
//=========================================================================== //===========================================================================
// //
// AHealth :: TryPickup // AHealth :: PickupMessage
// //
//=========================================================================== //===========================================================================
const char *AHealth::PickupMessage () const char *AHealth::PickupMessage ()

View file

@ -317,9 +317,10 @@ enum
WIF_POWERED_UP = 0x00000400, // this is a tome-of-power'ed version of its sister WIF_POWERED_UP = 0x00000400, // this is a tome-of-power'ed version of its sister
WIF_AMMO_CHECKBOTH = 0x00000800, // check for both primary and secondary fire before switching it off WIF_AMMO_CHECKBOTH = 0x00000800, // check for both primary and secondary fire before switching it off
WIF_NO_AUTO_SWITCH = 0x00001000, // never switch to this weapon when it's picked up 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 kickba 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_CHEATNOTWEAPON = 1<<27, // Give cheat considers this not a weapon (used by Sigil) WIF_CHEATNOTWEAPON = 0x08000000, // Give cheat considers this not a weapon (used by Sigil)
// Flags used only by bot AI: // Flags used only by bot AI:

View file

@ -974,6 +974,7 @@ static bool FindMostRecentWeapon(player_t *player, int *slot, int *index)
AWeapon *FWeaponSlots::PickNextWeapon(player_t *player) AWeapon *FWeaponSlots::PickNextWeapon(player_t *player)
{ {
int startslot, startindex; int startslot, startindex;
int slotschecked = 0;
if (player->mo == NULL) if (player->mo == NULL)
{ {
@ -997,6 +998,7 @@ AWeapon *FWeaponSlots::PickNextWeapon(player_t *player)
if (++index >= Slots[slot].Size()) if (++index >= Slots[slot].Size())
{ {
index = 0; index = 0;
slotschecked++;
if (++slot >= NUM_WEAPON_SLOTS) if (++slot >= NUM_WEAPON_SLOTS)
{ {
slot = 0; slot = 0;
@ -1009,7 +1011,7 @@ AWeapon *FWeaponSlots::PickNextWeapon(player_t *player)
return weap; return weap;
} }
} }
while (slot != startslot || index != startindex); while ((slot != startslot || index != startindex) && slotschecked < NUM_WEAPON_SLOTS);
} }
return player->ReadyWeapon; return player->ReadyWeapon;
} }
@ -1027,6 +1029,7 @@ AWeapon *FWeaponSlots::PickNextWeapon(player_t *player)
AWeapon *FWeaponSlots::PickPrevWeapon (player_t *player) AWeapon *FWeaponSlots::PickPrevWeapon (player_t *player)
{ {
int startslot, startindex; int startslot, startindex;
int slotschecked = 0;
if (player->mo == NULL) if (player->mo == NULL)
{ {
@ -1049,6 +1052,7 @@ AWeapon *FWeaponSlots::PickPrevWeapon (player_t *player)
{ {
if (--index < 0) if (--index < 0)
{ {
slotschecked++;
if (--slot < 0) if (--slot < 0)
{ {
slot = NUM_WEAPON_SLOTS - 1; slot = NUM_WEAPON_SLOTS - 1;
@ -1062,7 +1066,7 @@ AWeapon *FWeaponSlots::PickPrevWeapon (player_t *player)
return weap; return weap;
} }
} }
while (slot != startslot || index != startindex); while ((slot != startslot || index != startindex) && slotschecked < NUM_WEAPON_SLOTS);
} }
return player->ReadyWeapon; return player->ReadyWeapon;
} }

View file

@ -806,9 +806,8 @@ static int __cdecl dicmp (const void *a, const void *b)
case GLDIT_POLY: break; case GLDIT_POLY: break;
} }
} }
if (lights[0]!=lights[1]) return lights[0]-lights[1];
if (tx[0]!=tx[1]) return tx[0]-tx[1]; if (tx[0]!=tx[1]) return tx[0]-tx[1];
/*if (lights[0]!=lights[1])*/ return lights[0]-lights[1]; return lights[0]-lights[1];
} }

View file

@ -91,6 +91,7 @@ EXTERN_CVAR(Bool, nomonsterinterpolation)
EXTERN_CVAR(Int, showendoom) EXTERN_CVAR(Int, showendoom)
EXTERN_CVAR(Bool, hud_althud) EXTERN_CVAR(Bool, hud_althud)
EXTERN_CVAR(Int, compatmode) EXTERN_CVAR(Int, compatmode)
EXTERN_CVAR (Bool, vid_vsync)
static value_t Renderers[] = { static value_t Renderers[] = {
{ 0.0, "Software" }, { 0.0, "Software" },
@ -538,6 +539,7 @@ static menuitem_t VideoItems[] = {
{ slider, "Gamma correction", {&Gamma}, {0.1f}, {3.0}, {0.1f}, {NULL} }, { slider, "Gamma correction", {&Gamma}, {0.1f}, {3.0}, {0.1f}, {NULL} },
{ slider, "Brightness", {&vid_brightness}, {-0.8f}, {0.8f}, {0.05f}, {NULL} }, { slider, "Brightness", {&vid_brightness}, {-0.8f}, {0.8f}, {0.05f}, {NULL} },
{ slider, "Contrast", {&vid_contrast}, {0.1f}, {3.0}, {0.1f}, {NULL} }, { slider, "Contrast", {&vid_contrast}, {0.1f}, {3.0}, {0.1f}, {NULL} },
{ discrete, "Vertical Sync", {&vid_vsync}, {2.0}, {0.0}, {0.0}, {OnOff} },
{ discretes,"Crosshair", {&crosshair}, {8.0}, {0.0}, {0.0}, {NULL} }, { discretes,"Crosshair", {&crosshair}, {8.0}, {0.0}, {0.0}, {NULL} },
{ discrete, "Column render mode", {&r_columnmethod}, {2.0}, {0.0}, {0.0}, {ColumnMethods} }, { discrete, "Column render mode", {&r_columnmethod}, {2.0}, {0.0}, {0.0}, {ColumnMethods} },
{ discrete, "Stretch short skies", {&r_stretchsky}, {2.0}, {0.0}, {0.0}, {OnOff} }, { discrete, "Stretch short skies", {&r_stretchsky}, {2.0}, {0.0}, {0.0}, {OnOff} },
@ -556,7 +558,7 @@ static menuitem_t VideoItems[] = {
{ discrete, "Bullet Puff Type", {&cl_pufftype}, {2.0}, {0.0}, {0.0}, {PuffTypes} }, { discrete, "Bullet Puff Type", {&cl_pufftype}, {2.0}, {0.0}, {0.0}, {PuffTypes} },
}; };
#define CROSSHAIR_INDEX 9 #define CROSSHAIR_INDEX 10
menu_t VideoMenu = menu_t VideoMenu =
{ {
@ -1159,7 +1161,8 @@ static menuitem_t CompatibilityItems[] = {
{ bitflag, "Inst. moving floors are not silent", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_SILENT_INSTANT_FLOORS} }, { bitflag, "Inst. moving floors are not silent", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_SILENT_INSTANT_FLOORS} },
{ bitflag, "Sector sounds use center as source", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_SECTORSOUNDS} }, { bitflag, "Sector sounds use center as source", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_SECTORSOUNDS} },
{ bitflag, "Use Doom heights for missile clipping", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_MISSILECLIP} }, { bitflag, "Use Doom heights for missile clipping", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_MISSILECLIP} },
{ bitflag, "Allow any bossdeath for level special", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_ANYBOSSDEATH} }, { bitflag, "Allow any bossdeath for level special", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_ANYBOSSDEATH} },
{ bitflag, "No Minotaur floor flames in water", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_MINOTAUR} },
{ discrete, "Interpolate monster movement", {&nomonsterinterpolation}, {2.0}, {0.0}, {0.0}, {NoYes} }, { discrete, "Interpolate monster movement", {&nomonsterinterpolation}, {2.0}, {0.0}, {0.0}, {NoYes} },
}; };

View file

@ -2957,7 +2957,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
{ {
FName p(FBehavior::StaticLookupString(args[0])); FName p(FBehavior::StaticLookupString(args[0]));
ABasicArmor * armor = (ABasicArmor *) players[args[1]].mo->FindInventory(NAME_BasicArmor); ABasicArmor * armor = (ABasicArmor *) players[args[1]].mo->FindInventory(NAME_BasicArmor);
if (armor->ArmorType == p) return 1; if (armor && armor->ArmorType == p) return armor->Amount;
} }
return 0; return 0;
} }

View file

@ -1039,12 +1039,20 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
ang = R_PointToAngle2 (origin->x, origin->y, ang = R_PointToAngle2 (origin->x, origin->y,
target->x, target->y); target->x, target->y);
thrust = damage*(FRACUNIT>>3)*kickback / target->Mass;
// Calculate this as float to avoid overflows so that the
// clamping that had to be done here can be removed.
thrust = FLOAT2FIXED((damage * 0.125 * kickback) / target->Mass);
// [RH] If thrust overflows, use a more reasonable amount // [RH] If thrust overflows, use a more reasonable amount
/* old fixed point code that could overflow.
thrust = damage*(FRACUNIT>>3)*kickback / target->Mass;
if (thrust < 0 || thrust > 10*FRACUNIT) if (thrust < 0 || thrust > 10*FRACUNIT)
{ {
thrust = 10*FRACUNIT; thrust = 10*FRACUNIT;
} }
*/
// make fall forwards sometimes // make fall forwards sometimes
if ((damage < 40) && (damage > target->health) if ((damage < 40) && (damage > target->health)
&& (target->z - origin->z > 64*FRACUNIT) && (target->z - origin->z > 64*FRACUNIT)

View file

@ -2357,6 +2357,57 @@ FUNC(LS_Line_SetTextureOffset)
return true; return true;
} }
FUNC(LS_Line_SetTextureScale)
// Line_SetTextureScale (id, x, y, side, flags)
{
const fixed_t NO_CHANGE = 32767<<FRACBITS;
if (arg0 == 0 || arg3 < 0 || arg3 > 1)
return false;
for(int line = -1; (line = P_FindLineFromID (arg0, line)) >= 0; )
{
if (lines[line].sidenum[arg3] != NO_SIDE)
{
side_t *side = &sides[lines[line].sidenum[arg3]];
if ((arg4&8)==0)
{
// set
if (arg1 != NO_CHANGE)
{
if (arg4&1) side->SetTextureXScale(side_t::top, arg1);
if (arg4&2) side->SetTextureXScale(side_t::mid, arg1);
if (arg4&4) side->SetTextureXScale(side_t::bottom, arg1);
}
if (arg2 != NO_CHANGE)
{
if (arg4&1) side->SetTextureYScale(side_t::top, arg2);
if (arg4&2) side->SetTextureYScale(side_t::mid, arg2);
if (arg4&4) side->SetTextureYScale(side_t::bottom, arg2);
}
}
else
{
// add
if (arg1 != NO_CHANGE)
{
if (arg4&1) side->MultiplyTextureXScale(side_t::top, arg1);
if (arg4&2) side->MultiplyTextureXScale(side_t::mid, arg1);
if (arg4&4) side->MultiplyTextureXScale(side_t::bottom, arg1);
}
if (arg2 != NO_CHANGE)
{
if (arg4&1) side->MultiplyTextureYScale(side_t::top, arg2);
if (arg4&2) side->MultiplyTextureYScale(side_t::mid, arg2);
if (arg4&4) side->MultiplyTextureYScale(side_t::bottom, arg2);
}
}
}
}
return true;
}
FUNC(LS_Line_SetBlocking) FUNC(LS_Line_SetBlocking)
// Line_SetBlocking (id, setflags, clearflags) // Line_SetBlocking (id, setflags, clearflags)
{ {
@ -2978,7 +3029,7 @@ lnSpecFunc LineSpecials[256] =
LS_Line_SetTextureOffset, LS_Line_SetTextureOffset,
LS_Sector_ChangeFlags, LS_Sector_ChangeFlags,
LS_Line_SetBlocking, LS_Line_SetBlocking,
LS_NOP, // 56 LS_Line_SetTextureScale,
LS_NOP, // 57 LS_NOP, // 57
LS_NOP, // 58 LS_NOP, // 58
LS_NOP, // 59 LS_NOP, // 59

View file

@ -350,11 +350,13 @@ struct FCheckPosition
// ripping damage once per tic instead of once per move. // ripping damage once per tic instead of once per move.
bool DoRipping; bool DoRipping;
AActor *LastRipped; AActor *LastRipped;
int PushTime;
FCheckPosition(bool rip=false) FCheckPosition(bool rip=false)
{ {
DoRipping = rip; DoRipping = rip;
LastRipped = NULL; LastRipped = NULL;
PushTime = 0;
} }
}; };

View file

@ -755,7 +755,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
if ((thing->flags2 | tm.thing->flags2) & MF2_THRUACTORS) if ((thing->flags2 | tm.thing->flags2) & MF2_THRUACTORS)
return true; return true;
if ((tm.thing->flags6 & MF6_THRUSPECIES) && (tm.thing->Species == thing->Species)) if ((tm.thing->flags6 & MF6_THRUSPECIES) && (tm.thing->GetSpecies() == thing->GetSpecies()))
return true; return true;
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE)) ) if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE)) )
@ -826,6 +826,13 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
return false; return false;
} }
} }
// Check for players touching a thing with MF6_BUMPSPECIAL
// A blind recreation of what the Skulltag code is probably like.
if (tm.thing->player && (thing->flags6 & MF6_BUMPSPECIAL) && thing->special)
{
LineSpecials[thing->special] (NULL, tm.thing, false, thing->args[0],
thing->args[1], thing->args[2], thing->args[3], thing->args[4]);
}
// Check for missile // Check for missile
if (tm.thing->flags & MF_MISSILE) if (tm.thing->flags & MF_MISSILE)
{ {
@ -1001,8 +1008,12 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
if (thing->flags2 & MF2_PUSHABLE if (thing->flags2 & MF2_PUSHABLE
&& !(tm.thing->flags2 & MF2_CANNOTPUSH)) && !(tm.thing->flags2 & MF2_CANNOTPUSH))
{ // Push thing { // Push thing
thing->momx += tm.thing->momx>>2; if (thing->lastpush != tm.PushTime)
thing->momy += tm.thing->momy>>2; {
thing->momx += FixedMul(tm.thing->momx, thing->pushfactor);
thing->momy += FixedMul(tm.thing->momy, thing->pushfactor);
thing->lastpush = tm.PushTime;
}
} }
} }
spechit.Clear (); spechit.Clear ();
@ -1041,8 +1052,12 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
if (thing->flags2 & MF2_PUSHABLE && !(tm.thing->flags2 & MF2_CANNOTPUSH) && if (thing->flags2 & MF2_PUSHABLE && !(tm.thing->flags2 & MF2_CANNOTPUSH) &&
(tm.thing->player == NULL || !(tm.thing->player->cheats & CF_PREDICTING))) (tm.thing->player == NULL || !(tm.thing->player->cheats & CF_PREDICTING)))
{ // Push thing { // Push thing
thing->momx += FixedMul(tm.thing->momx, thing->pushfactor); if (thing->lastpush != tm.PushTime)
thing->momy += FixedMul(tm.thing->momy, thing->pushfactor); {
thing->momx += FixedMul(tm.thing->momx, thing->pushfactor);
thing->momy += FixedMul(tm.thing->momy, thing->pushfactor);
thing->lastpush = tm.PushTime;
}
} }
solid = (thing->flags & MF_SOLID) && solid = (thing->flags & MF_SOLID) &&
!(thing->flags & MF_NOCLIP) && !(thing->flags & MF_NOCLIP) &&
@ -2926,7 +2941,7 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
pitch_friend=thingpitch; pitch_friend=thingpitch;
} }
} }
else if (!(th->flags3&MF3_ISMONSTER) ) else if (!(th->flags3&MF3_ISMONSTER) && th->player == NULL)
{ {
if (sv_smartaim < 3) if (sv_smartaim < 3)
{ {
@ -3244,7 +3259,8 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance,
} }
} }
// [GZ] If MF6_FORCEPAIN is set, we need to call P_DamageMobj even if damage is 0! // [GZ] If MF6_FORCEPAIN is set, we need to call P_DamageMobj even if damage is 0!
if (damage || puff->flags6 & MF6_FORCEPAIN) // Note: The puff may not yet be spawned here so we must check the class defaults, not the actor.
if (damage || (puffDefaults->flags6 & MF6_FORCEPAIN))
{ {
int flags = DMG_INFLICTOR_IS_PUFF; int flags = DMG_INFLICTOR_IS_PUFF;
// Allow MF5_PIERCEARMOR on a weapon as well. // Allow MF5_PIERCEARMOR on a weapon as well.

View file

@ -296,6 +296,7 @@ void AActor::Serialize (FArchive &arc)
<< smokecounter << smokecounter
<< BlockingMobj << BlockingMobj
<< BlockingLine << BlockingLine
<< pushfactor
<< Species; << Species;
if (arc.IsStoring ()) if (arc.IsStoring ())
@ -1499,6 +1500,7 @@ bool P_SeekerMissile (AActor *actor, angle_t thresh, angle_t turnMax)
fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly) fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
{ {
static int pushtime = 0;
bool bForceSlide = scrollx || scrolly; bool bForceSlide = scrollx || scrolly;
angle_t angle; angle_t angle;
fixed_t ptryx, ptryy; fixed_t ptryx, ptryy;
@ -1658,11 +1660,16 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
// last actor ripped through is recorded so that if the projectile // last actor ripped through is recorded so that if the projectile
// passes through more than one actor this tic, each one takes damage // passes through more than one actor this tic, each one takes damage
// and not just the first one. // and not just the first one.
pushtime++;
FCheckPosition tm(!!(mo->flags2 & MF2_RIP)); FCheckPosition tm(!!(mo->flags2 & MF2_RIP));
do do
{ {
if (i_compatflags & COMPATF_WALLRUN) pushtime++;
tm.PushTime = pushtime;
ptryx = startx + Scale (xmove, step, steps); ptryx = startx + Scale (xmove, step, steps);
ptryy = starty + Scale (ymove, step, steps); ptryy = starty + Scale (ymove, step, steps);
@ -1722,7 +1729,7 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
fixed_t tx, ty; fixed_t tx, ty;
tx = 0, ty = onestepy; tx = 0, ty = onestepy;
walkplane = P_CheckSlopeWalk (mo, tx, ty); walkplane = P_CheckSlopeWalk (mo, tx, ty);
if (P_TryMove (mo, mo->x + tx, mo->y + ty, true, walkplane)) if (P_TryMove (mo, mo->x + tx, mo->y + ty, true, walkplane, tm))
{ {
mo->momx = 0; mo->momx = 0;
} }
@ -1730,7 +1737,7 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
{ {
tx = onestepx, ty = 0; tx = onestepx, ty = 0;
walkplane = P_CheckSlopeWalk (mo, tx, ty); walkplane = P_CheckSlopeWalk (mo, tx, ty);
if (P_TryMove (mo, mo->x + tx, mo->y + ty, true, walkplane)) if (P_TryMove (mo, mo->x + tx, mo->y + ty, true, walkplane, tm))
{ {
mo->momy = 0; mo->momy = 0;
} }
@ -5014,21 +5021,30 @@ AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z,
AActor *linetarget; AActor *linetarget;
int vrange = nofreeaim? ANGLE_1*35 : 0; int vrange = nofreeaim? ANGLE_1*35 : 0;
// see which target is to be aimed at // Note: NOAUTOAIM is implemented only here, and not in the hitscan or rail attack functions.
i = 2; // That is because it is only justified for projectiles affected by gravity, not for other attacks.
do if (source && source->player && source->player->ReadyWeapon && (source->player->ReadyWeapon->WeaponFlags & WIF_NOAUTOAIM))
{ {
an = angle + angdiff[i]; // Keep exactly the same angle and pitch as the player's own aim
pitch = P_AimLineAttack (source, an, 16*64*FRACUNIT, &linetarget, vrange); pitch = source->pitch; linetarget = NULL;
}
if (source->player != NULL && else // see which target is to be aimed at
!nofreeaim && {
level.IsFreelookAllowed() && i = 2;
source->player->userinfo.GetAimDist() <= ANGLE_1/2) do
{ {
break; an = angle + angdiff[i];
} pitch = P_AimLineAttack (source, an, 16*64*FRACUNIT, &linetarget, vrange);
} while (linetarget == NULL && --i >= 0);
if (source->player != NULL &&
!nofreeaim &&
level.IsFreelookAllowed() &&
source->player->userinfo.GetAimDist() <= ANGLE_1/2)
{
break;
}
} while (linetarget == NULL && --i >= 0);
}
if (linetarget == NULL) if (linetarget == NULL)
{ {

View file

@ -199,18 +199,6 @@ void R_InitPicAnims (void)
tex2->Name, pic2.GetIndex(), tex2->GetSourceLump(), Wads.GetLumpFile(tex2->GetSourceLump())); tex2->Name, pic2.GetIndex(), tex2->GetSourceLump(), Wads.GetLumpFile(tex2->GetSourceLump()));
} }
/* FIXME: doesn't work with hires texture replacements.
int l1 = tex1->GetSourceLump();
int l2 = tex2->GetSourceLump();
if (tex1->UseType == FTexture::TEX_Wall && l1 != l2)
{
// Animated walls must be in the same definition lumo
continue;
}
*/
// [RH] Allow for backward animations as well as forward. // [RH] Allow for backward animations as well as forward.
if (pic1 > pic2) if (pic1 > pic2)
{ {
@ -244,16 +232,19 @@ void R_InitPicAnims (void)
void R_AddSimpleAnim (FTextureID picnum, int animcount, int animtype, DWORD speedmin, DWORD speedrange) void R_AddSimpleAnim (FTextureID picnum, int animcount, int animtype, DWORD speedmin, DWORD speedrange)
{ {
FAnimDef *anim = (FAnimDef *)M_Malloc (sizeof(FAnimDef)); if (TexMan.AreTexturesCompatible(picnum, picnum + (animcount - 1)))
anim->CurFrame = 0; {
anim->BasePic = picnum; FAnimDef *anim = (FAnimDef *)M_Malloc (sizeof(FAnimDef));
anim->NumFrames = animcount; anim->CurFrame = 0;
anim->AnimType = animtype; anim->BasePic = picnum;
anim->SwitchTime = 0; anim->NumFrames = animcount;
anim->Frames[0].SpeedMin = speedmin; anim->AnimType = animtype;
anim->Frames[0].SpeedRange = speedrange; anim->SwitchTime = 0;
anim->Frames[0].FramePic = anim->BasePic; anim->Frames[0].SpeedMin = speedmin;
Anims.AddAnim (anim); anim->Frames[0].SpeedRange = speedrange;
anim->Frames[0].FramePic = anim->BasePic;
Anims.AddAnim (anim);
}
} }
//========================================================================== //==========================================================================

View file

@ -824,6 +824,11 @@ struct side_t
{ {
return textures[which].xscale; return textures[which].xscale;
} }
void MultiplyTextureXScale(int which, fixed_t delta)
{
textures[which].xscale = FixedMul(textures[which].xscale, delta);
}
void SetTextureYScale(int which, fixed_t scale) void SetTextureYScale(int which, fixed_t scale)
{ {
@ -837,6 +842,10 @@ struct side_t
{ {
return textures[which].yscale; return textures[which].yscale;
} }
void MultiplyTextureYScale(int which, fixed_t delta)
{
textures[which].yscale = FixedMul(textures[which].yscale, delta);
}
DInterpolation *SetInterpolation(int position); DInterpolation *SetInterpolation(int position);
void StopInterpolation(int position); void StopInterpolation(int position);

View file

@ -906,7 +906,7 @@ static void R_DrawSkyStriped (visplane_t *pl)
{ {
lastskycol[x] = 0xffffffff; lastskycol[x] = 0xffffffff;
} }
wallscan (pl->minx, pl->maxx, top, bot, swall, lwall, frontyScale, wallscan (pl->minx, pl->maxx, top, bot, swall, lwall, rw_pic->yScale,
backskytex == NULL ? R_GetOneSkyColumn : R_GetTwoSkyColumns); backskytex == NULL ? R_GetOneSkyColumn : R_GetTwoSkyColumns);
yl = yh; yl = yh;
yh += drawheight; yh += drawheight;

View file

@ -224,7 +224,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
i++; i++;
continue; continue;
} }
// same for x_START markers // same for x_END markers
while (i < markers.Size()-1 && (markers[i].markertype == 1 && markers[i+1].markertype == 1)) while (i < markers.Size()-1 && (markers[i].markertype == 1 && markers[i+1].markertype == 1))
{ {
Printf(TEXTCOLOR_YELLOW"WARNING: duplicate %s marker found.\n", endmarker); Printf(TEXTCOLOR_YELLOW"WARNING: duplicate %s marker found.\n", endmarker);
@ -235,13 +235,16 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
if (i >= markers.Size()) if (i >= markers.Size())
{ {
Printf(TEXTCOLOR_YELLOW"WARNING: %s marker without corresponding %s found.\n", startmarker, endmarker); Printf(TEXTCOLOR_YELLOW"WARNING: %s marker without corresponding %s found.\n", startmarker, endmarker);
return; end = NumLumps;
}
else
{
end = markers[i++].index;
} }
end = i++;
// we found a marked block // we found a marked block
DPrintf("Found %s block at (%d-%d)\n", startmarker, markers[start].index, markers[end].index); DPrintf("Found %s block at (%d-%d)\n", startmarker, markers[start].index, end);
for(int j = markers[start].index+1; j < markers[end].index; j++) for(int j = markers[start].index + 1; j < end; j++)
{ {
if (Lumps[j].Namespace != ns_global) if (Lumps[j].Namespace != ns_global)
{ {

View file

@ -170,14 +170,14 @@ static WORD DIKToKeySym[256] =
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, SDLK_KP_DIVIDE, 0, SDLK_SYSREQ, 0, 0, 0, 0, 0, SDLK_KP_DIVIDE, 0, SDLK_SYSREQ,
SDLK_RALT, 0, 0, 0, 0, 0, 0, 0, SDLK_RALT, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, SDLK_HOME, 0, 0, 0, 0, 0, SDLK_PAUSE, 0, SDLK_HOME,
SDLK_UP, SDLK_PAGEUP, 0, SDLK_LEFT, 0, SDLK_RIGHT, 0, SDLK_END, SDLK_UP, SDLK_PAGEUP, 0, SDLK_LEFT, 0, SDLK_RIGHT, 0, SDLK_END,
SDLK_DOWN, SDLK_PAGEDOWN, SDLK_INSERT, SDLK_DELETE, 0, 0, 0, 0, SDLK_DOWN, SDLK_PAGEDOWN, SDLK_INSERT, SDLK_DELETE, 0, 0, 0, 0,
0, 0, 0, SDLK_LSUPER, SDLK_RSUPER, SDLK_MENU, SDLK_POWER, 0, 0, 0, 0, SDLK_LSUPER, SDLK_RSUPER, SDLK_MENU, SDLK_POWER, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, SDLK_PAUSE 0, 0, 0, 0, 0, 0, 0, 0
}; };
static void FlushDIKState (int low=0, int high=NUM_KEYS-1) static void FlushDIKState (int low=0, int high=NUM_KEYS-1)

View file

@ -528,7 +528,7 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
} }
} }
// Check for game music // Check for game music
else if ((fmt = GME_CheckFormat(id)) != NULL) else if ((fmt = GME_CheckFormat(id)) != NULL && fmt[0] != '\0')
{ {
info = GME_OpenSong(file, musiccache, len, fmt); info = GME_OpenSong(file, musiccache, len, fmt);
} }

View file

@ -201,7 +201,7 @@ void GMESong::Play(bool looping, int track)
{ {
m_Status = STATE_Stopped; m_Status = STATE_Stopped;
m_Looping = looping; m_Looping = looping;
if (StartTrack(0) && m_Stream->Play(looping, 1)) if (StartTrack(track) && m_Stream->Play(looping, 1))
{ {
m_Status = STATE_Playing; m_Status = STATE_Playing;
} }

View file

@ -3,5 +3,5 @@
// This file was automatically generated by the // This file was automatically generated by the
// updaterevision tool. Do not edit by hand. // updaterevision tool. Do not edit by hand.
#define ZD_SVN_REVISION_STRING "1650" #define ZD_SVN_REVISION_STRING "1668"
#define ZD_SVN_REVISION_NUMBER 1650 #define ZD_SVN_REVISION_NUMBER 1668

View file

@ -371,6 +371,40 @@ void FTextureManager::ReplaceTexture (FTextureID picnum, FTexture *newtexture, b
} }
} }
//==========================================================================
//
// FTextureManager :: AreTexturesCompatible
//
// Checks if 2 textures are compatible for a ranged animation
//
//==========================================================================
bool FTextureManager::AreTexturesCompatible (FTextureID picnum1, FTextureID picnum2)
{
int index1 = picnum1.GetIndex();
int index2 = picnum2.GetIndex();
if (unsigned(index1) >= Textures.Size() || unsigned(index2) >= Textures.Size())
return false;
FTexture *texture1 = Textures[index1].Texture;
FTexture *texture2 = Textures[index2].Texture;
// both textures must be the same type.
if (texture1 == NULL || texture2 == NULL || texture1->UseType != texture2->UseType)
return false;
// both textures must be from the same file
for(unsigned i = 0; i < FirstTextureForFile.Size() - 1; i++)
{
if (index1 >= FirstTextureForFile[i] && index1 < FirstTextureForFile[i+1])
{
return (index2 >= FirstTextureForFile[i] && index2 < FirstTextureForFile[i+1]);
}
}
return false;
}
//========================================================================== //==========================================================================
// //
// FTextureManager :: AddGroup // FTextureManager :: AddGroup
@ -707,6 +741,8 @@ void FTextureManager::AddTexturesForWad(int wadnum)
int firsttexture = Textures.Size(); int firsttexture = Textures.Size();
int lumpcount = Wads.GetNumLumps(); int lumpcount = Wads.GetNumLumps();
FirstTextureForFile.Push(firsttexture);
// First step: Load sprites // First step: Load sprites
AddGroup(wadnum, ns_sprites, FTexture::TEX_Sprite); AddGroup(wadnum, ns_sprites, FTexture::TEX_Sprite);
@ -857,7 +893,12 @@ void FTextureManager::Init()
{ {
AddTexturesForWad(i); AddTexturesForWad(i);
} }
// Add one marker so that the last WAD is easier to handle and treat
// Build tiles as a completely separate block.
FirstTextureForFile.Push(Textures.Size());
R_InitBuildTiles (); R_InitBuildTiles ();
FirstTextureForFile.Push(Textures.Size());
DefaultTexture = CheckForTexture ("-NOFLAT-", FTexture::TEX_Override, 0); DefaultTexture = CheckForTexture ("-NOFLAT-", FTexture::TEX_Override, 0);

View file

@ -337,6 +337,7 @@ public:
void LoadTextureDefs(int wadnum, const char *lumpname); void LoadTextureDefs(int wadnum, const char *lumpname);
void ParseXTexture(FScanner &sc, int usetype); void ParseXTexture(FScanner &sc, int usetype);
void SortTexturesByType(int start, int end); void SortTexturesByType(int start, int end);
bool AreTexturesCompatible (FTextureID picnum1, FTextureID picnum2);
FTextureID CreateTexture (int lumpnum, int usetype=FTexture::TEX_Any); // Also calls AddTexture FTextureID CreateTexture (int lumpnum, int usetype=FTexture::TEX_Any); // Also calls AddTexture
FTextureID AddTexture (FTexture *texture); FTextureID AddTexture (FTexture *texture);
@ -374,6 +375,7 @@ private:
TArray<int> Translation; TArray<int> Translation;
int HashFirst[HASH_SIZE]; int HashFirst[HASH_SIZE];
FTextureID DefaultTexture; FTextureID DefaultTexture;
TArray<int> FirstTextureForFile;
}; };
extern FTextureManager TexMan; extern FTextureManager TexMan;

View file

@ -535,12 +535,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfArmorType)
ACTION_PARAM_START(3); ACTION_PARAM_START(3);
ACTION_PARAM_NAME(Type, 0); ACTION_PARAM_NAME(Type, 0);
ACTION_PARAM_STATE(JumpOffset, 1); ACTION_PARAM_STATE(JumpOffset, 1);
ACTION_PARAM_INT(amount, 2);
ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
ABasicArmor * armor = (ABasicArmor *) self->FindInventory(NAME_BasicArmor); ABasicArmor * armor = (ABasicArmor *) self->FindInventory(NAME_BasicArmor);
if (armor && armor->ArmorType == Type) if (armor && armor->ArmorType == Type && armor->Amount >= amount)
ACTION_JUMP(JumpOffset); ACTION_JUMP(JumpOffset);
} }
@ -1705,14 +1706,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeIn)
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeOut) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeOut)
{ {
ACTION_PARAM_START(1); ACTION_PARAM_START(2);
ACTION_PARAM_FIXED(reduce, 0); ACTION_PARAM_FIXED(reduce, 0);
ACTION_PARAM_BOOL(remove, 1);
if (reduce == 0) reduce = FRACUNIT/10; if (reduce == 0) reduce = FRACUNIT/10;
self->RenderStyle.Flags &= ~STYLEF_Alpha1; self->RenderStyle.Flags &= ~STYLEF_Alpha1;
self->alpha -= reduce; self->alpha -= reduce;
if (self->alpha<=0) self->Destroy(); if (self->alpha<=0 && remove) self->Destroy();
} }
//=========================================================================== //===========================================================================
@ -1780,24 +1782,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSight)
} }
//===========================================================================
//
// A_JumpIfTargetInSight
// jumps if monster can see its target
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInSight)
{
ACTION_PARAM_START(1);
ACTION_PARAM_STATE(jump, 0);
ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
if (self->target == NULL || !P_CheckSight(self, self->target,4)) return;
ACTION_JUMP(jump);
}
//=========================================================================== //===========================================================================
// //
// Inventory drop // Inventory drop
@ -2210,6 +2194,62 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
ACTION_JUMP(jump); ACTION_JUMP(jump);
} }
//==========================================================================
//
// A_JumpIfInTargetLOS (state label, optional fixed fov, optional bool
// projectiletarget)
//
//==========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS)
{
ACTION_PARAM_START(3);
ACTION_PARAM_STATE(jump, 0);
ACTION_PARAM_ANGLE(fov, 1);
ACTION_PARAM_BOOL(projtarg, 2);
angle_t an;
AActor *target;
ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
if (self->flags & MF_MISSILE && projtarg)
{
if (self->flags2 & MF2_SEEKERMISSILE)
target = self->tracer;
else
target = NULL;
}
else
{
target = self->target;
}
if (!target) return; // [KS] Let's not call P_CheckSight unnecessarily in this case.
if (!P_CheckSight (target, self, 1))
return;
if (fov && (fov < ANGLE_MAX))
{
an = R_PointToAngle2 (self->x,
self->y,
target->x,
target->y)
- self->angle;
if (an > (fov / 2) && an < (ANGLE_MAX - (fov / 2)))
{
return; // [KS] Outside of FOV - return
}
}
ACTION_JUMP(jump);
}
//=========================================================================== //===========================================================================
// //
// A_DamageMaster (int amount) // A_DamageMaster (int amount)

View file

@ -214,6 +214,7 @@ static FFlagDef ActorFlags[]=
DEFINE_FLAG(MF6, MTHRUSPECIES, AActor, flags6), DEFINE_FLAG(MF6, MTHRUSPECIES, AActor, flags6),
DEFINE_FLAG(MF6, FORCEPAIN, AActor, flags6), DEFINE_FLAG(MF6, FORCEPAIN, AActor, flags6),
DEFINE_FLAG(MF6, NOFEAR, AActor, flags6), DEFINE_FLAG(MF6, NOFEAR, AActor, flags6),
DEFINE_FLAG(MF6, BUMPSPECIAL, AActor, flags6),
// Effect flags // Effect flags
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
@ -234,9 +235,12 @@ static FFlagDef ActorFlags[]=
DEFINE_DEPRECATED_FLAG(HERETICBOUNCE), DEFINE_DEPRECATED_FLAG(HERETICBOUNCE),
DEFINE_DEPRECATED_FLAG(HEXENBOUNCE), DEFINE_DEPRECATED_FLAG(HEXENBOUNCE),
DEFINE_DEPRECATED_FLAG(DOOMBOUNCE), DEFINE_DEPRECATED_FLAG(DOOMBOUNCE),
DEFINE_DUMMY_FLAG(NONETID),
DEFINE_DUMMY_FLAG(ALLOWCLIENTSPAWN), // Various Skulltag flags that are quite irrelevant to ZDoom
DEFINE_DUMMY_FLAG(CLIENTSIDEONLY), DEFINE_DUMMY_FLAG(NONETID), // netcode-based
DEFINE_DUMMY_FLAG(ALLOWCLIENTSPAWN), // netcode-based
DEFINE_DUMMY_FLAG(CLIENTSIDEONLY), // netcode-based
DEFINE_DUMMY_FLAG(EXPLODEONDEATH), // seems useless
}; };
static FFlagDef InventoryFlags[] = static FFlagDef InventoryFlags[] =
@ -281,6 +285,7 @@ static FFlagDef WeaponFlags[] =
DEFINE_FLAG(WIF, CHEATNOTWEAPON, AWeapon, WeaponFlags), DEFINE_FLAG(WIF, CHEATNOTWEAPON, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF, NO_AUTO_SWITCH, AWeapon, WeaponFlags), DEFINE_FLAG(WIF, NO_AUTO_SWITCH, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF, AMMO_CHECKBOTH, AWeapon, WeaponFlags), DEFINE_FLAG(WIF, AMMO_CHECKBOTH, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF, NOAUTOAIM, AWeapon, WeaponFlags),
DEFINE_DUMMY_FLAG(NOLMS), DEFINE_DUMMY_FLAG(NOLMS),
}; };

View file

@ -60,7 +60,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def);
// //
// ParseParameter // ParseParameter
// //
// Parses aparameter - either a default in a function declaration // Parses a parameter - either a default in a function declaration
// or an argument in a function call. // or an argument in a function call.
// //
//========================================================================== //==========================================================================

View file

@ -1262,6 +1262,14 @@ DEFINE_CLASS_PROPERTY(pickupsound, S, Inventory)
defaults->PickupSound = str; defaults->PickupSound = str;
} }
//==========================================================================
// Dummy for Skulltag compatibility...
//==========================================================================
DEFINE_CLASS_PROPERTY(pickupannouncerentry, S, Inventory)
{
PROP_STRING_PARM(str, 0);
}
//========================================================================== //==========================================================================
// //
//========================================================================== //==========================================================================

View file

@ -71,6 +71,10 @@
// w32api does not #define the PBT_ macros in winuser.h like the PSDK does // w32api does not #define the PBT_ macros in winuser.h like the PSDK does
#include <pbt.h> #include <pbt.h>
#endif #endif
#ifndef GET_RAWINPUT_CODE_WPARAM
#define GET_RAWINPUT_CODE_WPARAM(wParam) ((wParam) & 0xff)
#endif
#define USE_WINDOWS_DWORD #define USE_WINDOWS_DWORD
#include "c_dispatch.h" #include "c_dispatch.h"
@ -460,6 +464,32 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{ {
LRESULT result; LRESULT result;
if (message == WM_INPUT)
{
if (MyGetRawInputData != NULL)
{
UINT size;
if (!MyGetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)) &&
size != 0)
{
BYTE *buffer = (BYTE *)alloca(size);
if (MyGetRawInputData((HRAWINPUT)lParam, RID_INPUT, buffer, &size, sizeof(RAWINPUTHEADER)) == size)
{
int code = GET_RAWINPUT_CODE_WPARAM(wParam);
if (Keyboard == NULL || !Keyboard->ProcessRawInput((RAWINPUT *)buffer, code))
{
if (Mouse != NULL)
{
Mouse->ProcessRawInput((RAWINPUT *)buffer, code);
}
}
}
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
if (CallHook(Keyboard, hWnd, message, wParam, lParam, &result)) if (CallHook(Keyboard, hWnd, message, wParam, lParam, &result))
{ {
return result; return result;
@ -1184,10 +1214,12 @@ void I_ShutdownInput ()
if (Keyboard != NULL) if (Keyboard != NULL)
{ {
delete Keyboard; delete Keyboard;
Keyboard = NULL;
} }
if (Mouse != NULL) if (Mouse != NULL)
{ {
delete Mouse; delete Mouse;
Mouse = NULL;
} }
if (g_pJoy) if (g_pJoy)
{ {
@ -1336,6 +1368,34 @@ FInputDevice::~FInputDevice()
{ {
} }
//==========================================================================
//
// FInputDevice :: ProcessInput
//
// Gives subclasses an opportunity to do input handling that doesn't involve
// window messages.
//
//==========================================================================
void FInputDevice::ProcessInput()
{
}
//==========================================================================
//
// FInputDevice :: ProcessRawInput
//
// Gives subclasses a chance to handle WM_INPUT messages. This is not part
// of WndProcHook so that we only need to fill the RAWINPUT buffer once
// per message and be sure it gets cleaned up properly.
//
//==========================================================================
bool FInputDevice::ProcessRawInput(RAWINPUT *raw, int code)
{
return false;
}
//========================================================================== //==========================================================================
// //
// FInputDevice :: WndProcHook // FInputDevice :: WndProcHook

View file

@ -57,12 +57,15 @@ extern void DI_EnumJoy ();
#ifdef USE_WINDOWS_DWORD #ifdef USE_WINDOWS_DWORD
// Don't make these definitions available to the main body of the source code. // Don't make these definitions available to the main body of the source code.
struct tagRAWINPUT;
class FInputDevice class FInputDevice
{ {
public: public:
virtual ~FInputDevice() = 0; virtual ~FInputDevice() = 0;
virtual bool GetDevice() = 0; virtual bool GetDevice() = 0;
virtual void ProcessInput() = 0; virtual void ProcessInput();
virtual bool ProcessRawInput(tagRAWINPUT *raw, int code);
virtual bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result); virtual bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result);
}; };

View file

@ -21,11 +21,6 @@
#define DINPUT_BUFFERSIZE 32 #define DINPUT_BUFFERSIZE 32
// Hi, w32api!
#ifndef GET_RAWINPUT_CODE_WPARAM
#define GET_RAWINPUT_CODE_WPARAM(wParam) ((wParam) & 0xff)
#endif
// TYPES ------------------------------------------------------------------- // TYPES -------------------------------------------------------------------
class FDInputKeyboard : public FKeyboard class FDInputKeyboard : public FKeyboard
@ -36,7 +31,6 @@ public:
bool GetDevice(); bool GetDevice();
void ProcessInput(); void ProcessInput();
bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result);
protected: protected:
LPDIRECTINPUTDEVICE8 Device; LPDIRECTINPUTDEVICE8 Device;
@ -49,8 +43,7 @@ public:
~FRawKeyboard(); ~FRawKeyboard();
bool GetDevice(); bool GetDevice();
void ProcessInput(); bool ProcessRawInput(RAWINPUT *rawinput, int code);
bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result);
protected: protected:
USHORT E1Prefix; USHORT E1Prefix;
@ -377,16 +370,8 @@ void FDInputKeyboard::ProcessInput()
} }
} }
//========================================================================== /**************************************************************************/
// /**************************************************************************/
// FDInputKeyboard :: WndProcHook
//
//==========================================================================
bool FDInputKeyboard::WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result)
{
return false;
}
//========================================================================== //==========================================================================
// //
@ -447,17 +432,7 @@ bool FRawKeyboard::GetDevice()
//========================================================================== //==========================================================================
// //
// FRawKeyboard :: ProcessInput // FRawKeyboard :: ProcessRawInput
//
//==========================================================================
void FRawKeyboard::ProcessInput()
{
}
//==========================================================================
//
// FRawKeyboard :: WndProcHook
// //
// Convert scan codes to DirectInput key codes. For the most part, this is // Convert scan codes to DirectInput key codes. For the most part, this is
// straight forward: Scan codes without any prefix are passed unmodified. // straight forward: Scan codes without any prefix are passed unmodified.
@ -476,102 +451,88 @@ void FRawKeyboard::ProcessInput()
// //
//========================================================================== //==========================================================================
bool FRawKeyboard::WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result) bool FRawKeyboard::ProcessRawInput(RAWINPUT *raw, int code)
{ {
if (message != WM_INPUT) if (raw->header.dwType != RIM_TYPEKEYBOARD)
{ {
return false; return false;
} }
BYTE buffer[40]; int keycode = raw->data.keyboard.MakeCode;
UINT size = sizeof(buffer); if (keycode == 0 && (raw->data.keyboard.Flags & RI_KEY_E0))
int keycode; { // Even if the make code is 0, we might still be able to extract a
// useful key from the message.
if (raw->data.keyboard.VKey >= VK_BROWSER_BACK && raw->data.keyboard.VKey <= VK_LAUNCH_APP2)
{
static const BYTE MediaKeys[VK_LAUNCH_APP2 - VK_BROWSER_BACK + 1] =
{
DIK_WEBBACK, DIK_WEBFORWARD, DIK_WEBREFRESH, DIK_WEBSTOP,
DIK_WEBSEARCH, DIK_WEBFAVORITES, DIK_WEBHOME,
if (MyGetRawInputData((HRAWINPUT)lParam, RID_INPUT, buffer, &size, sizeof(RAWINPUTHEADER)) > 0) DIK_MUTE, DIK_VOLUMEDOWN, DIK_VOLUMEUP,
DIK_NEXTTRACK, DIK_PREVTRACK, DIK_MEDIASTOP, DIK_PLAYPAUSE,
DIK_MAIL, DIK_MEDIASELECT, DIK_MYCOMPUTER, DIK_CALCULATOR
};
keycode = MediaKeys[raw->data.keyboard.VKey - VK_BROWSER_BACK];
}
}
if (keycode < 1 || keycode > 0xFF)
{ {
RAWINPUT *raw = (RAWINPUT *)buffer; return false;
if (raw->header.dwType != RIM_TYPEKEYBOARD) }
{ if (raw->data.keyboard.Flags & RI_KEY_E1)
{
E1Prefix = raw->data.keyboard.MakeCode;
return false;
}
if (raw->data.keyboard.Flags & RI_KEY_E0)
{
if (keycode == DIK_LSHIFT || keycode == DIK_RSHIFT)
{ // Ignore fake shifts.
return false; return false;
} }
keycode |= 0x80;
keycode = raw->data.keyboard.MakeCode; }
if (keycode == 0 && (raw->data.keyboard.Flags & RI_KEY_E0)) // The sequence for an unshifted pause is E1 1D 45 (E1 Prefix +
{ // Even if the make code is 0, we might still be able to extract a // Control + Num Lock).
// useful key from the message. if (E1Prefix)
if (raw->data.keyboard.VKey >= VK_BROWSER_BACK && raw->data.keyboard.VKey <= VK_LAUNCH_APP2) {
{ if (E1Prefix == 0x1D && keycode == DIK_NUMLOCK)
static const BYTE MediaKeys[VK_LAUNCH_APP2 - VK_BROWSER_BACK + 1] =
{
DIK_WEBBACK, DIK_WEBFORWARD, DIK_WEBREFRESH, DIK_WEBSTOP,
DIK_WEBSEARCH, DIK_WEBFAVORITES, DIK_WEBHOME,
DIK_MUTE, DIK_VOLUMEDOWN, DIK_VOLUMEUP,
DIK_NEXTTRACK, DIK_PREVTRACK, DIK_MEDIASTOP, DIK_PLAYPAUSE,
DIK_MAIL, DIK_MEDIASELECT, DIK_MYCOMPUTER, DIK_CALCULATOR
};
keycode = MediaKeys[raw->data.keyboard.VKey - VK_BROWSER_BACK];
}
}
if (keycode < 1 || keycode > 0xFF)
{
return false;
}
if (raw->data.keyboard.Flags & RI_KEY_E1)
{
E1Prefix = raw->data.keyboard.MakeCode;
return false;
}
if (raw->data.keyboard.Flags & RI_KEY_E0)
{
if (keycode == DIK_LSHIFT || keycode == DIK_RSHIFT)
{ // Ignore fake shifts.
return false;
}
keycode |= 0x80;
}
// The sequence for an unshifted pause is E1 1D 45 (E1 Prefix +
// Control + Num Lock).
if (E1Prefix)
{
if (E1Prefix == 0x1D && keycode == DIK_NUMLOCK)
{
keycode = DIK_PAUSE;
E1Prefix = 0;
}
else
{
E1Prefix = 0;
return false;
}
}
// If you press Ctrl+Pause, the keyboard sends the Break make code
// E0 46 instead of the Pause make code.
if (keycode == 0xC6)
{ {
keycode = DIK_PAUSE; keycode = DIK_PAUSE;
E1Prefix = 0;
} }
// If you press Ctrl+PrtScn (to get SysRq), the keyboard sends else
// the make code E0 37. If you press PrtScn without any modifiers,
// it sends E0 2A E0 37. And if you press Alt+PrtScn, it sends 54
// (which is undefined in the charts I can find.)
if (keycode == 0x54)
{ {
keycode = DIK_SYSRQ; E1Prefix = 0;
return false;
} }
// If you press any keys in the island between the main keyboard
// and the numeric keypad with Num Lock turned on, they generate
// a fake shift before their actual codes. They do not generate this
// fake shift if Num Lock is off. We unconditionally discard fake
// shifts above, so we don't need to do anything special for these,
// since they are also prefixed by E0 so we can tell them apart from
// their keypad counterparts.
// Okay, we're done translating the keycode. Post it (or ignore it.)
PostKeyEvent(keycode, !(raw->data.keyboard.Flags & RI_KEY_BREAK),
GET_RAWINPUT_CODE_WPARAM(wParam) == RIM_INPUT);
} }
return false; // If you press Ctrl+Pause, the keyboard sends the Break make code
// E0 46 instead of the Pause make code.
if (keycode == 0xC6)
{
keycode = DIK_PAUSE;
}
// If you press Ctrl+PrtScn (to get SysRq), the keyboard sends
// the make code E0 37. If you press PrtScn without any modifiers,
// it sends E0 2A E0 37. And if you press Alt+PrtScn, it sends 54
// (which is undefined in the charts I can find.)
if (keycode == 0x54)
{
keycode = DIK_SYSRQ;
}
// If you press any keys in the island between the main keyboard
// and the numeric keypad with Num Lock turned on, they generate
// a fake shift before their actual codes. They do not generate this
// fake shift if Num Lock is off. We unconditionally discard fake
// shifts above, so we don't need to do anything special for these,
// since they are also prefixed by E0 so we can tell them apart from
// their keypad counterparts.
// Okay, we're done translating the keycode. Post it (or ignore it.)
PostKeyEvent(keycode, !(raw->data.keyboard.Flags & RI_KEY_BREAK), code == RIM_INPUT);
return true;
} }
//========================================================================== //==========================================================================

View file

@ -47,7 +47,7 @@ public:
~FRawMouse(); ~FRawMouse();
bool GetDevice(); bool GetDevice();
void ProcessInput(); bool ProcessRawInput(RAWINPUT *rawinput, int code);
bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result); bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result);
void Grab(); void Grab();
void Ungrab(); void Ungrab();
@ -492,25 +492,12 @@ bool FRawMouse::GetDevice()
return true; return true;
} }
//==========================================================================
//
// FRawMouse :: ProcessInput
//
// All input comes through WM_INPUT messages, so nothing to do here.
//
//==========================================================================
void FRawMouse::ProcessInput()
{
}
//========================================================================== //==========================================================================
// //
// FRawMouse :: Grab // FRawMouse :: Grab
// //
//========================================================================== //==========================================================================
extern BOOL AppActive;
void FRawMouse::Grab() void FRawMouse::Grab()
{ {
if (!Grabbed) if (!Grabbed)
@ -561,6 +548,49 @@ void FRawMouse::Ungrab()
} }
} }
//==========================================================================
//
// FRawMouse :: ProcessRawInput
//
//==========================================================================
bool FRawMouse::ProcessRawInput(RAWINPUT *raw, int code)
{
if (!Grabbed || raw->header.dwType != RIM_TYPEMOUSE)
{
return false;
}
// Check buttons. The up and down motions are stored in the usButtonFlags field.
// The ulRawButtons field, unfortunately, is device-dependant, and may well
// not contain any data at all. This means it is apparently impossible
// to read more than five mouse buttons with Windows, because RI_MOUSE_WHEEL
// gets in the way when trying to extrapolate to more than five.
for (int i = 0, mask = 1; i < 5; ++i)
{
if (raw->data.mouse.usButtonFlags & mask) // button down
{
PostButtonEvent(i, true);
}
mask <<= 1;
if (raw->data.mouse.usButtonFlags & mask) // button up
{
PostButtonEvent(i, false);
}
mask <<= 1;
}
if (raw->data.mouse.usButtonFlags & RI_MOUSE_WHEEL)
{
WheelMoved(0, (SHORT)raw->data.mouse.usButtonData);
}
else if (raw->data.mouse.usButtonFlags & 0x800) // horizontal mouse wheel
{
WheelMoved(1, (SHORT)raw->data.mouse.usButtonData);
}
PostMouseMove(m_noprescale ? raw->data.mouse.lLastX : raw->data.mouse.lLastX<<2,
-raw->data.mouse.lLastY);
return true;
}
//========================================================================== //==========================================================================
// //
// FRawMouse :: WndProcHook // FRawMouse :: WndProcHook
@ -573,53 +603,7 @@ bool FRawMouse::WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPara
{ {
return false; return false;
} }
if (message == WM_INPUT) if (message == WM_SYSCOMMAND)
{
BYTE buffer[40];
UINT size = sizeof(buffer);
int i;
USHORT mask;
if (MyGetRawInputData((HRAWINPUT)lParam, RID_INPUT, buffer, &size, sizeof(RAWINPUTHEADER)) > 0)
{
RAWINPUT *raw = (RAWINPUT *)buffer;
if (raw->header.dwType != RIM_TYPEMOUSE)
{
return false;
}
// Check buttons. The up and down motions are stored in the usButtonFlags field.
// The ulRawButtons field, unfortunately, is device-dependant, and may well
// not contain any data at all. This means it is apparently impossible
// to read more than five mouse buttons with Windows, because RI_MOUSE_WHEEL
// gets in the way when trying to extrapolate to more than five.
for (i = 0, mask = 1; i < 5; ++i)
{
if (raw->data.mouse.usButtonFlags & mask) // button down
{
PostButtonEvent(i, true);
}
mask <<= 1;
if (raw->data.mouse.usButtonFlags & mask) // button up
{
PostButtonEvent(i, false);
}
mask <<= 1;
}
if (raw->data.mouse.usButtonFlags & RI_MOUSE_WHEEL)
{
WheelMoved(0, (SHORT)raw->data.mouse.usButtonData);
}
else if (raw->data.mouse.usButtonFlags & 0x800) // horizontal mouse wheel
{
WheelMoved(1, (SHORT)raw->data.mouse.usButtonData);
}
PostMouseMove(m_noprescale ? raw->data.mouse.lLastX : raw->data.mouse.lLastX<<2,
-raw->data.mouse.lLastY);
}
return false;
}
else if (message == WM_SYSCOMMAND)
{ {
wParam &= 0xFFF0; wParam &= 0xFFF0;
if (wParam == SC_MOVE || wParam == SC_SIZE) if (wParam == SC_MOVE || wParam == SC_SIZE)
@ -630,6 +614,9 @@ bool FRawMouse::WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPara
return false; return false;
} }
/**************************************************************************/
/**************************************************************************/
//========================================================================== //==========================================================================
// //
// CreateDInputMouse // CreateDInputMouse
@ -1126,6 +1113,9 @@ void FWin32Mouse::CenterMouse(int curx, int cury)
} }
} }
/**************************************************************************/
/**************************************************************************/
//========================================================================== //==========================================================================
// //
// I_StartupMouse // I_StartupMouse
@ -1193,4 +1183,3 @@ void I_StartupMouse ()
NativeMouse = true; NativeMouse = true;
} }
} }

View file

@ -176,7 +176,7 @@ ACTOR Actor native //: Thinker
action native A_JumpIfHealthLower(int health, state label); action native A_JumpIfHealthLower(int health, state label);
action native A_JumpIfCloser(float distance, state label); action native A_JumpIfCloser(float distance, state label);
action native A_JumpIfInventory(class<Inventory> itemtype, int itemamount, state label); action native A_JumpIfInventory(class<Inventory> itemtype, int itemamount, state label);
action native A_JumpIfArmorType(string Type, state label); action native A_JumpIfArmorType(string Type, state label, int amount = 1);
action native A_GiveInventory(class<Inventory> itemtype, int amount = 0); action native A_GiveInventory(class<Inventory> itemtype, int amount = 0);
action native A_TakeInventory(class<Inventory> itemtype, int amount = 0); action native A_TakeInventory(class<Inventory> itemtype, int amount = 0);
action native A_SpawnItem(class<Actor> itemtype, float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false); action native A_SpawnItem(class<Actor> itemtype, float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false);
@ -184,7 +184,7 @@ ACTOR Actor native //: Thinker
action native A_Print(string whattoprint, float time = 0, string fontname = ""); action native A_Print(string whattoprint, float time = 0, string fontname = "");
action native A_SetTranslucent(float alpha, int style = 0); action native A_SetTranslucent(float alpha, int style = 0);
action native A_FadeIn(float reduce = 0.1); action native A_FadeIn(float reduce = 0.1);
action native A_FadeOut(float reduce = 0.1); action native A_FadeOut(float reduce = 0.1, bool remove = true);
action native A_SpawnDebris(class<Actor> spawntype, bool transfer_translation = false, float mult_h = 1, float mult_v = 1); action native A_SpawnDebris(class<Actor> spawntype, bool transfer_translation = false, float mult_h = 1, float mult_v = 1);
action native A_CheckSight(state label); action native A_CheckSight(state label);
action native A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false); action native A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false);
@ -221,6 +221,7 @@ ACTOR Actor native //: Thinker
action native A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = ""); action native A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = "");
action native A_ClearTarget(); action native A_ClearTarget();
action native A_JumpIfTargetInLOS (state label, float fov = 0, bool projectiletarget = false); action native A_JumpIfTargetInLOS (state label, float fov = 0, bool projectiletarget = false);
action native A_JumpIfInTargetLOS (state label, float fov = 0, bool projectiletarget = false);
action native A_DamageMaster(int amount, name damagetype = "none"); action native A_DamageMaster(int amount, name damagetype = "none");
action native A_DamageChildren(int amount, name damagetype = "none"); action native A_DamageChildren(int amount, name damagetype = "none");
action native A_DamageSiblings(int amount, name damagetype = "none"); action native A_DamageSiblings(int amount, name damagetype = "none");
@ -236,8 +237,6 @@ ACTOR Actor native //: Thinker
action native A_RemoveForcefield(); action native A_RemoveForcefield();
action native A_DropWeaponPieces(class<Actor> p1, class<Actor> p2, class<Actor> p3); action native A_DropWeaponPieces(class<Actor> p1, class<Actor> p2, class<Actor> p3);
action native A_PigPain (); action native A_PigPain ();
action native A_JumpIfTargetInSight(state label);
action native A_MonsterRefire(int chance, state label); action native A_MonsterRefire(int chance, state label);
States States

View file

@ -340,6 +340,45 @@ ACTOR Rocket
} }
} }
// --------------------------------------------------------------------------
//
// Grenade -- Taken and adapted from Skulltag
//
// --------------------------------------------------------------------------
ACTOR Grenade
{
SpawnID 216
Radius 8
Height 8
Speed 25
Damage 20
Projectile
-NOGRAVITY
+RANDOMIZE
+DEHEXPLOSION
+GRENADETRAIL
BounceType "Doom"
Gravity 0.25
SeeSound "weapons/grenlf"
DeathSound "weapons/grenlx"
BounceSound "weapons/grbnce"
Obituary "$OB_GRENADE"
DamageType Grenade
States
{
Spawn:
SGRN A 1 Bright
Loop
Death:
MISL B 8 Bright A_Explode
MISL C 6 Bright
MISL D 4 Bright
Stop
}
}
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// //
// Plasma rifle // Plasma rifle

View file

@ -14,6 +14,7 @@ ACTOR Pod 2035
+CANPASS +TELESTOMP +DONTMORPH +CANPASS +TELESTOMP +DONTMORPH
+NOBLOCKMONST +DONTGIB +OLDRADIUSDMG +NOBLOCKMONST +DONTGIB +OLDRADIUSDMG
DeathSound "world/podexplode" DeathSound "world/podexplode"
PushFactor 0.5
action native A_PodPain (class<Actor> podtype = "PodGoo"); action native A_PodPain (class<Actor> podtype = "PodGoo");
action native A_RemovePod (); action native A_RemovePod ();

View file

@ -25,6 +25,7 @@ ACTOR Inventory native
action native A_LoadShotgun2(); action native A_LoadShotgun2();
action native A_CloseShotgun2(); action native A_CloseShotgun2();
action native A_FireCGun(); action native A_FireCGun();
action native A_FireSTGrenade(class<Actor> grenadetype = "Grenade");
action native A_FireMissile(); action native A_FireMissile();
action native A_FirePlasma(); action native A_FirePlasma();
action native A_FireRailgun(); action native A_FireRailgun();

View file

@ -201,6 +201,9 @@ weapons/plasmax dsfirxpl
weapons/bfgf dsbfg weapons/bfgf dsbfg
weapons/bfgx dsrxplod weapons/bfgx dsrxplod
weapons/railgf railgf1 weapons/railgf railgf1
weapons/grbnce dsbounce
weapons/grenlx dsgrnexp
weapons/grenlf dsglaunc
// Problem: weapons/rocklx needs to be unlimited but // Problem: weapons/rocklx needs to be unlimited but
// is also used for the MAP30 brain explosion. // is also used for the MAP30 brain explosion.