- Added a StartConversation special that allows automatic activation of Strife

dialogs.
- Added Thing_Raise special that allows Arch-Vile like resurrections from scripts
  or DECORATE states.
- Added a RadiusDamageFactor property for actors. This replaces the hard coded
  factor of 0.25 for Hexen's players.
- Added new SpawnProjectile function to ACS. It's the same as Thing_Projectile2
  but the projectile is specified by name, not spawn ID.
- Added MAPINFO option to set the compatibility flags. If this is done these
  explicit settings will take precedence over the compatflags CVAR.

SVN r164 (trunk)
This commit is contained in:
Christoph Oelckers 2006-06-03 12:30:11 +00:00
parent 4325fb8993
commit 15681d0588
32 changed files with 472 additions and 260 deletions

View file

@ -1,3 +1,15 @@
June 3, 2006 (Changes by Graf Zahl)
- Added a StartConversation special that allows automatic activation of Strife
dialogs.
- Added Thing_Raise special that allows Arch-Vile like resurrections from scripts
or DECORATE states.
- Added a RadiusDamageFactor property for actors. This replaces the hard coded
factor of 0.25 for Hexen's players.
- Added new SpawnProjectile function to ACS. It's the same as Thing_Projectile2
but the projectile is specified by name, not spawn ID.
- Added MAPINFO option to set the compatibility flags. If this is done these
explicit settings will take precedence over the compatflags CVAR.
May 31, 2006
- Merged in recent ZDBSP fixes:
- Added code to explicitly handle outputting overlapping segs when
@ -14,7 +26,6 @@ May 31, 2006
- Enabled reference optimization and COMDAT folding in the linker for a slightly
smaller executable.
May 31, 2006 (Changes by Graf Zahl)
- Fixed: Ammo items dropped by monsters that have a default amount of 1 didn't
contain any ammo at all.

View file

@ -403,6 +403,7 @@ enum
AMETA_WoundHealth, // health needed to enter wound state
AMETA_PoisonDamage, // Amount of poison damage
AMETA_FastSpeed, // Speed in fast mode
AMETA_RDFactor, // Radius damage factor
};
// Map Object definition.

View file

@ -372,7 +372,14 @@ CVAR (Flag, sv_barrelrespawn, dmflags2, DF2_BARRELS_RESPAWN);
//
//==========================================================================
CVAR (Int, compatflags, 0, CVAR_ARCHIVE|CVAR_SERVERINFO);
int i_compatflags; // internal compatflags composed from the compatflags CVAR and MAPINFO settings
CUSTOM_CVAR (Int, compatflags, 0, CVAR_ARCHIVE|CVAR_SERVERINFO)
{
if (level.info == NULL) i_compatflags = self;
else i_compatflags = (self & ~level.info->compatmask) | (level.info->compatflags & level.info->compatmask);
}
CVAR (Flag, compat_shortTex, compatflags, COMPATF_SHORTTEX);
CVAR (Flag, compat_stairs, compatflags, COMPATF_STAIRINDEX);
CVAR (Flag, compat_limitpain, compatflags, COMPATF_LIMITPAIN);

View file

@ -309,5 +309,6 @@ EXTERN_CVAR (Int, dmflags);
EXTERN_CVAR (Int, dmflags2); // [BC]
EXTERN_CVAR (Int, compatflags);
extern int i_compatflags;
#endif

View file

@ -132,7 +132,7 @@ void A_PainShootSkull (AActor *self, angle_t angle)
}
// [RH] make this optional
if (compatflags & COMPATF_LIMITPAIN)
if (i_compatflags & COMPATF_LIMITPAIN)
{
// count total number of skulls currently on the level
// if there are already 20 skulls on the level, don't spit another one

View file

@ -91,6 +91,7 @@ IMPLEMENT_ACTOR (AClericPlayer, Hexen, -1, 0)
PROP_RadiusFixed (16)
PROP_HeightFixed (64)
PROP_SpeedFixed (1)
PROP_RadiusdamageFactor(FRACUNIT/4)
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH|MF_FRIENDLY)
PROP_Flags2 (MF2_WINDTHRUST|MF2_FLOORCLIP|MF2_SLIDE|MF2_PASSMOBJ|MF2_TELESTOMP|MF2_PUSHWALL)
PROP_Flags3 (MF3_NOBLOCKMONST)
@ -193,19 +194,19 @@ bool AClericWeapon::TryPickup (AActor *toucher)
// somebody wants to use these weapons with either of those games.
if (toucher->IsKindOf (RUNTIME_CLASS(AFighterPlayer)) ||
toucher->IsKindOf (RUNTIME_CLASS(AMagePlayer)))
{ // Wrong class, but try to pick up for mana
if (ShouldStay())
{ // Can't pick up weapons for other classes in coop netplay
return false;
}
bool gaveSome = (NULL != AddAmmo (toucher, AmmoType1, AmmoGive1));
gaveSome |= (NULL != AddAmmo (toucher, AmmoType2, AmmoGive2));
if (gaveSome)
{
GoAwayAndDie ();
}
return gaveSome;
}
return Super::TryPickup (toucher);
{ // Wrong class, but try to pick up for mana
if (ShouldStay())
{ // Can't pick up weapons for other classes in coop netplay
return false;
}
bool gaveSome = (NULL != AddAmmo (toucher, AmmoType1, AmmoGive1));
gaveSome |= (NULL != AddAmmo (toucher, AmmoType2, AmmoGive2));
if (gaveSome)
{
GoAwayAndDie ();
}
return gaveSome;
}
return Super::TryPickup (toucher);
}

View file

@ -89,6 +89,7 @@ IMPLEMENT_ACTOR (AFighterPlayer, Hexen, -1, 0)
PROP_Mass (100)
PROP_PainChance (255)
PROP_SpeedFixed (1)
PROP_RadiusdamageFactor(FRACUNIT/4)
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH|MF_FRIENDLY)
PROP_Flags2 (MF2_WINDTHRUST|MF2_FLOORCLIP|MF2_SLIDE|MF2_PASSMOBJ|MF2_TELESTOMP|MF2_PUSHWALL)
PROP_Flags3 (MF3_NOBLOCKMONST)
@ -384,8 +385,8 @@ bool AFighterPlayer::DoHealingRadius (APlayerPawn *other)
gotSome = true;
}
}
if (gotSome)
{
if (gotSome)
{
S_Sound (other, CHAN_AUTO, "MysticIncant", 1, ATTN_NORM);
return true;
}
@ -402,19 +403,19 @@ bool AFighterWeapon::TryPickup (AActor *toucher)
// somebody wants to use these weapons with either of those games.
if (toucher->IsKindOf (RUNTIME_CLASS(AClericPlayer)) ||
toucher->IsKindOf (RUNTIME_CLASS(AMagePlayer)))
{ // Wrong class, but try to pick up for mana
if (ShouldStay())
{ // Can't pick up weapons for other classes in coop netplay
return false;
}
bool gaveSome = (NULL != AddAmmo (toucher, AmmoType1, AmmoGive1));
gaveSome |= (NULL != AddAmmo (toucher, AmmoType2, AmmoGive2));
if (gaveSome)
{
GoAwayAndDie ();
}
return gaveSome;
}
return Super::TryPickup (toucher);
{ // Wrong class, but try to pick up for mana
if (ShouldStay())
{ // Can't pick up weapons for other classes in coop netplay
return false;
}
bool gaveSome = (NULL != AddAmmo (toucher, AmmoType1, AmmoGive1));
gaveSome |= (NULL != AddAmmo (toucher, AmmoType2, AmmoGive2));
if (gaveSome)
{
GoAwayAndDie ();
}
return gaveSome;
}
return Super::TryPickup (toucher);
}

