This commit is contained in:
Christoph Oelckers 2016-07-28 09:20:48 +02:00
commit b8abec4e1f
17 changed files with 143 additions and 33 deletions

View file

@ -380,6 +380,8 @@ enum ActorFlag7
MF7_LAXTELEFRAGDMG = 0x00100000, // [MC] Telefrag damage can be reduced. MF7_LAXTELEFRAGDMG = 0x00100000, // [MC] Telefrag damage can be reduced.
MF7_ICESHATTER = 0x00200000, // [MC] Shatters ice corpses regardless of damagetype. MF7_ICESHATTER = 0x00200000, // [MC] Shatters ice corpses regardless of damagetype.
MF7_ALLOWTHRUFLAGS = 0x00400000, // [MC] Allow THRUACTORS and the likes on puffs to prevent mod breakage. MF7_ALLOWTHRUFLAGS = 0x00400000, // [MC] Allow THRUACTORS and the likes on puffs to prevent mod breakage.
MF7_USEKILLSCRIPTS = 0x00800000, // [JM] Use "KILL" Script on death if not forced by GameInfo.
MF7_NOKILLSCRIPTS = 0x01000000, // [JM] No "KILL" Script on death whatsoever, even if forced by GameInfo.
}; };
// --- mobj.renderflags --- // --- mobj.renderflags ---

View file

@ -378,6 +378,8 @@ enum
WIF_MELEEWEAPON = 0x00008000, // melee weapon. Used by bots and monster AI. WIF_MELEEWEAPON = 0x00008000, // melee weapon. Used by bots and monster AI.
WIF_DEHAMMO = 0x00010000, // Uses Doom's original amount of ammo for the respective attack functions so that old DEHACKED patches work as intended. WIF_DEHAMMO = 0x00010000, // Uses Doom's original amount of ammo for the respective attack functions so that old DEHACKED patches work as intended.
// AmmoUse1 will be set to the first attack's ammo use so that checking for empty weapons still works // AmmoUse1 will be set to the first attack's ammo use so that checking for empty weapons still works
WIF_NODEATHDESELECT = 0x00020000, // Don't jump to the Deselect state when the player dies
WIF_NODEATHINPUT = 0x00040000, // The weapon cannot be fired/reloaded/whatever when the player is dead
WIF_CHEATNOTWEAPON = 0x08000000, // Give cheat considers this not a weapon (used by Sigil) WIF_CHEATNOTWEAPON = 0x08000000, // Give cheat considers this not a weapon (used by Sigil)
// Flags used only by bot AI: // Flags used only by bot AI:

View file

