From 15681d058865ed54380e1bf7d25432d4a3d4dec6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 3 Jun 2006 12:30:11 +0000 Subject: [PATCH] - 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) --- docs/rh-log.txt | 13 +- src/actor.h | 1 + src/d_main.cpp | 9 +- src/doomstat.h | 1 + src/g_doom/a_painelemental.cpp | 2 +- src/g_hexen/a_clericplayer.cpp | 31 ++-- src/g_hexen/a_fighterplayer.cpp | 35 ++-- src/g_hexen/a_mageplayer.cpp | 43 ++--- src/g_level.cpp | 40 ++++- src/g_level.h | 3 + src/g_shared/a_pickups.cpp | 10 +- src/info.h | 1 + src/infodefaults.cpp | 3 +- src/infomacros.h | 1 + src/m_menu.cpp | 282 ++++++++++++++++---------------- src/p_acs.cpp | 9 +- src/p_acs.h | 4 + src/p_conversation.cpp | 15 +- src/p_conversation.h | 4 +- src/p_doors.cpp | 4 +- src/p_enemy.cpp | 8 +- src/p_floor.cpp | 4 +- src/p_lnspec.cpp | 122 +++++++++++++- src/p_lnspec.h | 2 + src/p_local.h | 2 +- src/p_map.cpp | 29 ++-- src/p_mobj.cpp | 14 +- src/p_sectors.cpp | 2 +- src/p_things.cpp | 18 +- src/p_trace.cpp | 2 +- src/s_sound.cpp | 8 +- src/thingdef.cpp | 10 ++ 32 files changed, 472 insertions(+), 260 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 38b12f2f9..61c1e2e69 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -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. diff --git a/src/actor.h b/src/actor.h index 68270043d..c6df4bade 100644 --- a/src/actor.h +++ b/src/actor.h @@ -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. diff --git a/src/d_main.cpp b/src/d_main.cpp index c0cbc09c5..eefef8e2e 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -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); diff --git a/src/doomstat.h b/src/doomstat.h index 99bc5ad4f..a80dead30 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -309,5 +309,6 @@ EXTERN_CVAR (Int, dmflags); EXTERN_CVAR (Int, dmflags2); // [BC] EXTERN_CVAR (Int, compatflags); +extern int i_compatflags; #endif diff --git a/src/g_doom/a_painelemental.cpp b/src/g_doom/a_painelemental.cpp index 997c7df75..21a68d000 100644 --- a/src/g_doom/a_painelemental.cpp +++ b/src/g_doom/a_painelemental.cpp @@ -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 diff --git a/src/g_hexen/a_clericplayer.cpp b/src/g_hexen/a_clericplayer.cpp index 4a7deab12..e0b22e06d 100644 --- a/src/g_hexen/a_clericplayer.cpp +++ b/src/g_hexen/a_clericplayer.cpp @@ -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); } diff --git a/src/g_hexen/a_fighterplayer.cpp b/src/g_hexen/a_fighterplayer.cpp index 24ca2d09a..846af5571 100644 --- a/src/g_hexen/a_fighterplayer.cpp +++ b/src/g_hexen/a_fighterplayer.cpp @@ -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); } diff --git a/src/g_hexen/a_mageplayer.cpp b/src/g_hexen/a_mageplayer.cpp index 48fdbe072..fcdda1f10 100644 --- a/src/g_hexen/a_mageplayer.cpp +++ b/src/g_hexen/a_mageplayer.cpp @@ -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); } diff --git a/src/g_level.cpp b/src/g_level.cpp index 3c3c4d3a5..0c6eaf631 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -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) diff --git a/src/g_level.h b/src/g_level.h index e5cadc7a5..d762c7379 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -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. diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 53edaf1c8..9046f43db 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -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; diff --git a/src/info.h b/src/info.h index fdf63075f..aa5470e19 100644 --- a/src/info.h +++ b/src/info.h @@ -282,6 +282,7 @@ enum ADEF_BounceFactor, ADEF_BounceCount, ADEF_FloatSpeed, + ADEF_RDFactor, ADEF_SpawnState, ADEF_SeeState, diff --git a/src/infodefaults.cpp b/src/infodefaults.cpp index 8feba61eb..6eacece45 100644 --- a/src/infodefaults.cpp +++ b/src/infodefaults.cpp @@ -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; diff --git a/src/infomacros.h b/src/infomacros.h index efe1ec5e1..d99ab0bf4 100644 --- a/src/infomacros.h +++ b/src/infomacros.h @@ -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) diff --git a/src/m_menu.cpp b/src/m_menu.cpp index 9f5b4a035..ced3fbb03 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -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) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 129835e7c..e03ee4d8e 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -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; diff --git a/src/p_acs.h b/src/p_acs.h index d5940b214..be61b79b8 100644 --- a/src/p_acs.h +++ b/src/p_acs.h @@ -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 }; diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 559f28b91..6e1c64b46 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -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 diff --git a/src/p_conversation.h b/src/p_conversation.h index 60aa21d8c..5705cb22f 100644 --- a/src/p_conversation.h +++ b/src/p_conversation.h @@ -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 diff --git a/src/p_doors.cpp b/src/p_doors.cpp index d06b6a4f7..b333edfb1 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -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 = §ors[secnum]; if (sec->ceilingdata != NULL) { diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 5899d6722..5d8ad6a9c 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -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); } diff --git a/src/p_floor.cpp b/src/p_floor.cpp index c1d35d6a7..294f74b72 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -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 } diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 03e7a2bf0..18813c925 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -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 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, diff --git a/src/p_lnspec.h b/src/p_lnspec.h index 6aa3531ed..ed3a7b17c 100644 --- a/src/p_lnspec.h +++ b/src/p_lnspec.h @@ -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, diff --git a/src/p_local.h b/src/p_local.h index 2118a5e76..a40a72840 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -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); diff --git a/src/p_map.cpp b/src/p_map.cpp index 26d4c776a..0a09a3d1b 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -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; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index b9b97e056..73fc374f1 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -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))) { diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index 816891c47..e305b72fc 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -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; diff --git a/src/p_things.cpp b/src/p_things.cpp index d4ad5bfaa..5b84ffac9 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -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)) diff --git a/src/p_trace.cpp b/src/p_trace.cpp index 69a0779cc..97999107a 100644 --- a/src/p_trace.cpp +++ b/src/p_trace.cpp @@ -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; } diff --git a/src/s_sound.cpp b/src/s_sound.cpp index e68770d9a..9c882d62e 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -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; } diff --git a/src/thingdef.cpp b/src/thingdef.cpp index 7aedf1405..6e98959ed 100644 --- a/src/thingdef.cpp +++ b/src/thingdef.cpp @@ -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) },