View file

@ -88,6 +88,7 @@ IMPLEMENT_ACTOR (AMagePlayer, Hexen, -1, 0)
PROP_RadiusFixed (16)
PROP_HeightFixed (64)
PROP_SpeedFixed (1)
PROP_RadiusdamageFactor(FRACUNIT/4)
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH|MF_FRIENDLY)
PROP_Flags2 (MF2_WINDTHRUST|MF2_FLOORCLIP|MF2_SLIDE|MF2_PASSMOBJ|MF2_TELESTOMP|MF2_PUSHWALL)
PROP_Flags3 (MF3_NOBLOCKMONST)
@ -162,14 +163,14 @@ fixed_t AMagePlayer::GetJumpZ ()
// Radius mana boost
bool AMagePlayer::DoHealingRadius (APlayerPawn *other)
{
int amount = 50 + (pr_manaradius() % 50);
if (GiveAmmo (RUNTIME_CLASS(AMana1), amount) ||
GiveAmmo (RUNTIME_CLASS(AMana2), amount))
{
int amount = 50 + (pr_manaradius() % 50);
if (GiveAmmo (RUNTIME_CLASS(AMana1), amount) ||
GiveAmmo (RUNTIME_CLASS(AMana2), amount))
{
S_Sound (other, CHAN_AUTO, "MysticIncant", 1, ATTN_NORM);
return true;
}
}
return false;
}
@ -199,19 +200,19 @@ bool AMageWeapon::TryPickup (AActor *toucher)
// somebody wants to use these weapons with either of those games.
if (toucher->IsKindOf (RUNTIME_CLASS(AFighterPlayer)) ||
toucher->IsKindOf (RUNTIME_CLASS(AClericPlayer)))
{ // Wrong class, but try to pick up for mana
if (ShouldStay())
{ // Can't pick up weapons for other classes in coop netplay
return false;
}
bool gaveSome = (NULL != AddAmmo (toucher, AmmoType1, AmmoGive1));
gaveSome |= (NULL != AddAmmo (toucher, AmmoType2, AmmoGive2));
if (gaveSome)
{
GoAwayAndDie ();
}
return gaveSome;
}
return Super::TryPickup (toucher);
{ // Wrong class, but try to pick up for mana
if (ShouldStay())
{ // Can't pick up weapons for other classes in coop netplay
return false;
}
bool gaveSome = (NULL != AddAmmo (toucher, AmmoType1, AmmoGive1));
gaveSome |= (NULL != AddAmmo (toucher, AmmoType2, AmmoGive2));
if (gaveSome)
{
GoAwayAndDie ();
}
return gaveSome;
}
return Super::TryPickup (toucher);
}

View file

@ -247,6 +247,19 @@ static const char *MapInfoMapLevel[] =
"allowcrouch",
"nocrouch",
"pausemusicinmenus",
"compat_shorttex",
"compat_stairs",
"compat_limitpain",
"compat_nopassover",
"compat_notossdrops",
"compat_useblocking",
"compat_nodoorlight",
"compat_ravenscroll",
"compat_soundtarget",
"compat_dehhealth",
"compat_trace",
"compat_dropoff",
NULL
};
@ -270,7 +283,8 @@ enum EMIType
MITYPE_RELLIGHT,
MITYPE_CLRBYTES,
MITYPE_REDIRECT,
MITYPE_SPECIALACTION
MITYPE_SPECIALACTION,
MITYPE_COMPATFLAG,
};
struct MapInfoHandler
@ -363,6 +377,18 @@ MapHandlers[] =
{ MITYPE_SCFLAGS, LEVEL_CROUCH_YES, ~LEVEL_CROUCH_NO },
{ MITYPE_SCFLAGS, LEVEL_CROUCH_NO, ~LEVEL_CROUCH_YES },
{ MITYPE_SCFLAGS, LEVEL_PAUSE_MUSIC_IN_MENUS, 0 },
{ MITYPE_COMPATFLAG, COMPATF_SHORTTEX},
{ MITYPE_COMPATFLAG, COMPATF_STAIRINDEX},
{ MITYPE_COMPATFLAG, COMPATF_LIMITPAIN},
{ MITYPE_COMPATFLAG, COMPATF_NO_PASSMOBJ},
{ MITYPE_COMPATFLAG, COMPATF_NOTOSSDROPS},
{ MITYPE_COMPATFLAG, COMPATF_USEBLOCKING},
{ MITYPE_COMPATFLAG, COMPATF_NODOORLIGHT},
{ MITYPE_COMPATFLAG, COMPATF_RAVENSCROLL},
{ MITYPE_COMPATFLAG, COMPATF_SOUNDTARGET},
{ MITYPE_COMPATFLAG, COMPATF_DEHHEALTH},
{ MITYPE_COMPATFLAG, COMPATF_TRACE},
{ MITYPE_COMPATFLAG, COMPATF_DROPOFF},
};
static const char *MapInfoClusterLevel[] =
@ -976,6 +1002,16 @@ static void ParseMapInfoLower (MapInfoHandler *handlers,
SC_SetCMode(false);
}
break;
case MITYPE_COMPATFLAG:
SC_MustGetNumber();
if (levelinfo != NULL)
{
if (sc_Number) levelinfo->compatflags |= (DWORD)handler->data1;
else levelinfo->compatflags &= ~ (DWORD)handler->data1;
levelinfo->compatmask |= (DWORD)handler->data1;
}
break;
}
}
if (levelinfo)
@ -2157,6 +2193,8 @@ void G_InitLevelLocals ()
dmflags = (dmflags & ~clear) | set;
compatflags.Callback();
NormalLight.ChangeFade (level.fadeto);
if (level.Scrolls != NULL)

View file