@ -539,6 +539,38 @@ static void AddAmmoToList(AWeapon * weapdef)
} }
} }
static int GetDigitCount(int value)
{
int digits = 0;
do
{
value /= 10;
++digits;
}
while (0 != value);
return digits;
}
static void GetAmmoTextLengths(player_t *CPlayer, int& ammocur, int& ammomax)
{
for (auto type : orderedammos)
{
AAmmo * ammoitem = static_cast<AAmmo*>(CPlayer->mo->FindInventory(type));
AAmmo * inv = nullptr == ammoitem
? static_cast<AAmmo*>(GetDefaultByType(type))
: ammoitem;
assert(nullptr != inv);
ammocur = MAX(ammocur, nullptr == ammoitem ? 0 : ammoitem->Amount);
ammomax = MAX(ammomax, inv->MaxAmount);
}
ammocur = GetDigitCount(ammocur);
ammomax = GetDigitCount(ammomax);
}
static int DrawAmmo(player_t *CPlayer, int x, int y) static int DrawAmmo(player_t *CPlayer, int x, int y)
{ {
@ -586,7 +618,13 @@ static int DrawAmmo(player_t *CPlayer, int x, int y)
// ok, we got all ammo types. Now draw the list back to front (bottom to top) // ok, we got all ammo types. Now draw the list back to front (bottom to top)
int def_width = ConFont->StringWidth("000/000"); int ammocurlen = 0;
int ammomaxlen = 0;
GetAmmoTextLengths(CPlayer, ammocurlen, ammomaxlen);
mysnprintf(buf, countof(buf), "%0*d/%0*d", ammocurlen, 0, ammomaxlen, 0);
int def_width = ConFont->StringWidth(buf);
int yadd = ConFont->GetHeight(); int yadd = ConFont->GetHeight();
int xtext = x - def_width; int xtext = x - def_width;
@ -618,7 +656,7 @@ static int DrawAmmo(player_t *CPlayer, int x, int y)
int maxammo = inv->MaxAmount; int maxammo = inv->MaxAmount;
int ammo = ammoitem? ammoitem->Amount : 0; int ammo = ammoitem? ammoitem->Amount : 0;
mysnprintf(buf, countof(buf), "%3d/%3d", ammo, maxammo); mysnprintf(buf, countof(buf), "%*d/%*d", ammocurlen, ammo, ammomaxlen, maxammo);
int tex_width= clamp<int>(ConFont->StringWidth(buf)-def_width, 0, 1000); int tex_width= clamp<int>(ConFont->StringWidth(buf)-def_width, 0, 1000);

View file

@ -354,6 +354,7 @@ void FMapInfoParser::ParseGameInfo()
GAMEINFOKEY_PATCH(mStatscreenFinishedFont, "statscreen_finishedpatch") GAMEINFOKEY_PATCH(mStatscreenFinishedFont, "statscreen_finishedpatch")
GAMEINFOKEY_PATCH(mStatscreenEnteringFont, "statscreen_enteringpatch") GAMEINFOKEY_PATCH(mStatscreenEnteringFont, "statscreen_enteringpatch")
GAMEINFOKEY_BOOL(norandomplayerclass, "norandomplayerclass") GAMEINFOKEY_BOOL(norandomplayerclass, "norandomplayerclass")
GAMEINFOKEY_BOOL(forcekillscripts, "forcekillscripts") // [JM] Force kill scripts on thing death. (MF7_NOKILLSCRIPTS overrides.)
else else
{ {

View file

@ -173,6 +173,7 @@ struct gameinfo_t
FGIFont mStatscreenFinishedFont; FGIFont mStatscreenFinishedFont;
FGIFont mStatscreenEnteringFont; FGIFont mStatscreenEnteringFont;
bool norandomplayerclass; bool norandomplayerclass;
bool forcekillscripts;
const char *GetFinalePage(unsigned int num) const; const char *GetFinalePage(unsigned int num) const;
}; };

View file

@ -418,7 +418,7 @@ public:
class FPlayerNameBox : public FListMenuItemSelectable class FPlayerNameBox : public FListMenuItemSelectable
{ {
const char *mText; FString mText;
FFont *mFont; FFont *mFont;
EColorRange mFontColor; EColorRange mFontColor;
int mFrameSize; int mFrameSize;
@ -447,7 +447,7 @@ public:
class FValueTextItem : public FListMenuItemSelectable class FValueTextItem : public FListMenuItemSelectable
{ {
TArray<FString> mSelections; TArray<FString> mSelections;
const char *mText; FString mText;
int mSelection; int mSelection;
FFont *mFont; FFont *mFont;
EColorRange mFontColor; EColorRange mFontColor;
@ -472,7 +472,7 @@ public:
class FSliderItem : public FListMenuItemSelectable class FSliderItem : public FListMenuItemSelectable
{ {
const char *mText; FString mText;
FFont *mFont; FFont *mFont;
EColorRange mFontColor; EColorRange mFontColor;
int mMinrange, mMaxrange; int mMinrange, mMaxrange;
@ -539,7 +539,7 @@ public:
class FOptionMenuItem : public FListMenuItem class FOptionMenuItem : public FListMenuItem
{ {
protected: protected:
char *mLabel; FString mLabel;
bool mCentered; bool mCentered;
void drawLabel(int indent, int y, EColorRange color, bool grayed = false); void drawLabel(int indent, int y, EColorRange color, bool grayed = false);
@ -548,7 +548,7 @@ public:
FOptionMenuItem(const char *text, FName action = NAME_None, bool center = false) FOptionMenuItem(const char *text, FName action = NAME_None, bool center = false)
: FListMenuItem(0, 0, action) : FListMenuItem(0, 0, action)
{ {
mLabel = copystring(text); mLabel = text;
mCentered = center; mCentered = center;
} }

View file

@ -781,7 +781,15 @@ static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc)
FString label = sc.String; FString label = sc.String;
sc.MustGetStringName(","); sc.MustGetStringName(",");
sc.MustGetString(); sc.MustGetString();
FOptionMenuItem *it = new FOptionMenuItemSafeCommand(label, sc.String); FString command = sc.String;
FString prompt;
// Check for optional custom prompt
if (sc.CheckString(","))
{
sc.MustGetString();
prompt = sc.String;
}
FOptionMenuItem *it = new FOptionMenuItemSafeCommand(label, command, prompt);
desc->mItems.Push(it); desc->mItems.Push(it);
} }
else if (sc.Compare("Control") || sc.Compare("MapControl")) else if (sc.Compare("Control") || sc.Compare("MapControl"))

View file

@ -479,7 +479,6 @@ void DOptionMenu::Drawer ()
FOptionMenuItem::~FOptionMenuItem() FOptionMenuItem::~FOptionMenuItem()
{ {
if (mLabel != NULL) delete [] mLabel;
} }
int FOptionMenuItem::Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected) int FOptionMenuItem::Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
@ -507,14 +506,14 @@ int FOptionMenuItem::GetIndent()
{ {
return 0; return 0;
} }
const char *label = mLabel; const char *label = mLabel.GetChars();
if (*label == '$') label = GStrings(label+1); if (*label == '$') label = GStrings(label+1);
return SmallFont->StringWidth(label); return SmallFont->StringWidth(label);
} }
void FOptionMenuItem::drawLabel(int indent, int y, EColorRange color, bool grayed) void FOptionMenuItem::drawLabel(int indent, int y, EColorRange color, bool grayed)
{ {
const char *label = mLabel; const char *label = mLabel.GetChars();
if (*label == '$') label = GStrings(label+1); if (*label == '$') label = GStrings(label+1);
int overlay = grayed? MAKEARGB(96,48,0,0) : 0; int overlay = grayed? MAKEARGB(96,48,0,0) : 0;

View file

@ -103,9 +103,13 @@ public:
class FOptionMenuItemSafeCommand : public FOptionMenuItemCommand class FOptionMenuItemSafeCommand : public FOptionMenuItemCommand
{ {
// action is a CCMD // action is a CCMD
protected:
FString mPrompt;
public: public:
FOptionMenuItemSafeCommand(const char *label, const char *menu) FOptionMenuItemSafeCommand(const char *label, const char *menu, const char *prompt)
: FOptionMenuItemCommand(label, menu) : FOptionMenuItemCommand(label, menu)
, mPrompt(prompt)
{ {
} }
@ -121,9 +125,13 @@ public:
bool Activate() bool Activate()
{ {
const char *msg = GStrings("SAFEMESSAGE"); const char *msg = mPrompt.IsNotEmpty() ? mPrompt.GetChars() : "$SAFEMESSAGE";
if (*msg == '$')
{
msg = GStrings(msg + 1);
}
const char *actionLabel = mLabel; const char *actionLabel = mLabel.GetChars();
if (actionLabel != NULL) if (actionLabel != NULL)
{ {
if (*actionLabel == '$') if (*actionLabel == '$')
@ -528,7 +536,7 @@ public:
int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected) int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
{ {
const char *txt = mCurrent? mAltText.GetChars() : mLabel; const char *txt = mCurrent? mAltText.GetChars() : mLabel.GetChars();
if (*txt == '$') txt = GStrings(txt + 1); if (*txt == '$') txt = GStrings(txt + 1);
int w = SmallFont->StringWidth(txt) * CleanXfac_1; int w = SmallFont->StringWidth(txt) * CleanXfac_1;
int x = (screen->GetWidth() - w) / 2; int x = (screen->GetWidth() - w) / 2;

View file

@ -64,7 +64,7 @@ EXTERN_CVAR (Bool, cl_run)
FPlayerNameBox::FPlayerNameBox(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action) FPlayerNameBox::FPlayerNameBox(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action)
: FListMenuItemSelectable(x, y, height, action) : FListMenuItemSelectable(x, y, height, action)
{ {
mText = copystring(text); mText = text;
mFont = font; mFont = font;
mFontColor = color; mFontColor = color;
mFrameSize = frameofs; mFrameSize = frameofs;
@ -74,7 +74,6 @@ FPlayerNameBox::FPlayerNameBox(int x, int y, int height, int frameofs, const cha
FPlayerNameBox::~FPlayerNameBox() FPlayerNameBox::~FPlayerNameBox()
{ {
if (mText != NULL) delete [] mText;
} }
//============================================================================= //=============================================================================
@ -220,7 +219,7 @@ bool FPlayerNameBox::MenuEvent(int mkey, bool fromcontroller)
FValueTextItem::FValueTextItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values) FValueTextItem::FValueTextItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values)
: FListMenuItemSelectable(x, y, height, action) : FListMenuItemSelectable(x, y, height, action)
{ {
mText = copystring(text); mText = text;
mFont = font; mFont = font;
mFontColor = color; mFontColor = color;
mFontColor2 = valuecolor; mFontColor2 = valuecolor;
@ -240,7 +239,6 @@ FValueTextItem::FValueTextItem(int x, int y, int height, const char *text, FFont
FValueTextItem::~FValueTextItem() FValueTextItem::~FValueTextItem()
{ {
if (mText != NULL) delete [] mText;
} }
//============================================================================= //=============================================================================
@ -341,7 +339,7 @@ void FValueTextItem::Drawer(bool selected)
FSliderItem::FSliderItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step) FSliderItem::FSliderItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step)
: FListMenuItemSelectable(x, y, height, action) : FListMenuItemSelectable(x, y, height, action)
{ {
mText = copystring(text); mText = text;
mFont = font; mFont = font;
mFontColor = color; mFontColor = color;
mSelection = 0; mSelection = 0;
@ -352,7 +350,6 @@ FSliderItem::FSliderItem(int x, int y, int height, const char *text, FFont *font
FSliderItem::~FSliderItem() FSliderItem::~FSliderItem()
{ {
if (mText != NULL) delete [] mText;
} }
//============================================================================= //=============================================================================

View file

@ -270,6 +270,8 @@ enum
SCRIPT_Unloading = 13, SCRIPT_Unloading = 13,
SCRIPT_Disconnect = 14, SCRIPT_Disconnect = 14,
SCRIPT_Return = 15, SCRIPT_Return = 15,
SCRIPT_Event = 16, // [BB]
SCRIPT_Kill = 17, // [JM]
}; };
// Script flags // Script flags

View file

@ -379,6 +379,12 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags)
target = source; target = source;
} }
// [JM] Fire KILL type scripts for actor. Not needed for players, since they have the "DEATH" script type.
if (!player && !(flags7 & MF7_NOKILLSCRIPTS) && ((flags7 & MF7_USEKILLSCRIPTS) || gameinfo.forcekillscripts))
{
FBehavior::StaticStartTypedScripts(SCRIPT_Kill, this, true, 0, true);
}
flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY); flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY);
if (!(flags4 & MF4_DONTFALL)) flags&=~MF_NOGRAVITY; if (!(flags4 & MF4_DONTFALL)) flags&=~MF_NOGRAVITY;
flags |= MF_DROPOFF; flags |= MF_DROPOFF;

View file

@ -510,7 +510,7 @@ void P_DropWeapon (player_t *player)
} }
// Since the weapon is dropping, stop blocking switching. // Since the weapon is dropping, stop blocking switching.
player->WeaponState &= ~WF_DISABLESWITCH; player->WeaponState &= ~WF_DISABLESWITCH;
if (player->ReadyWeapon != nullptr) if ((player->ReadyWeapon != nullptr) && (player->health > 0 || !(player->ReadyWeapon->WeaponFlags & WIF_NODEATHDESELECT)))
{ {
P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->GetDownState()); P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->GetDownState());
} }
@ -1396,20 +1396,23 @@ void player_t::TickPSprites()
pspr = pspr->Next; pspr = pspr->Next;
} }
if (ReadyWeapon == nullptr && (health > 0 || mo->DamageType != NAME_Fire)) if ((health > 0) || (ReadyWeapon != nullptr && !(ReadyWeapon->WeaponFlags & WIF_NODEATHINPUT)))
{ {
if (PendingWeapon != WP_NOCHANGE) if (ReadyWeapon == nullptr)
P_BringUpWeapon(this);
}
else
{
P_CheckWeaponSwitch(this);
if (WeaponState & (WF_WEAPONREADY | WF_WEAPONREADYALT))
{ {
P_CheckWeaponFire(this); if (PendingWeapon != WP_NOCHANGE)
P_BringUpWeapon(this);
}
else
{
P_CheckWeaponSwitch(this);
if (WeaponState & (WF_WEAPONREADY | WF_WEAPONREADYALT))
{
P_CheckWeaponFire(this);
}
// Check custom buttons
P_CheckWeaponButtons(this);
} }
// Check custom buttons
P_CheckWeaponButtons(this);
} }
} }

View file

@ -7188,3 +7188,34 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMovementDirection)
ACTION_RETURN_BOOL(true); ACTION_RETURN_BOOL(true);
} }
//==========================================================================
//
// A_CopySpriteFrame(from, to, flags)
//
// Copies the sprite and/or frame from one pointer to another.
//==========================================================================
enum CPSFFlags
{
CPSF_NOSPRITE = 1,
CPSF_NOFRAME = 1 << 1,
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CopySpriteFrame)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_INT(from);
PARAM_INT(to);
PARAM_INT_OPT(flags) { flags = 0; }
AActor *copyfrom = COPY_AAPTR(self, from);
AActor *copyto = COPY_AAPTR(self, to);
if (copyfrom == copyto || copyfrom == nullptr || copyto == nullptr || ((flags & CPSF_NOSPRITE) && (flags & CPSF_NOFRAME)))
{
ACTION_RETURN_BOOL(false);
}
if (!(flags & CPSF_NOSPRITE)) copyto->sprite = copyfrom->sprite;
if (!(flags & CPSF_NOFRAME)) copyto->frame = copyfrom->frame;
ACTION_RETURN_BOOL(true);
}

