mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2025-02-20 10:22:41 +00:00
Merge branch 'master' of https://github.com/coelckers/gzdoom
This commit is contained in:
commit
13c3e512d7
26 changed files with 261 additions and 78 deletions
|
@ -197,6 +197,7 @@ Note: All <bool> fields default to false unless mentioned otherwise.
|
|||
desaturation = <float>; // Color desaturation factor. 0 = none, 1 = full, default = 0.
|
||||
silent = <bool>; // Actors in this sector make no sound,
|
||||
nofallingdamage = <bool>; // Falling damage is disabled in this sector
|
||||
noattack = <bool>; // Blocks monster attacks in this sector.
|
||||
dropactors = <bool>; // Actors drop with instantly moving floors (*)
|
||||
norespawn = <bool>; // Players can not respawn in this sector
|
||||
soundsequence = <string>; // The sound sequence to play when this sector moves. Placing a
|
||||
|
@ -262,8 +263,8 @@ Note: All <bool> fields default to false unless mentioned otherwise.
|
|||
gravity = <float>; // Set per-actor gravity. Positive values are multiplied with the class's property,
|
||||
// negative values are used as their absolute. Default = 1.0.
|
||||
|
||||
health = <int>; // Set per-actor health. Positive values are multiplied with the class's property,
|
||||
// negative values are used as their absolute. Default = 1.
|
||||
health = <int>; // Set per-actor health as an absolute value. Default = actor default.
|
||||
healthfactor = <float>; // Set per-actor health as a factor to the original. Default = 1.
|
||||
|
||||
renderstyle = <string>; // Set per-actor render style, overriding the class default. Possible values can be "normal",
|
||||
// "none", "add" or "additive", "subtract" or "subtractive", "stencil", "translucentstencil",
|
||||
|
|
|
@ -47,7 +47,7 @@ DEFINE_SPECIAL(Ceiling_CrushRaiseAndStay, 45, 3, 4, 4)
|
|||
DEFINE_SPECIAL(Floor_CrushStop, 46, 1, 1, 1)
|
||||
DEFINE_SPECIAL(Ceiling_MoveToValue, 47, 3, 5, 5)
|
||||
DEFINE_SPECIAL(Sector_Attach3dMidtex, 48, -1, -1, 3)
|
||||
DEFINE_SPECIAL(GlassBreak, 49, 0, 1, 1)
|
||||
DEFINE_SPECIAL(GlassBreak, 49, 0, 1, 2)
|
||||
DEFINE_SPECIAL(ExtraFloor_LightOnly, 50, -1, -1, 2)
|
||||
DEFINE_SPECIAL(Sector_SetLink, 51, 4, 4, 4)
|
||||
DEFINE_SPECIAL(Scroll_Wall, 52, 5, 5, 5)
|
||||
|
|
|
@ -469,6 +469,7 @@ enum ActorBounceFlag
|
|||
BOUNCE_MBF = 1<<12, // This in itself is not a valid mode, but replaces MBF's MF_BOUNCE flag.
|
||||
BOUNCE_AutoOffFloorOnly = 1<<13, // like BOUNCE_AutoOff, but only on floors
|
||||
BOUNCE_UseBounceState = 1<<14, // Use Bounce[.*] states
|
||||
BOUNCE_NotOnShootables = 1<<15, // do not bounce off shootable actors if we are a projectile. Explode instead.
|
||||
|
||||
BOUNCE_TypeMask = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors | BOUNCE_AutoOff | BOUNCE_HereticType | BOUNCE_MBF,
|
||||
|
||||
|
|
|
@ -524,6 +524,7 @@ struct FSkillInfo
|
|||
|
||||
bool EasyBossBrain;
|
||||
bool EasyKey;
|
||||
bool NoMenu;
|
||||
int RespawnCounter;
|
||||
int RespawnLimit;
|
||||
double Aggressiveness;
|
||||
|
|
|
@ -701,3 +701,30 @@ void AMorphedMonster::Tick ()
|
|||
Super::Tick ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Morph)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_CLASS(type, AActor);
|
||||
PARAM_INT_DEF(duration);
|
||||
PARAM_INT_DEF(flags);
|
||||
PARAM_CLASS_DEF(enter_flash, AActor);
|
||||
PARAM_CLASS_DEF(exit_flash, AActor);
|
||||
bool res = false;
|
||||
if (self->player)
|
||||
{
|
||||
if (type->IsKindOf(RUNTIME_CLASS(APlayerPawn)))
|
||||
{
|
||||
res = P_MorphPlayer(self->player, self->player, type, duration, flags, enter_flash, exit_flash);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (type->IsKindOf(RUNTIME_CLASS(AMorphedMonster)))
|
||||
{
|
||||
res = P_MorphMonster(self, type, duration, flags, enter_flash, exit_flash);
|
||||
}
|
||||
}
|
||||
ACTION_RETURN_BOOL(res);
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ void FMapInfoParser::ParseSkill ()
|
|||
bool thisisdefault = false;
|
||||
bool acsreturnisset = false;
|
||||
|
||||
skill.NoMenu = false;
|
||||
skill.AmmoFactor = 1.;
|
||||
skill.DoubleAmmoFactor = 2.;
|
||||
skill.DropAmmoFactor = -1.;
|
||||
|
@ -149,6 +150,10 @@ void FMapInfoParser::ParseSkill ()
|
|||
{
|
||||
skill.AutoUseHealth = true;
|
||||
}
|
||||
else if (sc.Compare("nomenu"))
|
||||
{
|
||||
skill.NoMenu = true;
|
||||
}
|
||||
else if (sc.Compare("respawntime"))
|
||||
{
|
||||
ParseAssign();
|
||||
|
@ -508,6 +513,7 @@ FSkillInfo &FSkillInfo::operator=(const FSkillInfo &other)
|
|||
{
|
||||
Name = other.Name;
|
||||
AmmoFactor = other.AmmoFactor;
|
||||
NoMenu = other.NoMenu;
|
||||
DoubleAmmoFactor = other.DoubleAmmoFactor;
|
||||
DropAmmoFactor = other.DropAmmoFactor;
|
||||
DamageFactor = other.DamageFactor;
|
||||
|
|
13
src/info.cpp
13
src/info.cpp
|
@ -767,6 +767,13 @@ DEFINE_ACTION_FUNCTION(_DamageTypeDefinition, IgnoreArmor)
|
|||
ACTION_RETURN_BOOL(DamageTypeDefinition::IgnoreArmor(type));
|
||||
}
|
||||
|
||||
FString DamageTypeDefinition::GetObituary(FName type)
|
||||
{
|
||||
DamageTypeDefinition *dtd = Get(type);
|
||||
if (dtd) return dtd->Obituary;
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -859,6 +866,12 @@ void FMapInfoParser::ParseDamageDefinition()
|
|||
dtd.DefaultFactor = sc.Float;
|
||||
if (dtd.DefaultFactor == 0) dtd.ReplaceFactor = true;
|
||||
}
|
||||
if (sc.Compare("OBITUARY"))
|
||||
{
|
||||
sc.MustGetStringName("=");
|
||||
sc.MustGetString();
|
||||
dtd.Obituary = sc.String;
|
||||
}
|
||||
else if (sc.Compare("REPLACEFACTOR"))
|
||||
{
|
||||
dtd.ReplaceFactor = true;
|
||||
|
|
|
@ -214,6 +214,7 @@ struct DamageTypeDefinition
|
|||
public:
|
||||
DamageTypeDefinition() { Clear(); }
|
||||
|
||||
FString Obituary;
|
||||
double DefaultFactor;
|
||||
bool ReplaceFactor;
|
||||
bool NoArmor;
|
||||
|
@ -221,6 +222,7 @@ public:
|
|||
void Apply(FName type);
|
||||
void Clear()
|
||||
{
|
||||
Obituary = "";
|
||||
DefaultFactor = 1.;
|
||||
ReplaceFactor = false;
|
||||
NoArmor = false;
|
||||
|
@ -228,6 +230,7 @@ public:
|
|||
|
||||
static bool IgnoreArmor(FName type);
|
||||
static int ApplyMobjDamageFactor(int damage, FName type, DmgFactors const * const factors);
|
||||
static FString GetObituary(FName type);
|
||||
|
||||
private:
|
||||
static double GetMobjDamageFactor(FName type, DmgFactors const * const factors);
|
||||
|
|
|
@ -68,6 +68,7 @@ IMPLEMENT_POINTERS_END
|
|||
|
||||
extern int NoWipe;
|
||||
|
||||
CVAR(Bool, nointerscrollabort, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -647,7 +648,7 @@ void DIntermissionScreenScroller::Init(FIntermissionAction *desc, bool first)
|
|||
int DIntermissionScreenScroller::Responder (event_t *ev)
|
||||
{
|
||||
int res = Super::Responder(ev);
|
||||
if (res == -1)
|
||||
if (res == -1 && !nointerscrollabort)
|
||||
{
|
||||
mBackground = mSecondPic;
|
||||
mTicker = mScrollDelay + mScrollTime;
|
||||
|
|
|
@ -64,6 +64,7 @@ CVAR (Float, mouse_sensitivity, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|||
CVAR (Bool, show_messages, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, show_obituaries, true, CVAR_ARCHIVE)
|
||||
CVAR(Bool, m_showinputgrid, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
CVAR(Bool, m_blockcontrollers, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
|
||||
CVAR (Float, snd_menuvolume, 0.6f, CVAR_ARCHIVE)
|
||||
|
@ -582,6 +583,9 @@ bool M_Responder (event_t *ev)
|
|||
}
|
||||
else if (menuactive != MENU_WaitKey && (ev->type == EV_KeyDown || ev->type == EV_KeyUp))
|
||||
{
|
||||
// eat blocked controller events without dispatching them.
|
||||
if (ev->data1 >= KEY_FIRSTJOYBUTTON && m_blockcontrollers) return true;
|
||||
|
||||
keyup = ev->type == EV_KeyUp;
|
||||
|
||||
ch = ev->data1;
|
||||
|
|
|
@ -339,7 +339,6 @@ void M_ActivateMenu(DMenu *menu);
|
|||
void M_ClearMenus ();
|
||||
void M_ParseMenuDefs();
|
||||
void M_StartupSkillMenu(FGameStartup *gs);
|
||||
int M_GetDefaultSkill();
|
||||
void M_StartControlPanel (bool makeSound);
|
||||
void M_SetMenu(FName menu, int param = -1);
|
||||
void M_StartMessage(const char *message, int messagemode, FName action = NAME_None);
|
||||
|
|
|
@ -1323,6 +1323,43 @@ void M_StartupSkillMenu(FGameStartup *gs)
|
|||
{
|
||||
static int done = -1;
|
||||
bool success = false;
|
||||
TArray<FSkillInfo*> MenuSkills;
|
||||
TArray<int> SkillIndices;
|
||||
if (MenuSkills.Size() == 0)
|
||||
{
|
||||
for (unsigned ind = 0; ind < AllSkills.Size(); ind++)
|
||||
{
|
||||
if (!AllSkills[ind].NoMenu)
|
||||
{
|
||||
MenuSkills.Push(&AllSkills[ind]);
|
||||
SkillIndices.Push(ind);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (MenuSkills.Size() == 0) I_Error("No valid skills for menu found. At least one must be defined.");
|
||||
|
||||
int defskill = DefaultSkill;
|
||||
if ((unsigned int)defskill >= MenuSkills.Size())
|
||||
{
|
||||
defskill = SkillIndices[(MenuSkills.Size() - 1) / 2];
|
||||
}
|
||||
if (AllSkills[defskill].NoMenu)
|
||||
{
|
||||
for (defskill = 0; defskill < (int)AllSkills.Size(); defskill++)
|
||||
{
|
||||
if (!AllSkills[defskill].NoMenu) break;
|
||||
}
|
||||
}
|
||||
int defindex = 0;
|
||||
for (unsigned i = 0; i < MenuSkills.Size(); i++)
|
||||
{
|
||||
if (MenuSkills[i] == &AllSkills[defskill])
|
||||
{
|
||||
defindex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_Skillmenu);
|
||||
if (desc != nullptr)
|
||||
{
|
||||
|
@ -1346,12 +1383,7 @@ void M_StartupSkillMenu(FGameStartup *gs)
|
|||
if (done != restart)
|
||||
{
|
||||
done = restart;
|
||||
int defskill = DefaultSkill;
|
||||
if ((unsigned int)defskill >= AllSkills.Size())
|
||||
{
|
||||
defskill = (AllSkills.Size() - 1) / 2;
|
||||
}
|
||||
ld->mSelectedItem = ld->mItems.Size() + defskill;
|
||||
ld->mSelectedItem = ld->mItems.Size() + defindex;
|
||||
|
||||
int posy = y;
|
||||
int topy = posy;
|
||||
|
@ -1364,9 +1396,9 @@ void M_StartupSkillMenu(FGameStartup *gs)
|
|||
}
|
||||
|
||||
// center the menu on the screen if the top space is larger than the bottom space
|
||||
int totalheight = posy + AllSkills.Size() * ld->mLinespacing - topy;
|
||||
int totalheight = posy + MenuSkills.Size() * ld->mLinespacing - topy;
|
||||
|
||||
if (totalheight < 190 || AllSkills.Size() == 1)
|
||||
if (totalheight < 190 || MenuSkills.Size() == 1)
|
||||
{
|
||||
int newtop = (200 - totalheight + topy) / 2;
|
||||
int topdelta = newtop - topy;
|
||||
|
@ -1389,9 +1421,9 @@ void M_StartupSkillMenu(FGameStartup *gs)
|
|||
}
|
||||
|
||||
unsigned firstitem = ld->mItems.Size();
|
||||
for(unsigned int i = 0; i < AllSkills.Size(); i++)
|
||||
for(unsigned int i = 0; i < MenuSkills.Size(); i++)
|
||||
{
|
||||
FSkillInfo &skill = AllSkills[i];
|
||||
FSkillInfo &skill = *MenuSkills[i];
|
||||
DMenuItemBase *li;
|
||||
// Using a different name for skills that must be confirmed makes handling this easier.
|
||||
FName action = (skill.MustConfirm && !AllEpisodes[gs->Episode].mNoSkill) ?
|
||||
|
@ -1405,22 +1437,22 @@ void M_StartupSkillMenu(FGameStartup *gs)
|
|||
if (skill.PicName.Len() != 0 && pItemText == nullptr)
|
||||
{
|
||||
FTextureID tex = GetMenuTexture(skill.PicName);
|
||||
li = CreateListMenuItemPatch(ld->mXpos, y, ld->mLinespacing, skill.Shortcut, tex, action, i);
|
||||
li = CreateListMenuItemPatch(ld->mXpos, y, ld->mLinespacing, skill.Shortcut, tex, action, SkillIndices[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
EColorRange color = (EColorRange)skill.GetTextColor();
|
||||
if (color == CR_UNTRANSLATED) color = ld->mFontColor;
|
||||
li = CreateListMenuItemText(x, y, ld->mLinespacing, skill.Shortcut,
|
||||
pItemText? *pItemText : skill.MenuName, ld->mFont, color,ld->mFontColor2, action, i);
|
||||
pItemText? *pItemText : skill.MenuName, ld->mFont, color,ld->mFontColor2, action, SkillIndices[i]);
|
||||
}
|
||||
ld->mItems.Push(li);
|
||||
GC::WriteBarrier(*desc, li);
|
||||
y += ld->mLinespacing;
|
||||
}
|
||||
if (AllEpisodes[gs->Episode].mNoSkill || AllSkills.Size() == 1)
|
||||
if (AllEpisodes[gs->Episode].mNoSkill || MenuSkills.Size() == 1)
|
||||
{
|
||||
ld->mAutoselect = firstitem + M_GetDefaultSkill();
|
||||
ld->mAutoselect = firstitem + defindex;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1439,7 +1471,7 @@ fail:
|
|||
MenuDescriptors[NAME_Skillmenu] = od;
|
||||
od->mMenuName = NAME_Skillmenu;
|
||||
od->mTitle = "$MNU_CHOOSESKILL";
|
||||
od->mSelectedItem = 0;
|
||||
od->mSelectedItem = defindex;
|
||||
od->mScrollPos = 0;
|
||||
od->mClass = nullptr;
|
||||
od->mPosition = -15;
|
||||
|
@ -1453,9 +1485,9 @@ fail:
|
|||
od = static_cast<DOptionMenuDescriptor*>(*desc);
|
||||
od->mItems.Clear();
|
||||
}
|
||||
for(unsigned int i = 0; i < AllSkills.Size(); i++)
|
||||
for(unsigned int i = 0; i < MenuSkills.Size(); i++)
|
||||
{
|
||||
FSkillInfo &skill = AllSkills[i];
|
||||
FSkillInfo &skill = *MenuSkills[i];
|
||||
DMenuItemBase *li;
|
||||
// Using a different name for skills that must be confirmed makes handling this easier.
|
||||
const char *action = (skill.MustConfirm && !AllEpisodes[gs->Episode].mNoSkill) ?
|
||||
|
@ -1466,29 +1498,13 @@ fail:
|
|||
{
|
||||
pItemText = skill.MenuNamesForPlayerClass.CheckKey(gs->PlayerClass);
|
||||
}
|
||||
li = CreateOptionMenuItemSubmenu(pItemText? *pItemText : skill.MenuName, action, i);
|
||||
li = CreateOptionMenuItemSubmenu(pItemText? *pItemText : skill.MenuName, action, SkillIndices[i]);
|
||||
od->mItems.Push(li);
|
||||
GC::WriteBarrier(od, li);
|
||||
if (!done)
|
||||
{
|
||||
done = true;
|
||||
od->mSelectedItem = M_GetDefaultSkill();
|
||||
od->mSelectedItem = defindex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Returns the default skill level.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
int M_GetDefaultSkill()
|
||||
{
|
||||
int defskill = DefaultSkill;
|
||||
if ((unsigned int)defskill >= AllSkills.Size())
|
||||
{
|
||||
defskill = (AllSkills.Size() - 1) / 2;
|
||||
}
|
||||
return defskill;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ xx(Shadow)
|
|||
xx(Subtract)
|
||||
xx(Subtractive)
|
||||
xx(FillColor)
|
||||
xx(HealthFactor)
|
||||
|
||||
// Healingradius types
|
||||
xx(Mana)
|
||||
|
@ -773,6 +774,7 @@ xx(BuiltinGetDefault)
|
|||
xx(BuiltinClassCast)
|
||||
xx(BuiltinFormat)
|
||||
xx(Damage)
|
||||
xx(Noattack)
|
||||
|
||||
// basic type names
|
||||
xx(Default)
|
||||
|
|
|
@ -350,7 +350,7 @@ bool AActor::CheckMeleeRange ()
|
|||
|
||||
double dist;
|
||||
|
||||
if (!pl)
|
||||
if (!pl || (Sector->Flags & SECF_NOATTACK))
|
||||
return false;
|
||||
|
||||
dist = Distance2D (pl);
|
||||
|
@ -399,7 +399,7 @@ bool P_CheckMeleeRange2 (AActor *actor)
|
|||
double dist;
|
||||
|
||||
|
||||
if (!actor->target)
|
||||
if (!actor->target || (actor->Sector->Flags & SECF_NOATTACK))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -446,6 +446,8 @@ bool P_CheckMissileRange (AActor *actor)
|
|||
{
|
||||
double dist;
|
||||
|
||||
if ((actor->Sector->Flags & SECF_NOATTACK)) return false;
|
||||
|
||||
if (!P_CheckSight (actor, actor->target, SF_SEEPASTBLOCKEVERYTHING))
|
||||
return false;
|
||||
|
||||
|
|
|
@ -217,15 +217,20 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf
|
|||
}
|
||||
}
|
||||
|
||||
switch (mod)
|
||||
FString obit = DamageTypeDefinition::GetObituary(mod);
|
||||
if (obit.IsNotEmpty()) messagename = obit;
|
||||
else
|
||||
{
|
||||
case NAME_Suicide: messagename = "OB_SUICIDE"; break;
|
||||
case NAME_Falling: messagename = "OB_FALLING"; break;
|
||||
case NAME_Crush: messagename = "OB_CRUSH"; break;
|
||||
case NAME_Exit: messagename = "OB_EXIT"; break;
|
||||
case NAME_Drowning: messagename = "OB_WATER"; break;
|
||||
case NAME_Slime: messagename = "OB_SLIME"; break;
|
||||
case NAME_Fire: if (attacker == NULL) messagename = "OB_LAVA"; break;
|
||||
switch (mod)
|
||||
{
|
||||
case NAME_Suicide: messagename = "OB_SUICIDE"; break;
|
||||
case NAME_Falling: messagename = "OB_FALLING"; break;
|
||||
case NAME_Crush: messagename = "OB_CRUSH"; break;
|
||||
case NAME_Exit: messagename = "OB_EXIT"; break;
|
||||
case NAME_Drowning: messagename = "OB_WATER"; break;
|
||||
case NAME_Slime: messagename = "OB_SLIME"; break;
|
||||
case NAME_Fire: if (attacker == NULL) messagename = "OB_LAVA"; break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for being killed by a voodoo doll.
|
||||
|
|
|
@ -3177,7 +3177,7 @@ FUNC(LS_ClearForceField)
|
|||
}
|
||||
|
||||
FUNC(LS_GlassBreak)
|
||||
// GlassBreak (bNoJunk)
|
||||
// GlassBreak (bNoJunk, junkID)
|
||||
{
|
||||
bool switched;
|
||||
bool quest1, quest2;
|
||||
|
@ -3197,7 +3197,6 @@ FUNC(LS_GlassBreak)
|
|||
{
|
||||
if (!arg0)
|
||||
{ // Break some glass
|
||||
AActor *glass;
|
||||
|
||||
DVector2 linemid((ln->v1->fX() + ln->v2->fX()) / 2, (ln->v1->fY() + ln->v2->fY()) / 2);
|
||||
|
||||
|
@ -3209,18 +3208,32 @@ FUNC(LS_GlassBreak)
|
|||
y += (ln->frontsector->centerspot.y - y) / 5;
|
||||
*/
|
||||
|
||||
auto type = SpawnableThings.CheckKey(arg1);
|
||||
for (int i = 0; i < 7; ++i)
|
||||
{
|
||||
glass = Spawn("GlassJunk", DVector3(linemid, ONFLOORZ), ALLOW_REPLACE);
|
||||
|
||||
glass->AddZ(24.);
|
||||
glass->SetState (glass->SpawnState + (pr_glass() % glass->health));
|
||||
|
||||
glass->Angles.Yaw = pr_glass() * (360 / 256.);
|
||||
glass->VelFromAngle(pr_glass() & 3);
|
||||
glass->Vel.Z = (pr_glass() & 7);
|
||||
// [RH] Let the shards stick around longer than they did in Strife.
|
||||
glass->tics += pr_glass();
|
||||
AActor *glass = nullptr;
|
||||
if (arg1 > 0)
|
||||
{
|
||||
if (type != nullptr)
|
||||
{
|
||||
glass = Spawn(*type, DVector3(linemid, ONFLOORZ), ALLOW_REPLACE);
|
||||
glass->AddZ(24.);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glass = Spawn("GlassJunk", DVector3(linemid, ONFLOORZ), ALLOW_REPLACE);
|
||||
glass->AddZ(24.);
|
||||
glass->SetState(glass->SpawnState + (pr_glass() % glass->health));
|
||||
}
|
||||
if (glass != nullptr)
|
||||
{
|
||||
glass->Angles.Yaw = pr_glass() * (360 / 256.);
|
||||
glass->VelFromAngle(pr_glass() & 3);
|
||||
glass->Vel.Z = (pr_glass() & 7);
|
||||
// [RH] Let the shards stick around longer than they did in Strife.
|
||||
glass->tics += pr_glass();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (quest1 || quest2)
|
||||
|
|
|
@ -3538,6 +3538,11 @@ bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop)
|
|||
if ((mo->flags & MF_MISSILE) && (mo->flags2 & MF2_RIP) && BlockingMobj->flags & MF_SHOOTABLE)
|
||||
return true;
|
||||
|
||||
if (BlockingMobj->flags & MF_SHOOTABLE && mo->BounceFlags & BOUNCE_NotOnShootables)
|
||||
{
|
||||
mo->bouncecount = 1; // let it explode now.
|
||||
}
|
||||
|
||||
if (mo->bouncecount>0 && --mo->bouncecount == 0)
|
||||
{
|
||||
if (mo->flags & MF_MISSILE)
|
||||
|
|
|
@ -515,6 +515,7 @@ public:
|
|||
FString arg0str, arg1str;
|
||||
|
||||
memset(th, 0, sizeof(*th));
|
||||
double healthfactor = 1;
|
||||
th->Gravity = 1;
|
||||
th->RenderStyle = STYLE_Count;
|
||||
th->Alpha = -1;
|
||||
|
@ -738,38 +739,52 @@ public:
|
|||
break;
|
||||
|
||||
case NAME_Alpha:
|
||||
CHECK_N(Zd | Zdt)
|
||||
th->Alpha = CheckFloat(key);
|
||||
break;
|
||||
|
||||
case NAME_FillColor:
|
||||
CHECK_N(Zd | Zdt)
|
||||
th->fillcolor = CheckInt(key);
|
||||
break;
|
||||
|
||||
case NAME_Health:
|
||||
CHECK_N(Zd | Zdt)
|
||||
th->health = CheckInt(key);
|
||||
break;
|
||||
|
||||
case NAME_HealthFactor:
|
||||
CHECK_N(Zd | Zdt)
|
||||
healthfactor = CheckFloat(key);
|
||||
break;
|
||||
|
||||
case NAME_Score:
|
||||
CHECK_N(Zd | Zdt)
|
||||
th->score = CheckInt(key);
|
||||
break;
|
||||
|
||||
case NAME_Pitch:
|
||||
CHECK_N(Zd | Zdt)
|
||||
th->pitch = (short)CheckInt(key);
|
||||
break;
|
||||
|
||||
case NAME_Roll:
|
||||
CHECK_N(Zd | Zdt)
|
||||
th->roll = (short)CheckInt(key);
|
||||
break;
|
||||
|
||||
case NAME_ScaleX:
|
||||
CHECK_N(Zd | Zdt)
|
||||
th->Scale.X = CheckFloat(key);
|
||||
break;
|
||||
|
||||
case NAME_ScaleY:
|
||||
CHECK_N(Zd | Zdt)
|
||||
th->Scale.Y = CheckFloat(key);
|
||||
break;
|
||||
|
||||
case NAME_Scale:
|
||||
CHECK_N(Zd | Zdt)
|
||||
th->Scale.X = th->Scale.Y = CheckFloat(key);
|
||||
break;
|
||||
|
||||
|
@ -793,6 +808,7 @@ public:
|
|||
{
|
||||
th->args[1] = -FName(arg1str);
|
||||
}
|
||||
th->health = int(th->health * healthfactor);
|
||||
// Thing specials are only valid in namespaces with Hexen-type specials
|
||||
// and in ZDoomTranslated - which will use the translator on them.
|
||||
if (namespc == NAME_ZDoomTranslated)
|
||||
|
@ -1658,6 +1674,10 @@ public:
|
|||
sec->planes[sector_t::ceiling].GlowHeight = (float)CheckFloat(key);
|
||||
break;
|
||||
|
||||
case NAME_Noattack:
|
||||
Flag(sec->Flags, SECF_NOATTACK, key);
|
||||
break;
|
||||
|
||||
case NAME_MoreIds:
|
||||
// delay parsing of the tag string until parsing of the sector is complete
|
||||
// This ensures that the ID is always the first tag in the list.
|
||||
|
|
|
@ -495,6 +495,7 @@ enum
|
|||
SECF_ENDGODMODE = 256, // getting damaged by this sector ends god mode
|
||||
SECF_ENDLEVEL = 512, // ends level when health goes below 10
|
||||
SECF_HAZARD = 1024, // Change to Strife's delayed damage handling.
|
||||
SECF_NOATTACK = 2048, // monsters cannot start attacks in this sector.
|
||||
|
||||
SECF_WASSECRET = 1 << 30, // a secret that was discovered
|
||||
SECF_SECRET = 1 << 31, // a secret sector
|
||||
|
|
|
@ -217,12 +217,66 @@ bool FZipFile::Open(bool quiet)
|
|||
|
||||
char *dirptr = (char*)directory;
|
||||
FZipLump *lump_p = Lumps;
|
||||
|
||||
// Check if all files have the same prefix so that this can be stripped out.
|
||||
FString name0;
|
||||
for (DWORD i = 0; i < NumLumps; i++)
|
||||
{
|
||||
FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr;
|
||||
|
||||
int len = LittleShort(zip_fh->NameLength);
|
||||
FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len);
|
||||
|
||||
dirptr += sizeof(FZipCentralDirectoryInfo) +
|
||||
LittleShort(zip_fh->NameLength) +
|
||||
LittleShort(zip_fh->ExtraLength) +
|
||||
LittleShort(zip_fh->CommentLength);
|
||||
|
||||
if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file.
|
||||
{
|
||||
free(directory);
|
||||
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", Filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
name.ToLower();
|
||||
if (i == 0)
|
||||
{
|
||||
// check for special names, if one of these gets found this must be treated as a normal zip.
|
||||
bool isspecial = !name.Compare("flats/") ||
|
||||
!name.Compare("textures/") ||
|
||||
!name.Compare("hires/") ||
|
||||
!name.Compare("sprites/") ||
|
||||
!name.Compare("voxels/") ||
|
||||
!name.Compare("colormaps/") ||
|
||||
!name.Compare("acs/") ||
|
||||
!name.Compare("voices/") ||
|
||||
!name.Compare("patches/") ||
|
||||
!name.Compare("graphics/") ||
|
||||
!name.Compare("sounds/") ||
|
||||
!name.Compare("music/");
|
||||
if (isspecial) break;
|
||||
name0 = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (name.IndexOf(name0) != 0)
|
||||
{
|
||||
name0 = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dirptr = (char*)directory;
|
||||
lump_p = Lumps;
|
||||
for (DWORD i = 0; i < NumLumps; i++)
|
||||
{
|
||||
FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr;
|
||||
|
||||
int len = LittleShort(zip_fh->NameLength);
|
||||
FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len);
|
||||
if (name0.IsNotEmpty()) name = name.Mid(name0.Len());
|
||||
dirptr += sizeof(FZipCentralDirectoryInfo) +
|
||||
LittleShort(zip_fh->NameLength) +
|
||||
LittleShort(zip_fh->ExtraLength) +
|
||||
|
|
|
@ -356,6 +356,7 @@ static FFlagDef ActorFlagDefs[]=
|
|||
DEFINE_FLAG2(BOUNCE_MBF, MBFBOUNCER, AActor, BounceFlags),
|
||||
DEFINE_FLAG2(BOUNCE_AutoOffFloorOnly, BOUNCEAUTOOFFFLOORONLY, AActor, BounceFlags),
|
||||
DEFINE_FLAG2(BOUNCE_UseBounceState, USEBOUNCESTATE, AActor, BounceFlags),
|
||||
DEFINE_FLAG2(BOUNCE_NotOnShootables, DONTBOUNCEONSHOOTABLES, AActor, BounceFlags),
|
||||
};
|
||||
|
||||
// These won't be accessible through bitfield variables
|
||||
|
|
|
@ -1156,7 +1156,8 @@ public:
|
|||
|
||||
void WI_initShowNextLoc ()
|
||||
{
|
||||
if (wbs->next_ep == -1)
|
||||
auto info = FindLevelInfo(wbs->next, false);
|
||||
if (info == nullptr)
|
||||
{
|
||||
// Last map in episode - there is no next location!
|
||||
WI_End();
|
||||
|
|
|
@ -1776,6 +1776,7 @@ MOUSEMNU_LOOKSTRAFE = "Lookstrafe";
|
|||
|
||||
JOYMNU_CONFIG = "CONFIGURE CONTROLLER";
|
||||
JOYMNU_OPTIONS = "CONTROLLER OPTIONS";
|
||||
JOYMNU_NOMENU = "Block controller input in menu";
|
||||
|
||||
// Player Setup Menu
|
||||
MNU_PLAYERSETUP = "PLAYER SETUP";
|
||||
|
@ -1895,7 +1896,7 @@ MISCMNU_DEHLOAD = "Load *.deh/*.bex lumps";
|
|||
MISCMNU_CACHENODES = "Cache nodes";
|
||||
MISCMNU_CACHETIME = "Time threshold for node caching";
|
||||
MISCMNU_CLEARNODECACHE = "Clear node cache";
|
||||
|
||||
MISCMNU_INTERSCROLL = "Allow skipping of intermission scrollers";
|
||||
// Automap Options
|
||||
AUTOMAPMNU_TITLE = "AUTOMAP OPTIONS";
|
||||
AUTOMAPMNU_COLORSET = "Map color set";
|
||||
|
|
|
@ -562,6 +562,7 @@ OptionMenu "JoystickOptionsDefaults"
|
|||
{
|
||||
Title "$JOYMNU_OPTIONS"
|
||||
Option "$JOYMNU_ENABLE", "use_joystick", "YesNo"
|
||||
Option "$JOYMNU_NOMENU", "m_blockcontrollers", "YesNo"
|
||||
IfOption(Windows)
|
||||
{
|
||||
Option "$JOYMNU_DINPUT", "joy_dinput", "YesNo"
|
||||
|
@ -945,6 +946,7 @@ OptionMenu "MiscOptions"
|
|||
Option "$MISCMNU_SAVELOADCONFIRMATION", "saveloadconfirmation", "OnOff"
|
||||
Slider "$MISCMNU_AUTOSAVECOUNT", "autosavecount", 1, 20, 1, 0
|
||||
Option "$MISCMNU_DEHLOAD", "dehload", "dehopt"
|
||||
Option "$MISCMNU_INTERSCROLL", "nointerscrollabort", "OffOn"
|
||||
StaticText " "
|
||||
Option "$MISCMNU_CACHENODES", "gl_cachenodes", "OnOff"
|
||||
Slider "$MISCMNU_CACHETIME", "gl_cachetime", 0.0, 2.0, 0.1
|
||||
|
|
|
@ -796,6 +796,7 @@ class Actor : Thinker native
|
|||
deprecated native void A_BasicAttack(int meleedamage, sound meleesound, class<actor> missiletype, double missileheight);
|
||||
action native bool, Actor A_ThrowGrenade(class<Actor> itemtype, double zheight = 0, double xyvel = 0, double zvel = 0, bool useammo = true);
|
||||
native void A_Weave(int xspeed, int yspeed, double xdist, double ydist);
|
||||
native bool A_Morph(class<Actor> type, int duration = 0, int flags = 0, class<Actor> enter_flash = null, class<Actor> exit_flash = null);
|
||||
|
||||
|
||||
action native state, bool A_Teleport(statelabel teleportstate = null, class<SpecialSpot> targettype = "BossSpot", class<Actor> fogtype = "TeleportFog", int flags = 0, double mindist = 128, double maxdist = 0, int ptr = AAPTR_DEFAULT);
|
||||
|
|
|
@ -214,20 +214,23 @@ enum ESelectWeaponFlags
|
|||
// Morph constants
|
||||
enum EMorphFlags
|
||||
{
|
||||
MRF_ADDSTAMINA = 1,
|
||||
MRF_FULLHEALTH = 2,
|
||||
MRF_UNDOBYTOMEOFPOWER = 4,
|
||||
MRF_UNDOBYCHAOSDEVICE = 8,
|
||||
MRF_FAILNOTELEFRAG = 16,
|
||||
MRF_FAILNOLAUGH = 32,
|
||||
MRF_WHENINVULNERABLE = 64,
|
||||
MRF_LOSEACTUALWEAPON = 128,
|
||||
MRF_NEWTIDBEHAVIOUR = 256,
|
||||
MRF_UNDOBYDEATH = 512,
|
||||
MRF_UNDOBYDEATHFORCED = 1024,
|
||||
MRF_UNDOBYDEATHSAVES = 2048,
|
||||
MRF_UNDOALWAYS = 4096,
|
||||
MRF_TRANSFERTRANSLATION = 8192,
|
||||
MRF_OLDEFFECTS = 0x00000000,
|
||||
MRF_ADDSTAMINA = 0x00000001,
|
||||
MRF_FULLHEALTH = 0x00000002,
|
||||
MRF_UNDOBYTOMEOFPOWER = 0x00000004,
|
||||
MRF_UNDOBYCHAOSDEVICE = 0x00000008,
|
||||
MRF_FAILNOTELEFRAG = 0x00000010,
|
||||
MRF_FAILNOLAUGH = 0x00000020,
|
||||
MRF_WHENINVULNERABLE = 0x00000040,
|
||||
MRF_LOSEACTUALWEAPON = 0x00000080,
|
||||
MRF_NEWTIDBEHAVIOUR = 0x00000100,
|
||||
MRF_UNDOBYDEATH = 0x00000200,
|
||||
MRF_UNDOBYDEATHFORCED = 0x00000400,
|
||||
MRF_UNDOBYDEATHSAVES = 0x00000800,
|
||||
MRF_UNDOBYTIMEOUT = 0x00001000,
|
||||
MRF_UNDOALWAYS = 0x00002000,
|
||||
MRF_TRANSFERTRANSLATION = 0x00004000,
|
||||
MRF_STANDARDUNDOING = MRF_UNDOBYTOMEOFPOWER | MRF_UNDOBYCHAOSDEVICE | MRF_UNDOBYTIMEOUT,
|
||||
};
|
||||
|
||||
// Flags for A_RailAttack and A_CustomRailgun
|
||||
|
|
Loading…
Reference in a new issue