@ -134,6 +134,7 @@ struct level_info_s
char *level_name;
char fadetable[9];
SBYTE WallVertLight, WallHorizLight;
// TheDefaultLevelInfo initializes everything above this line.
int musicorder;
FCompressedMemFile *snapshot;
DWORD snapshotVer;
@ -149,6 +150,8 @@ struct level_info_s
float aircontrol;
int WarpTrans;
int airsupply;
DWORD compatflags;
DWORD compatmask;
// Redirection: If any player is carrying the specified item, then
// you go to the RedirectMap instead of this one.

View file

@ -180,7 +180,7 @@ bool P_GiveBody (AActor *actor, int num)
if (player != NULL)
{
max = ((compatflags&COMPATF_DEHHEALTH)? 100 : deh.MaxHealth) + player->stamina;
max = ((i_compatflags&COMPATF_DEHHEALTH)? 100 : deh.MaxHealth) + player->stamina;
if (player->morphTics)
{
max = MAXMORPHHEALTH;
@ -1484,9 +1484,9 @@ void ABasicArmor::Tick ()
case GAME_Strife:
Icon = TexMan.CheckForTexture (SavePercent == FRACUNIT/3 ? "I_ARM2" : "I_ARM1", FTexture::TEX_Any);
break;
default:
break;
default:
break;
}
}
@ -1768,7 +1768,7 @@ bool AHealth::TryPickup (AActor *other)
{
if (max == 0)
{
max = ((compatflags&COMPATF_DEHHEALTH)? 100 : deh.MaxHealth) + player->stamina;
max = ((i_compatflags&COMPATF_DEHHEALTH)? 100 : deh.MaxHealth) + player->stamina;
if (player->morphTics)
{
max = MAXMORPHHEALTH;

View file

@ -282,6 +282,7 @@ enum
ADEF_BounceFactor,
ADEF_BounceCount,
ADEF_FloatSpeed,
ADEF_RDFactor,
ADEF_SpawnState,
ADEF_SeeState,

View file

@ -216,6 +216,7 @@ static void ApplyActorDefault (int defnum, const char *datastr, int dataint)
case ADEF_MaxStepHeight: actor->MaxStepHeight = dataint; break;
case ADEF_BounceFactor: actor->bouncefactor = dataint; break;
case ADEF_BounceCount: actor->bouncecount = dataint; break;
case ADEF_RDFactor: sgClass->Meta.SetMetaFixed (AMETA_RDFactor, dataint); break;
case ADEF_SpawnState: actor->SpawnState = datastate; break;
case ADEF_SeeState: actor->SeeState = datastate; break;
@ -273,7 +274,7 @@ static void ApplyActorDefault (int defnum, const char *datastr, int dataint)
case ADEF_Ammo_BackpackAmount: ammo->BackpackAmount = dataint; break;
case ADEF_Ammo_BackpackMaxAmount:ammo->BackpackMaxAmount = dataint; break;
case ADEF_Ammo_DropAmount: sgClass->Meta.SetMetaInt (AIMETA_DropAmount, dataint);
case ADEF_Ammo_DropAmount: sgClass->Meta.SetMetaInt (AIMETA_DropAmount, dataint); break;
case ADEF_Weapon_Flags: weapon->WeaponFlags = dataint; break;
case ADEF_Weapon_FlagsSet: weapon->WeaponFlags |= dataint; break;

View file

@ -252,6 +252,7 @@ public:
#define PROP_MaxStepHeight(x) ADD_FIXD_PROP(ADEF_MaxStepHeight,x)
#define PROP_BounceFactor(x) ADD_LONG_PROP(ADEF_BounceFactor,x)
#define PROP_BounceCount(x) ADD_LONG_PROP(ADEF_BounceCount,x)
#define PROP_RadiusdamageFactor(x) ADD_LONG_PROP(ADEF_RDFactor,x)
#define PROP_SpawnState(x) ADD_BYTE_PROP(ADEF_SpawnState,x)
#define PROP_SeeState(x) ADD_BYTE_PROP(ADEF_SeeState,x)

View file

@ -282,21 +282,21 @@ static oldmenu_t HereticMainDef =
//
// HEXEN "NEW GAME" MENU
//
static oldmenuitem_t ClassItems[] =
{
{ 1,1, 'f', "FIGHTER", SCClass },
{ 1,1, 'c', "CLERIC", SCClass },
{ 1,1, 'm', "MAGE", SCClass },
{ 1,1, 'r', "RANDOM", SCClass } // [RH]
};
static oldmenu_t ClassMenu =
{
4, ClassItems,
DrawClassMenu,
66, 58,
0
};
static oldmenuitem_t ClassItems[] =
{
{ 1,1, 'f', "FIGHTER", SCClass },
{ 1,1, 'c', "CLERIC", SCClass },
{ 1,1, 'm', "MAGE", SCClass },
{ 1,1, 'r', "RANDOM", SCClass } // [RH]
};
static oldmenu_t ClassMenu =
{
4, ClassItems,
DrawClassMenu,
66, 58,
0
};
//
// EPISODE SELECT
@ -388,23 +388,23 @@ static oldmenu_t HereticSkillMenu =
//
// HEXEN SKILL SELECT
//
static oldmenuitem_t HexenSkillItems[] =
{
{ 1,1, '1', NULL, M_ChooseSkill },
{ 1,1, '2', NULL, M_ChooseSkill },
{ 1,1, '3', NULL, M_ChooseSkill },
{ 1,1, '4', NULL, M_ChooseSkill },
{ 1,1, '5', NULL, M_ChooseSkill }
};
static oldmenu_t HexenSkillMenu =
{
5, HexenSkillItems,
DrawHexenSkillMenu,
120, 44,
2
};
static oldmenuitem_t HexenSkillItems[] =
{
{ 1,1, '1', NULL, M_ChooseSkill },
{ 1,1, '2', NULL, M_ChooseSkill },
{ 1,1, '3', NULL, M_ChooseSkill },
{ 1,1, '4', NULL, M_ChooseSkill },
{ 1,1, '5', NULL, M_ChooseSkill }
};
static oldmenu_t HexenSkillMenu =
{
5, HexenSkillItems,
DrawHexenSkillMenu,
120, 44,
2
};
//
// [RH] Player Setup Menu
@ -1525,53 +1525,53 @@ void M_NewGame(int choice)
}
}
//==========================================================================
//
// DrawClassMenu
//
//==========================================================================
static void DrawClassMenu(void)
{
char name[9];
int classnum;
static const char boxLumpName[3][7] =
{
"M_FBOX",
"M_CBOX",
"M_MBOX"
};
static const char walkLumpName[3][10] =
{
"M_FWALK%d",
"M_CWALK%d",
"M_MWALK%d"
};
screen->DrawText (CR_UNTRANSLATED, 34, 24, "CHOOSE CLASS:", DTA_Clean, true, TAG_DONE);
classnum = itemOn;
if (classnum > 2)
{
classnum = (MenuTime>>2) % 3;
}
screen->DrawTexture (TexMan[boxLumpName[classnum]], 174, 8, DTA_Clean, true, TAG_DONE);
sprintf (name, walkLumpName[classnum], ((MenuTime >> 3) & 3) + 1);
screen->DrawTexture (TexMan[name], 174+24, 8+12, DTA_Clean, true, TAG_DONE);
}
//==========================================================================
//
// DrawClassMenu
//
//==========================================================================
static void DrawClassMenu(void)
{
char name[9];
int classnum;
static const char boxLumpName[3][7] =
{
"M_FBOX",
"M_CBOX",
"M_MBOX"
};
static const char walkLumpName[3][10] =
{
"M_FWALK%d",
"M_CWALK%d",
"M_MWALK%d"
};
screen->DrawText (CR_UNTRANSLATED, 34, 24, "CHOOSE CLASS:", DTA_Clean, true, TAG_DONE);
classnum = itemOn;
if (classnum > 2)
{
classnum = (MenuTime>>2) % 3;
}
screen->DrawTexture (TexMan[boxLumpName[classnum]], 174, 8, DTA_Clean, true, TAG_DONE);
sprintf (name, walkLumpName[classnum], ((MenuTime >> 3) & 3) + 1);
screen->DrawTexture (TexMan[name], 174+24, 8+12, DTA_Clean, true, TAG_DONE);
}
//---------------------------------------------------------------------------
//
// PROC DrawSkillMenu
//
//---------------------------------------------------------------------------
static void DrawHexenSkillMenu()
{
screen->DrawText (CR_UNTRANSLATED, 74, 16, "CHOOSE SKILL LEVEL:", DTA_Clean, true, TAG_DONE);
}
//---------------------------------------------------------------------------
//
// PROC DrawSkillMenu
//
//---------------------------------------------------------------------------
static void DrawHexenSkillMenu()
{
screen->DrawText (CR_UNTRANSLATED, 74, 16, "CHOOSE SKILL LEVEL:", DTA_Clean, true, TAG_DONE);
}
//
// M_Episode
@ -1645,70 +1645,70 @@ void M_Episode (int choice)
M_SetupNextMenu (&HereticSkillMenu);
}
//==========================================================================
//
// SCClass
//
//==========================================================================
static void SCClass (int option)
{
if (netgame)
{
//==========================================================================
//
// SCClass
//
//==========================================================================
static void SCClass (int option)
{
if (netgame)
{
M_StartMessage (GStrings("NEWGAME"), NULL, false);
return;
}
MenuPClass = option < 3 ? option : -1;
switch (MenuPClass)
{
case 0/*PCLASS_FIGHTER*/:
HexenSkillMenu.x = 120;
HexenSkillItems[0].name = "SQUIRE";
HexenSkillItems[1].name = "KNIGHT";
HexenSkillItems[2].name = "WARRIOR";
HexenSkillItems[3].name = "BERSERKER";
HexenSkillItems[4].name = "TITAN";
break;
case 1/*PCLASS_CLERIC*/:
HexenSkillMenu.x = 116;
HexenSkillItems[0].name = "ALTAR BOY";
HexenSkillItems[1].name = "ACOLYTE";
HexenSkillItems[2].name = "PRIEST";
HexenSkillItems[3].name = "CARDINAL";
HexenSkillItems[4].name = "POPE";
break;
case 2/*PCLASS_MAGE*/:
HexenSkillMenu.x = 112;
HexenSkillItems[0].name = "APPRENTICE";
HexenSkillItems[1].name = "ENCHANTER";
HexenSkillItems[2].name = "SORCERER";
HexenSkillItems[3].name = "WARLOCK";
HexenSkillItems[4].name = "ARCHMAGE";
break;
case -1/*random*/: // [RH]
// Since Hexen is "Heretic 2", use the Heretic skill
// names when not playing as a specific class.
HexenSkillMenu.x = HereticSkillMenu.x;
HexenSkillItems[0].name = HereticSkillItems[0].name;
HexenSkillItems[1].name = HereticSkillItems[1].name;
HexenSkillItems[2].name = HereticSkillItems[2].name;
HexenSkillItems[3].name = HereticSkillItems[3].name;
HexenSkillItems[4].name = HereticSkillItems[4].name;
break;
}
if (EpiDef.numitems > 1)
{
M_SetupNextMenu (&EpiDef);
}
else if (!EpisodeNoSkill[0])
{
M_SetupNextMenu (&HexenSkillMenu);
}
else
{
M_ChooseSkill(2);
}
}
return;
}
MenuPClass = option < 3 ? option : -1;
switch (MenuPClass)
{
case 0/*PCLASS_FIGHTER*/:
HexenSkillMenu.x = 120;
HexenSkillItems[0].name = "SQUIRE";
HexenSkillItems[1].name = "KNIGHT";
HexenSkillItems[2].name = "WARRIOR";
HexenSkillItems[3].name = "BERSERKER";
HexenSkillItems[4].name = "TITAN";
break;
case 1/*PCLASS_CLERIC*/:
HexenSkillMenu.x = 116;
HexenSkillItems[0].name = "ALTAR BOY";
HexenSkillItems[1].name = "ACOLYTE";
HexenSkillItems[2].name = "PRIEST";
HexenSkillItems[3].name = "CARDINAL";
HexenSkillItems[4].name = "POPE";
break;
case 2/*PCLASS_MAGE*/:
HexenSkillMenu.x = 112;
HexenSkillItems[0].name = "APPRENTICE";
HexenSkillItems[1].name = "ENCHANTER";
HexenSkillItems[2].name = "SORCERER";
HexenSkillItems[3].name = "WARLOCK";
HexenSkillItems[4].name = "ARCHMAGE";
break;
case -1/*random*/: // [RH]
// Since Hexen is "Heretic 2", use the Heretic skill
// names when not playing as a specific class.
HexenSkillMenu.x = HereticSkillMenu.x;
HexenSkillItems[0].name = HereticSkillItems[0].name;
HexenSkillItems[1].name = HereticSkillItems[1].name;
HexenSkillItems[2].name = HereticSkillItems[2].name;
HexenSkillItems[3].name = HereticSkillItems[3].name;
HexenSkillItems[4].name = HereticSkillItems[4].name;
break;
}
if (EpiDef.numitems > 1)
{
M_SetupNextMenu (&EpiDef);
}
else if (!EpisodeNoSkill[0])
{
M_SetupNextMenu (&HexenSkillMenu);
}
else
{
M_ChooseSkill(2);
}
}
void M_Options (int choice)