View file

@ -257,6 +257,8 @@ static FFlagDef ActorFlagDefs[]=
DEFINE_FLAG(MF7, LAXTELEFRAGDMG, AActor, flags7), DEFINE_FLAG(MF7, LAXTELEFRAGDMG, AActor, flags7),
DEFINE_FLAG(MF7, ICESHATTER, AActor, flags7), DEFINE_FLAG(MF7, ICESHATTER, AActor, flags7),
DEFINE_FLAG(MF7, ALLOWTHRUFLAGS, AActor, flags7), DEFINE_FLAG(MF7, ALLOWTHRUFLAGS, AActor, flags7),
DEFINE_FLAG(MF7, USEKILLSCRIPTS, AActor, flags7),
DEFINE_FLAG(MF7, NOKILLSCRIPTS, AActor, flags7),
// Effect flags // Effect flags
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
@ -362,6 +364,8 @@ static FFlagDef WeaponFlagDefs[] =
DEFINE_FLAG(WIF, NO_AUTO_SWITCH, AWeapon, WeaponFlags), DEFINE_FLAG(WIF, NO_AUTO_SWITCH, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF, AMMO_CHECKBOTH, AWeapon, WeaponFlags), DEFINE_FLAG(WIF, AMMO_CHECKBOTH, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF, NOAUTOAIM, AWeapon, WeaponFlags), DEFINE_FLAG(WIF, NOAUTOAIM, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF, NODEATHDESELECT, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF, NODEATHINPUT, AWeapon, WeaponFlags),
DEFINE_DUMMY_FLAG(NOLMS), DEFINE_DUMMY_FLAG(NOLMS),
DEFINE_FLAG(WIF, ALT_USES_BOTH, AWeapon, WeaponFlags), DEFINE_FLAG(WIF, ALT_USES_BOTH, AWeapon, WeaponFlags),