View file

@ -4294,7 +4294,14 @@ int DLevelScript::RunScript ()
// Like Thing_Projectile(Gravity) specials, but you can give the
// projectile a TID.
// Thing_Projectile2 (tid, type, angle, speed, vspeed, gravity, newtid);
P_Thing_Projectile (STACK(7), STACK(6), ((angle_t)(STACK(5)<<24)),
P_Thing_Projectile (STACK(7), STACK(6), NULL, ((angle_t)(STACK(5)<<24)),
STACK(4)<<(FRACBITS-3), STACK(3)<<(FRACBITS-3), 0, NULL, STACK(2), STACK(1), false);
sp -= 7;
break;
case PCD_SPAWNPROJECTILE:
// Same, but takes an actor name instead of a spawn ID.
P_Thing_Projectile (STACK(7), 0, FBehavior::StaticLookupString (STACK(6)), ((angle_t)(STACK(5)<<24)),
STACK(4)<<(FRACBITS-3), STACK(3)<<(FRACBITS-3), 0, NULL, STACK(2), STACK(1), false);
sp -= 7;
break;

View file

@ -478,6 +478,10 @@ public:
PCD_PRINTWORLDCHARARRAY,
PCD_PRINTGLOBALCHARARRAY, // [JB] end of new p-codes
PCD_SETACTORANGLE, // [GRB]
PCD_GRABINPUT, // Unused but acc defines them
PCD_SETMOUSEPOINTER, // "
PCD_MOVEMOUSEPOINTER, // "
PCD_SPAWNPROJECTILE,
PCODE_COMMAND_COUNT
};

View file

@ -84,6 +84,7 @@ static FStrifeDialogueNode *CurNode, *PrevNode;
static brokenlines_t *DialogueLines;
static AActor *ConversationNPC, *ConversationPC;
static angle_t ConversationNPCAngle;
static bool ConversationFaceTalker;
#define NUM_RANDOM_LINES 10
#define NUM_RANDOM_GOODBYES 3
@ -601,7 +602,7 @@ CUSTOM_CVAR(Float, dlg_musicvolume, 1.0f, CVAR_ARCHIVE)
//
//============================================================================
void P_StartConversation (AActor *npc, AActor *pc)
void P_StartConversation (AActor *npc, AActor *pc, bool facetalker)
{
FStrifeDialogueReply *reply;
menuitem_t item;
@ -629,9 +630,13 @@ void P_StartConversation (AActor *npc, AActor *pc)
{
npc->target = pc;
}
ConversationFaceTalker = facetalker;
ConversationNPCAngle = npc->angle;
A_FaceTarget (npc);
pc->angle = R_PointToAngle2 (pc->x, pc->y, npc->x, npc->y);
if (facetalker)
{
A_FaceTarget (npc);
pc->angle = R_PointToAngle2 (pc->x, pc->y, npc->x, npc->y);
}
// Check if we should jump to another node
while (CurNode->ItemCheck[0] != NULL)
@ -742,7 +747,7 @@ void P_ResumeConversation ()
{
if (ConversationPC != NULL && ConversationNPC != NULL)
{
P_StartConversation (ConversationNPC, ConversationPC);
P_StartConversation (ConversationNPC, ConversationPC, ConversationFaceTalker);
}
}
@ -962,7 +967,7 @@ static void PickConversationReply ()
ConversationNPC->Conversation = StrifeDialogues[rootnode - reply->NextNode - 1];
if (gameaction != ga_slideshow)
{
P_StartConversation (ConversationNPC, players[consoleplayer].mo);
P_StartConversation (ConversationNPC, players[consoleplayer].mo, ConversationFaceTalker);
return;
}
else

View file

@ -59,7 +59,7 @@ extern const PClass *StrifeTypes[999];
void P_LoadStrifeConversations (const char *mapname);
void P_FreeStrifeConversations ();
void P_StartConversation (AActor *npc, AActor *pc);
void P_StartConversation (AActor *npc, AActor *pc, bool facetalker);
void P_ResumeConversation ();
#endif
#endif

View file

@ -302,7 +302,7 @@ DDoor::DDoor (sector_t *sec, EVlDoor type, fixed_t speed, int delay, int lightTa
vertex_t *spot;
fixed_t height;
if (compatflags & COMPATF_NODOORLIGHT)
if (i_compatflags & COMPATF_NODOORLIGHT)
{
m_LightTag = 0;
}
@ -779,7 +779,7 @@ bool EV_SlidingDoor (line_t *line, AActor *actor, int tag, int speed, int delay)
}
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
{
{
sec = &sectors[secnum];
if (sec->ceilingdata != NULL)
{

View file

@ -775,7 +775,7 @@ void P_NewChaseDir(AActor * actor)
if (actor->floorz - actor->dropoffz > actor->MaxDropOffHeight &&
actor->z <= actor->floorz && !(actor->flags & MF_DROPOFF) &&
!(actor->flags2 & MF2_ONMOBJ) &&
!(actor->flags & MF_FLOAT) && !(compatflags & COMPATF_DROPOFF))
!(actor->flags & MF_FLOAT) && !(i_compatflags & COMPATF_DROPOFF))
{
a.thing = actor;
a.deltax = a.deltay = 0;
@ -1537,7 +1537,7 @@ void A_Look (AActor *actor)
}
else
{
targ = (compatflags & COMPATF_SOUNDTARGET)? actor->Sector->SoundTarget : actor->LastHeard;
targ = (i_compatflags & COMPATF_SOUNDTARGET)? actor->Sector->SoundTarget : actor->LastHeard;
// [RH] If the soundtarget is dead, don't chase it
if (targ != NULL && targ->health <= 0)
@ -2195,7 +2195,7 @@ AInventory *P_DropItem (AActor *source, const PClass *type, int special, int cha
fixed_t spawnz;
spawnz = source->z;
if (!(compatflags & COMPATF_NOTOSSDROPS))
if (!(i_compatflags & COMPATF_NOTOSSDROPS))
{
int style = sv_dropstyle;
if (style==0) style= (gameinfo.gametype == GAME_Strife)? 2:1;
@ -2235,7 +2235,7 @@ AInventory *P_DropItem (AActor *source, const PClass *type, int special, int cha
return NULL;
}
}
if (!(compatflags & COMPATF_NOTOSSDROPS))
if (!(i_compatflags & COMPATF_NOTOSSDROPS))
{
P_TossItem (mo);
}

View file

@ -698,7 +698,7 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line,
persteptime = FixedDiv (stairsize, speed) >> FRACBITS;
int (* FindSector) (int tag, int start) =
(compatflags & COMPATF_STAIRINDEX)? P_FindSectorFromTagLinear : P_FindSectorFromTag;
(i_compatflags & COMPATF_STAIRINDEX)? P_FindSectorFromTagLinear : P_FindSectorFromTag;
// check if a manual trigger, if so do just the sector on the backside
if (tag == 0)
@ -862,7 +862,7 @@ manual_stair:
{
return rtn;
}
if (!(compatflags & COMPATF_STAIRINDEX))
if (!(i_compatflags & COMPATF_STAIRINDEX))
{
secnum = osecnum; //jff 3/4/98 restore loop index
}

View file

@ -50,6 +50,7 @@
#include "a_keys.h"
#include "gi.h"
#include "m_random.h"
#include "p_conversation.h"
#include "a_strifeglobal.h"
#define FUNC(a) static int a (line_t *ln, AActor *it, bool backSide, \
@ -1107,14 +1108,14 @@ FUNC(LS_Thing_Damage)
FUNC(LS_Thing_Projectile)
// Thing_Projectile (tid, type, angle, speed, vspeed)
{
return P_Thing_Projectile (arg0, arg1, BYTEANGLE(arg2), arg3<<(FRACBITS-3),
return P_Thing_Projectile (arg0, arg1, NULL, BYTEANGLE(arg2), arg3<<(FRACBITS-3),
arg4<<(FRACBITS-3), 0, NULL, 0, 0, false);
}
FUNC(LS_Thing_ProjectileGravity)
// Thing_ProjectileGravity (tid, type, angle, speed, vspeed)
{
return P_Thing_Projectile (arg0, arg1, BYTEANGLE(arg2), arg3<<(FRACBITS-3),
return P_Thing_Projectile (arg0, arg1, NULL, BYTEANGLE(arg2), arg3<<(FRACBITS-3),
arg4<<(FRACBITS-3), 0, NULL, 1, 0, false);
}
@ -1284,13 +1285,13 @@ FUNC(LS_Thing_Hate)
FUNC(LS_Thing_ProjectileAimed)
// Thing_ProjectileAimed (tid, type, speed, target, newtid)
{
return P_Thing_Projectile (arg0, arg1, 0, arg2<<(FRACBITS-3), 0, arg3, it, 0, arg4, false);
return P_Thing_Projectile (arg0, arg1, NULL, 0, arg2<<(FRACBITS-3), 0, arg3, it, 0, arg4, false);
}
FUNC(LS_Thing_ProjectileIntercept)
// Thing_ProjectileIntercept (tid, type, speed, target, newtid)
{
return P_Thing_Projectile (arg0, arg1, 0, arg2<<(FRACBITS-3), 0, arg3, it, 0, arg4, true);
return P_Thing_Projectile (arg0, arg1, NULL, 0, arg2<<(FRACBITS-3), 0, arg3, it, 0, arg4, true);
}
// [BC] added newtid for next two
@ -1312,6 +1313,81 @@ FUNC(LS_Thing_SpawnFacing)
return P_Thing_Spawn (arg0, arg1, ANGLE_MAX, arg2 ? false : true, arg3);
}
static bool DoThingRaise(AActor * thing)
{
if (thing == NULL)
return false; // not valid
if (!(thing->flags & MF_CORPSE) )
return true; // not a corpse
if (thing->tics != -1)
return true; // not lying still yet
if (thing->RaiseState == NULL)
return true; // monster doesn't have a raise state
AActor *info = thing->GetDefault ();
thing->momx = thing->momy = 0;
// [RH] Check against real height and radius
fixed_t oldheight = thing->height;
fixed_t oldradius = thing->radius;
int oldflags = thing->flags;
thing->flags |= MF_SOLID;
thing->height = info->height; // [RH] Use real height
thing->radius = info->radius; // [RH] Use real radius
if (!P_CheckPosition (thing, thing->x, thing->y))
{
thing->flags = oldflags;
thing->radius = oldradius;
thing->height = oldheight;
return false;
}
S_Sound (thing, CHAN_BODY, "vile/raise", 1, ATTN_IDLE);
thing->SetState (info->RaiseState);
thing->flags = info->flags;
thing->flags2 = info->flags2;
thing->flags3 = info->flags3;
thing->flags4 = info->flags4;
thing->health = info->health;
thing->target = NULL;
thing->lastenemy = NULL;
// [RH] If it's a monster, it gets to count as another kill
if (thing->CountsAsKill())
{
level.total_monsters++;
}
return true;
}
FUNC(LS_Thing_Raise)
// Thing_Raise(tid)
{
AActor * target;
bool ok = false;
if (arg0==0)
{
ok = DoThingRaise (it);
}
else
{
TActorIterator<AActor> iterator (arg0);
while ( (target = iterator.Next ()) )
{
ok |= DoThingRaise(target);
}
}
return ok;
}
FUNC(LS_Thing_SetGoal)
// Thing_SetGoal (tid, goal, delay, chasegoal)
{
@ -2555,6 +2631,40 @@ FUNC(LS_GlassBreak)
return false;
}
FUNC(LS_StartConversation)
// StartConversation (tid, facetalker)
{
FActorIterator iterator (arg0);
AActor *target = iterator.Next();
// Only living players are allowed to start conversations
if (it == NULL || it->player == NULL || it->player->mo != it || it->health<=0)
{
return false;
}
// Dead things can't talk.
if (target->health <= 0)
{
return false;
}
// Fighting things don't talk either.
if (target->flags4 & MF4_INCOMBAT)
{
return false;
}
if (target->Conversation != NULL)
{
// Give the NPC a chance to play a brief animation
target->ConversationAnimation (0);
P_StartConversation (target, it, !!arg1);
return true;
}
return false;
}
lnSpecFunc LineSpecials[256] =
{
LS_NOP,
@ -2574,8 +2684,8 @@ lnSpecFunc LineSpecials[256] =
LS_Door_Animated,
LS_Autosave,
LS_NOP, // Transfer_WallLight
LS_NOP, // 17
LS_NOP, // 18
LS_Thing_Raise,
LS_StartConversation,
LS_NOP, // 19
LS_Floor_LowerByValue,
LS_Floor_LowerToLowest,

View file

@ -57,6 +57,8 @@ typedef enum {
Autosave = 15, // [RH] Save the game *now*
Transfer_WallLight = 16,
Thing_Raise = 17,
StartConversation = 18,
Floor_LowerByValue = 20,
Floor_LowerToLowest = 21,

View file

@ -126,7 +126,7 @@ void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz);
extern const PClass *SpawnableThings[MAX_SPAWNABLES];
bool P_Thing_Spawn (int tid, int type, angle_t angle, bool fog, int newtid);
bool P_Thing_Projectile (int tid, int type, angle_t angle,
bool P_Thing_Projectile (int tid, int type, const char * type_name, angle_t angle,
fixed_t speed, fixed_t vspeed, int dest, AActor *forcedest, int gravity, int newtid,
bool leadTarget);
bool P_Thing_Move (int tid, int mapspot, bool fog);

View file

@ -834,7 +834,7 @@ BOOL PIT_CheckThing (AActor *thing)
}
BlockingMobj = thing;
topz = thing->z + thing->height;
if (!(compatflags & COMPATF_NO_PASSMOBJ) && !(tmthing->flags & (MF_FLOAT|MF_MISSILE|MF_SKULLFLY|MF_NOGRAVITY)) &&
if (!(i_compatflags & COMPATF_NO_PASSMOBJ) && !(tmthing->flags & (MF_FLOAT|MF_MISSILE|MF_SKULLFLY|MF_NOGRAVITY)) &&
(thing->flags & MF_SOLID) && (thing->flags4 & MF4_ACTLIKEBRIDGE))
{
// [RH] Let monsters walk on actors as well as floors
@ -856,7 +856,7 @@ BOOL PIT_CheckThing (AActor *thing)
}
// [RH] If the other thing is a bridge, then treat the moving thing as if it had MF2_PASSMOBJ, so
// you can use a scrolling floor to move scenery items underneath a bridge.
if ((tmthing->flags2 & MF2_PASSMOBJ || thing->flags4 & MF4_ACTLIKEBRIDGE) && !(compatflags & COMPATF_NO_PASSMOBJ))
if ((tmthing->flags2 & MF2_PASSMOBJ || thing->flags4 & MF4_ACTLIKEBRIDGE) && !(i_compatflags & COMPATF_NO_PASSMOBJ))
{ // check if a mobj passed over/under another object
if (tmthing->flags3 & thing->flags3 & MF3_DONTOVERLAP)
{ // Some things prefer not to overlap each other, if possible
@ -1329,7 +1329,7 @@ BOOL P_CheckPosition (AActor *thing, fixed_t x, fixed_t y)
// other things in the blocks and see if we hit something that is
// definitely blocking. Otherwise, we need to check the lines, or we
// could end up stuck inside a wall.
if (BlockingMobj == NULL || (compatflags & COMPATF_NO_PASSMOBJ))
if (BlockingMobj == NULL || (i_compatflags & COMPATF_NO_PASSMOBJ))
{ // Thing slammed into something; don't let it move now.
thing->height = realheight;
return false;
@ -1593,7 +1593,7 @@ BOOL P_TryMove (AActor *thing, fixed_t x, fixed_t y,
goto pushline;
}
}
if (!(tmthing->flags2 & MF2_PASSMOBJ) || (compatflags & COMPATF_NO_PASSMOBJ))
if (!(tmthing->flags2 & MF2_PASSMOBJ) || (i_compatflags & COMPATF_NO_PASSMOBJ))
{
thing->z = oldz;
return false;
@ -3159,7 +3159,7 @@ BOOL PTR_UseTraverse (intercept_t *in)
{
// Give the NPC a chance to play a brief animation
in->d.thing->ConversationAnimation (0);
P_StartConversation (in->d.thing, usething);
P_StartConversation (in->d.thing, usething, true);
return false;
}
return true;
@ -3189,7 +3189,7 @@ blocked:
trace.y + FixedMul (trace.dy, in->frac));
}
if (openrange <= 0 ||
(in->d.line->special != 0 && (compatflags & COMPATF_USEBLOCKING)))
(in->d.line->special != 0 && (i_compatflags & COMPATF_USEBLOCKING)))
{
// [RH] Give sector a chance to intercept the use
@ -3233,7 +3233,7 @@ blocked:
//[RH] And now I've changed it again. If the line is of type
// SPAC_USE, then it eats the use. Everything else passes
// it through, including SPAC_USETHROUGH.
if (compatflags & COMPATF_USEBLOCKING)
if (i_compatflags & COMPATF_USEBLOCKING)
{
return GET_SPAC(in->d.line->flags) == SPAC_USETHROUGH;
}
@ -3508,10 +3508,8 @@ BOOL PIT_RadiusAttack (AActor *thing)
{
points = points * splashfactor;
}
if (thing->player && gameinfo.gametype == GAME_Hexen)
{
points = points * 0.25f;
}
points *= thing->GetClass()->Meta.GetMetaFixed(AMETA_RDFactor, FRACUNIT)/(float)FRACUNIT;
if (points > 0.f && P_CheckSight (thing, bombspot, 1))
{ // OK to damage; target is in direct path
float momz;
@ -3569,12 +3567,13 @@ BOOL PIT_RadiusAttack (AActor *thing)
{ // OK to damage; target is in direct path
int damage = Scale (bombdamage, bombdistance-dist, bombdistance);
damage = (int)((float)damage * splashfactor);
if (thing->player && gameinfo.gametype == GAME_Hexen)
damage = Scale(damage, thing->GetClass()->Meta.GetMetaFixed(AMETA_RDFactor, FRACUNIT), FRACUNIT);
if (damage > 0)
{
damage >>= 2;
P_DamageMobj (thing, bombspot, bombsource, damage, bombmod);
P_TraceBleed (damage, thing, bombspot);
}
P_DamageMobj (thing, bombspot, bombsource, damage, bombmod);
P_TraceBleed (damage, thing, bombspot);
}
}
return true;

View file

@ -1313,7 +1313,7 @@ void P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
// that large thrusts can't propel an actor through a wall, because wall
// running depends on the player's original movement continuing even after
// it gets blocked.
if (mo->player != NULL && (compatflags & COMPATF_WALLRUN) || (mo->waterlevel >= 1) ||
if (mo->player != NULL && (i_compatflags & COMPATF_WALLRUN) || (mo->waterlevel >= 1) ||
(mo->player != NULL && mo->player->crouchfactor < FRACUNIT*3/4))
{
// preserve the direction instead of clamping x and y independently.
@ -1456,7 +1456,7 @@ void P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
{
mo->momz = WATER_JUMP_SPEED;
}
if (player && (compatflags & COMPATF_WALLRUN))
if (player && (i_compatflags & COMPATF_WALLRUN))
{
// [RH] Here is the key to wall running: The move is clipped using its full speed.
// If the move is done a second time (because it was too fast for one move), it
@ -1474,7 +1474,7 @@ void P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
}
else
{
if (!player || !(compatflags & COMPATF_WALLRUN))
if (!player || !(i_compatflags & COMPATF_WALLRUN))
{
xmove = mo->momx;
ymove = mo->momy;
@ -2595,7 +2595,7 @@ void AActor::Tick ()
scrolltype <= Scroll_SouthWest_Fast)
{ // Hexen scroll special
scrolltype -= Scroll_North_Slow;
if (compatflags&COMPATF_RAVENSCROLL)
if (i_compatflags&COMPATF_RAVENSCROLL)
{
angle_t fineangle = HexenScrollDirs[scrolltype / 3] * 32;
fixed_t carryspeed = DivScale32 (HexenSpeedMuls[scrolltype % 3], 32*CARRYFACTOR);
@ -2615,7 +2615,7 @@ void AActor::Tick ()
scrolltype -= Carry_East5;
byte dir = HereticScrollDirs[scrolltype / 5];
fixed_t carryspeed = DivScale32 (HereticSpeedMuls[scrolltype % 5], 32*CARRYFACTOR);
if (scrolltype<=Carry_East35 && !(compatflags&COMPATF_RAVENSCROLL))
if (scrolltype<=Carry_East35 && !(i_compatflags&COMPATF_RAVENSCROLL))
{
// Use speeds that actually match the scrolling textures!
carryspeed = (1 << ((scrolltype%5) + FRACBITS-1));
@ -2625,7 +2625,7 @@ void AActor::Tick ()
}
else if (scrolltype == dScroll_EastLavaDamage)
{ // Special Heretic scroll special
if (compatflags&COMPATF_RAVENSCROLL)
if (i_compatflags&COMPATF_RAVENSCROLL)
{
scrollx += DivScale32 (28, 32*CARRYFACTOR);
}
@ -2762,7 +2762,7 @@ void AActor::Tick ()
(z - FloatBobOffsets[(FloatBobPhase + level.maptime) & 63] != floorz)
)))
{ // Handle Z momentum and gravity
if (((flags2 & MF2_PASSMOBJ) || (flags & MF_SPECIAL)) && !(compatflags & COMPATF_NO_PASSMOBJ))
if (((flags2 & MF2_PASSMOBJ) || (flags & MF_SPECIAL)) && !(i_compatflags & COMPATF_NO_PASSMOBJ))
{
if (!(onmo = P_CheckOnmobj (this)))
{

View file

@ -451,7 +451,7 @@ fixed_t sector_t::FindHighestCeilingSurrounding (vertex_t **v) const
static inline void CheckShortestTex (int texnum, fixed_t &minsize)
{
if (texnum > 0 || (texnum == 0 && (compatflags & COMPATF_SHORTTEX)))
if (texnum > 0 || (texnum == 0 && (i_compatflags & COMPATF_SHORTTEX)))
{
FTexture *tex = TexMan[texnum];
int yscale = tex->ScaleY ? tex->ScaleY : 8;

View file

@ -150,7 +150,7 @@ bool P_Thing_Move (int tid, int mapspot, bool fog)
return false;
}
bool P_Thing_Projectile (int tid, int type, angle_t angle,
bool P_Thing_Projectile (int tid, int type, const char * type_name, angle_t angle,
fixed_t speed, fixed_t vspeed, int dest, AActor *forcedest, int gravity, int newtid,
bool leadTarget)
{
@ -161,11 +161,19 @@ bool P_Thing_Projectile (int tid, int type, angle_t angle,
float fspeed = float(speed);
int defflags3;
if (type >= MAX_SPAWNABLES)
return false;
if (type_name == NULL)
{
if (type >= MAX_SPAWNABLES)
return false;
if ((kind = SpawnableThings[type]) == NULL)
return false;
if ((kind = SpawnableThings[type]) == NULL)
return false;
}
else
{
if ((kind = PClass::FindClass(type_name)) == NULL)
return false;
}
defflags3 = GetDefaultByType (kind)->flags3;
if ((defflags3 & MF3_ISMONSTER) && (dmflags & DF_NO_MONSTERS))

View file

@ -171,7 +171,7 @@ static BOOL PTR_TraceIterator (intercept_t *in)
// For backwards compatibility: Ignore lines with the same sector on both sides.
// This is the way Doom.exe did it and some WADs (e.g. Alien Vendetta MAP15 needs it.
if (compatflags & COMPATF_TRACE)
if (i_compatflags & COMPATF_TRACE)
{
return true;
}

View file

@ -624,13 +624,13 @@ static void S_StartSound (fixed_t *pt, AActor *mover, int channel,
{
pt = NULL;
}
if (compatflags & COMPATF_MAGICSILENCE)
if (i_compatflags & COMPATF_MAGICSILENCE)
{ // For people who just can't play without a silent BFG.
channel = 1;
}
else
{
if ((channel & CHAN_MAYBE_LOCAL) && (compatflags & COMPATF_SILENTPICKUP))
if ((channel & CHAN_MAYBE_LOCAL) && (i_compatflags & COMPATF_SILENTPICKUP))
{
if (mover != 0 && mover != players[consoleplayer].camera)
{
@ -1108,7 +1108,7 @@ void S_StopSound (fixed_t *pt, int channel)
{
if (Channel[i].sfxinfo &&
((pt == NULL && Channel[i].pt == &Channel[i].x) || Channel[i].pt == pt) &&
((compatflags & COMPATF_MAGICSILENCE) || Channel[i].entchannel == channel))
((i_compatflags & COMPATF_MAGICSILENCE) || Channel[i].entchannel == channel))
{
S_StopChannel (i);
}
@ -1208,7 +1208,7 @@ bool S_IsActorPlayingSomething (AActor *actor, int channel)
{
int i;
if (compatflags & COMPATF_MAGICSILENCE)
if (i_compatflags & COMPATF_MAGICSILENCE)
{
channel = 0;
}

View file

@ -2954,6 +2954,15 @@ static void ActorFastSpeed (AActor *defaults, Baggage &bag)
bag.Info->Class->Meta.SetMetaFixed (AMETA_FastSpeed, fixed_t(sc_Float*FRACUNIT));
}
//==========================================================================
//
//==========================================================================
static void ActorRadiusDamageFactor (AActor *defaults, Baggage &bag)
{
SC_MustGetFloat();
bag.Info->Class->Meta.SetMetaFixed (AMETA_RDFactor, fixed_t(sc_Float*FRACUNIT));
}
//==========================================================================
//
//==========================================================================
@ -3572,6 +3581,7 @@ static const ActorProps props[] =
{ "projectile", ActorProjectile, RUNTIME_CLASS(AActor) },
{ "puzzleitem.number", (apf)PuzzleitemNumber, RUNTIME_CLASS(APuzzleItem) },
{ "radius", ActorRadius, RUNTIME_CLASS(AActor) },
{ "radiusdamagefactor", ActorRadiusDamageFactor, RUNTIME_CLASS(AActor) },
{ "raise", ActorRaiseState, RUNTIME_CLASS(AActor) },
{ "reactiontime", ActorReactionTime, RUNTIME_CLASS(AActor) },
{ "renderstyle", ActorRenderStyle, RUNTIME_CLASS(AActor) },