View file

@ -330,6 +330,7 @@ ACTOR Actor native //: Thinker
native state A_CheckRange(float distance, state label, bool two_dimension = false); native state A_CheckRange(float distance, state label, bool two_dimension = false);
action native bool A_FaceMovementDirection(float offset = 0, float anglelimit = 0, float pitchlimit = 0, int flags = 0, int ptr = AAPTR_DEFAULT); action native bool A_FaceMovementDirection(float offset = 0, float anglelimit = 0, float pitchlimit = 0, int flags = 0, int ptr = AAPTR_DEFAULT);
action native int A_ClearOverlays(int sstart = 0, int sstop = 0, bool safety = true); action native int A_ClearOverlays(int sstart = 0, int sstop = 0, bool safety = true);
action native bool A_CopySpriteFrame(int from, int to, int flags = 0);
native void A_RearrangePointers(int newtarget, int newmaster = AAPTR_DEFAULT, int newtracer = AAPTR_DEFAULT, int flags=0); native void A_RearrangePointers(int newtarget, int newmaster = AAPTR_DEFAULT, int newtracer = AAPTR_DEFAULT, int flags=0);
native void A_TransferPointer(int ptr_source, int ptr_recepient, int sourcefield, int recepientfield=AAPTR_DEFAULT, int flags=0); native void A_TransferPointer(int ptr_source, int ptr_recepient, int sourcefield, int recepientfield=AAPTR_DEFAULT, int flags=0);

View file

@ -666,4 +666,11 @@ enum
{ {
GAF_RELATIVE = 1, GAF_RELATIVE = 1,
GAF_SWITCH = 1 << 1, GAF_SWITCH = 1 << 1,
};
//Flags for A_CopySpriteFrame
enum
{
CPSF_NOSPRITE = 1,
CPSF_NOFRAME = 1 << 1,
}; };