- Fixed: G_DoPlayDemo did not free the demobuffer or the CVAR backups when it

failed to start the demo.
- Added a MF5_BRIGHT flag to always render an actor fullbright.
- Fixed: Calling Door_Animated with a non-zero tag created a new thinker
  for each two-sided line of the sector.
- Added Karate Chris's submission for making 'spray' a cheat.
- Added CO2's default parameter additions for several Doom code pointers
  submission.
- Added CO2's A_RemoveMaster/A_RemoveChildren submission.
- Added Blzut3's SBARINFO replacement for the Doom statusbar.
- Fixed: SBarInfo still displayed the wrong bar for height 0
- Added A_KillSiblings and A_DamageSiblings code pointers.
- added MaxAbsorb and MaxFullAbsorb properties for Armor.


SVN r1304 (trunk)
This commit is contained in:
Christoph Oelckers 2008-12-06 10:22:37 +00:00
commit 153a2a4c2c
26 changed files with 367 additions and 1019 deletions

View file

@ -22,7 +22,7 @@ IMPLEMENT_CLASS (AHexenArmor)
void ABasicArmor::Serialize (FArchive &arc)
{
Super::Serialize (arc);
arc << SavePercent << BonusCount;
arc << SavePercent << BonusCount << MaxAbsorb << MaxFullAbsorb << AbsorbCount;
}
//===========================================================================
@ -37,6 +37,7 @@ void ABasicArmor::Serialize (FArchive &arc)
void ABasicArmor::Tick ()
{
Super::Tick ();
AbsorbCount = 0;
if (!Icon.isValid())
{
switch (gameinfo.gametype)
@ -108,15 +109,31 @@ bool ABasicArmor::HandlePickup (AInventory *item)
void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
{
int saved;
if (damageType != NAME_Drowning)
{
int saved = FixedMul (damage, SavePercent);
int full = MAX(0, MaxFullAbsorb - AbsorbCount);
if (damage < full)
{
saved = damage;
}
else
{
saved += full + FixedMul (damage - full, SavePercent);
if (MaxAbsorb > 0 && saved + AbsorbCount > MaxAbsorb)
{
saved = MAX(0, MaxAbsorb - AbsorbCount);
}
}
if (Amount < saved)
{
saved = Amount;
}
newdamage -= saved;
Amount -= saved;
AbsorbCount += saved;
if (Amount == 0)
{
// The armor has become useless
@ -159,7 +176,7 @@ void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
void ABasicArmorPickup::Serialize (FArchive &arc)
{
Super::Serialize (arc);
arc << SavePercent << SaveAmount;
arc << SavePercent << SaveAmount << MaxAbsorb << MaxFullAbsorb;
arc << DropTime;
}
@ -174,6 +191,8 @@ AInventory *ABasicArmorPickup::CreateCopy (AActor *other)
ABasicArmorPickup *copy = static_cast<ABasicArmorPickup *> (Super::CreateCopy (other));
copy->SavePercent = SavePercent;
copy->SaveAmount = SaveAmount;
copy->MaxAbsorb = MaxAbsorb;
copy->MaxFullAbsorb = MaxFullAbsorb;
return copy;
}
@ -216,6 +235,8 @@ bool ABasicArmorPickup::Use (bool pickup)
armor->Amount = SaveAmount + armor->BonusCount;
armor->MaxAmount = SaveAmount;
armor->Icon = Icon;
armor->MaxAbsorb = MaxAbsorb;
armor->MaxFullAbsorb = MaxFullAbsorb;
return true;
}
@ -228,7 +249,8 @@ bool ABasicArmorPickup::Use (bool pickup)
void ABasicArmorBonus::Serialize (FArchive &arc)
{
Super::Serialize (arc);
arc << SavePercent << SaveAmount << MaxSaveAmount << BonusCount << BonusMax;
arc << SavePercent << SaveAmount << MaxSaveAmount << BonusCount << BonusMax
<< MaxAbsorb << MaxFullAbsorb;
}
//===========================================================================
@ -245,6 +267,8 @@ AInventory *ABasicArmorBonus::CreateCopy (AActor *other)
copy->MaxSaveAmount = MaxSaveAmount;
copy->BonusCount = BonusCount;
copy->BonusMax = BonusMax;
copy->MaxAbsorb = MaxAbsorb;
copy->MaxFullAbsorb = MaxFullAbsorb;
return copy;
}
@ -295,6 +319,8 @@ bool ABasicArmorBonus::Use (bool pickup)
armor->Amount = 0;
armor->Icon = Icon;
armor->SavePercent = SavePercent;
armor->MaxAbsorb = MaxAbsorb;
armor->MaxFullAbsorb = MaxFullAbsorb;
}
armor->Amount = MIN(armor->Amount + saveAmount, MaxSaveAmount + armor->BonusCount);

View file

@ -334,7 +334,10 @@ public:
virtual bool HandlePickup (AInventory *item);
virtual void AbsorbDamage (int damage, FName damageType, int &newdamage);
int AbsorbCount;
fixed_t SavePercent;
int MaxAbsorb;
int MaxFullAbsorb;
int BonusCount;
};
@ -348,6 +351,8 @@ public:
virtual bool Use (bool pickup);
fixed_t SavePercent;
int MaxAbsorb;
int MaxFullAbsorb;
int SaveAmount;
};
@ -362,6 +367,8 @@ public:
fixed_t SavePercent; // The default, for when you don't already have armor
int MaxSaveAmount;
int MaxAbsorb;
int MaxFullAbsorb;
int SaveAmount;
int BonusCount;
int BonusMax;

View file

@ -360,8 +360,7 @@ extern DBaseStatusBar *StatusBar;
// Status bar factories -----------------------------------------------------
DBaseStatusBar *CreateDoomStatusBar();
DBaseStatusBar *CreateHereticStatusBar();
DBaseStatusBar *CreateHexenStatusBar();
DBaseStatusBar *CreateStrifeStatusBar();
DBaseStatusBar *CreateCustomStatusBar();
DBaseStatusBar *CreateCustomStatusBar(int script=0);

View file

@ -147,7 +147,17 @@ struct SBarInfo
static void Load();
};
extern SBarInfo *SBarInfoScript;
#define NUM_SCRIPTS 5
#define SCRIPT_CUSTOM 0
#define SCRIPT_DOOM 1
// The next ones shouldn't be used... yet
#define SCRIPT_HERETIC 2
#define SCRIPT_HEXEN 3
#define SCRIPT_STRIFE 4
// Converts GAME_x to it's script number
#define GETSBARINFOSCRIPT(game) \
(game & GAME_DoomChex) ? SCRIPT_DOOM : (game == GAME_Heretic ? SCRIPT_HERETIC : (game == GAME_Hexen ? SCRIPT_HEXEN : (game == GAME_Strife ? SCRIPT_STRIFE : SCRIPT_CUSTOM)))
extern SBarInfo *SBarInfoScript[5];
// Enums used between the parser and the display
@ -344,7 +354,7 @@ class DSBarInfo : public DBaseStatusBar
{
DECLARE_CLASS(DSBarInfo, DBaseStatusBar)
public:
DSBarInfo();
DSBarInfo(SBarInfo *script=NULL);
~DSBarInfo();
void Draw(EHudState state);
void NewGame();
@ -367,6 +377,7 @@ private:
bool wiggle, bool translate);
FRemapTable* getTranslation();
SBarInfo *script;
FImageCollection Images;
FPlayerSkin *oldSkin;
FFont *drawingFont;

View file

@ -155,12 +155,14 @@ void FBarShader::Unload()
}
//SBarInfo Display
DSBarInfo::DSBarInfo () : DBaseStatusBar (SBarInfoScript->height),
DSBarInfo::DSBarInfo (SBarInfo *script) : DBaseStatusBar(script->height),
shader_horz_normal(false, false),
shader_horz_reverse(false, true),
shader_vert_normal(true, false),
shader_vert_reverse(true, true)
{
this->script = script;
static const char *InventoryBarLumps[] =
{
"ARTIBOX", "SELECTBO", "INVCURS", "INVGEML1",
@ -168,21 +170,21 @@ DSBarInfo::DSBarInfo () : DBaseStatusBar (SBarInfoScript->height),
"USEARTIA", "USEARTIB", "USEARTIC", "USEARTID",
};
TArray<const char *> patchnames;
patchnames.Resize(SBarInfoScript->Images.Size()+10);
patchnames.Resize(script->Images.Size()+10);
unsigned int i = 0;
for(i = 0;i < SBarInfoScript->Images.Size();i++)
for(i = 0;i < script->Images.Size();i++)
{
patchnames[i] = SBarInfoScript->Images[i];
patchnames[i] = script->Images[i];
}
for(i = 0;i < 10;i++)
{
patchnames[i+SBarInfoScript->Images.Size()] = InventoryBarLumps[i];
patchnames[i+script->Images.Size()] = InventoryBarLumps[i];
}
for (i = 0;i < numskins;i++)
{
AddFaceToImageCollection (&skins[i], &Images);
}
invBarOffset = SBarInfoScript->Images.Size();
invBarOffset = script->Images.Size();
Images.Init(&patchnames[0], patchnames.Size());
drawingFont = V_GetFont("ConFont");
oldHealth = 0;
@ -204,14 +206,14 @@ void DSBarInfo::Draw (EHudState state)
int hud = STBAR_NORMAL;
if(state == HUD_StatusBar)
{
if(SBarInfoScript->completeBorder) //Fill the statusbar with the border before we draw.
if(script->completeBorder) //Fill the statusbar with the border before we draw.
{
FTexture *b = TexMan[gameinfo.border->b];
R_DrawBorder(viewwindowx, viewwindowy + viewheight + b->GetHeight(), viewwindowx + viewwidth, SCREENHEIGHT);
if(screenblocks == 10)
screen->FlatFill(viewwindowx, viewwindowy + viewheight, viewwindowx + viewwidth, viewwindowy + viewheight + b->GetHeight(), b, true);
}
if(SBarInfoScript->automapbar && automapactive)
if(script->automapbar && automapactive)
{
hud = STBAR_AUTOMAP;
}
@ -228,28 +230,28 @@ void DSBarInfo::Draw (EHudState state)
{
hud = STBAR_NONE;
}
if(SBarInfoScript->huds[hud].forceScaled) //scale the statusbar
if(script->huds[hud].forceScaled) //scale the statusbar
{
SetScaled(true, true);
setsizeneeded = true;
}
doCommands(SBarInfoScript->huds[hud], 0, 0, SBarInfoScript->huds[hud].alpha);
doCommands(script->huds[hud], 0, 0, script->huds[hud].alpha);
if(CPlayer->inventorytics > 0 && !(level.flags & LEVEL_NOINVENTORYBAR))
{
if(state == HUD_StatusBar)
{
// No overlay? Lets cancel it.
if(SBarInfoScript->huds[STBAR_INVENTORY].commands.Size() == 0)
if(script->huds[STBAR_INVENTORY].commands.Size() == 0)
CPlayer->inventorytics = 0;
else
doCommands(SBarInfoScript->huds[STBAR_INVENTORY], 0, 0, SBarInfoScript->huds[STBAR_INVENTORY].alpha);
doCommands(script->huds[STBAR_INVENTORY], 0, 0, script->huds[STBAR_INVENTORY].alpha);
}
else if(state == HUD_Fullscreen)
{
if(SBarInfoScript->huds[STBAR_INVENTORYFULLSCREEN].commands.Size() == 0)
if(script->huds[STBAR_INVENTORYFULLSCREEN].commands.Size() == 0)
CPlayer->inventorytics = 0;
else
doCommands(SBarInfoScript->huds[STBAR_INVENTORYFULLSCREEN], 0, 0, SBarInfoScript->huds[STBAR_INVENTORYFULLSCREEN].alpha);
doCommands(script->huds[STBAR_INVENTORYFULLSCREEN], 0, 0, script->huds[STBAR_INVENTORYFULLSCREEN].alpha);
}
}
if(currentPopup != POP_None)
@ -261,8 +263,8 @@ void DSBarInfo::Draw (EHudState state)
popbar = STBAR_POPUPKEYS;
else if(currentPopup == POP_Status)
popbar = STBAR_POPUPSTATUS;
doCommands(SBarInfoScript->huds[popbar], SBarInfoScript->popups[currentPopup-1].getXOffset(), SBarInfoScript->popups[currentPopup-1].getYOffset(),
SBarInfoScript->popups[currentPopup-1].getAlpha(SBarInfoScript->huds[popbar].alpha));
doCommands(script->huds[popbar], script->popups[currentPopup-1].getXOffset(), script->popups[currentPopup-1].getYOffset(),
script->popups[currentPopup-1].getAlpha(script->huds[popbar].alpha));
}
}
@ -290,20 +292,20 @@ void DSBarInfo::Tick ()
DBaseStatusBar::Tick();
if(level.time & 1)
chainWiggle = pr_chainwiggle() & 1;
if(!SBarInfoScript->interpolateHealth)
if(!script->interpolateHealth)
{
oldHealth = CPlayer->health;
}
else
{
int health = SBarInfoScript->lowerHealthCap ? CPlayer->health : CPlayer->mo->health;
int health = script->lowerHealthCap ? CPlayer->health : CPlayer->mo->health;
if(oldHealth > health)
{
oldHealth -= clamp((oldHealth - health), 1, SBarInfoScript->interpolationSpeed);
oldHealth -= clamp((oldHealth - health), 1, script->interpolationSpeed);
}
else if(oldHealth < CPlayer->health)
{
oldHealth += clamp((health - oldHealth), 1, SBarInfoScript->interpolationSpeed);
oldHealth += clamp((health - oldHealth), 1, script->interpolationSpeed);
}
}
AInventory *armor = CPlayer->mo->FindInventory<ABasicArmor>();
@ -313,7 +315,7 @@ void DSBarInfo::Tick ()
}
else
{
if(!SBarInfoScript->interpolateArmor)
if(!script->interpolateArmor)
{
oldArmor = armor->Amount;
}
@ -321,11 +323,11 @@ void DSBarInfo::Tick ()
{
if(oldArmor > armor->Amount)
{
oldArmor -= clamp((oldArmor - armor->Amount) >> 2, 1, SBarInfoScript->armorInterpolationSpeed);
oldArmor -= clamp((oldArmor - armor->Amount) >> 2, 1, script->armorInterpolationSpeed);
}
else if(oldArmor < armor->Amount)
{
oldArmor += clamp((armor->Amount - oldArmor) >> 2, 1, SBarInfoScript->armorInterpolationSpeed);
oldArmor += clamp((armor->Amount - oldArmor) >> 2, 1, script->armorInterpolationSpeed);
}
}
}
@ -337,12 +339,12 @@ void DSBarInfo::Tick ()
MugShot.Tick(CPlayer);
if(currentPopup != POP_None)
{
SBarInfoScript->popups[currentPopup-1].tick();
if(SBarInfoScript->popups[currentPopup-1].opened == false && SBarInfoScript->popups[currentPopup-1].isDoneMoving())
script->popups[currentPopup-1].tick();
if(script->popups[currentPopup-1].opened == false && script->popups[currentPopup-1].isDoneMoving())
{
currentPopup = pendingPopup;
if(currentPopup != POP_None)
SBarInfoScript->popups[currentPopup-1].open();
script->popups[currentPopup-1].open();
}
}
}
@ -367,13 +369,13 @@ void DSBarInfo::ShowPop(int popnum)
else
pendingPopup = POP_None;
if(currentPopup != POP_None)
SBarInfoScript->popups[currentPopup-1].close();
script->popups[currentPopup-1].close();
else
{
currentPopup = pendingPopup;
pendingPopup = POP_None;
if(currentPopup != POP_None)
SBarInfoScript->popups[currentPopup-1].open();
script->popups[currentPopup-1].open();
}
}
@ -386,11 +388,11 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a
ABasicArmor *armor = CPlayer->mo->FindInventory<ABasicArmor>();
int health = CPlayer->mo->health;
int armorAmount = armor != NULL ? armor->Amount : 0;
if(SBarInfoScript->interpolateHealth)
if(script->interpolateHealth)
{
health = oldHealth;
}
if(SBarInfoScript->interpolateArmor)
if(script->interpolateArmor)
{
armorAmount = oldArmor;
}
@ -567,7 +569,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a
if(cmd.flags & DRAWNUMBER_HEALTH)
{
value = health;
if(SBarInfoScript->lowerHealthCap && value < 0) //health shouldn't display negatives
if(script->lowerHealthCap && value < 0) //health shouldn't display negatives
{
value = 0;
}
@ -1440,17 +1442,17 @@ void DSBarInfo::DrawString(const char* str, int x, int y, int xOffset, int yOffs
continue;
}
int width;
if(SBarInfoScript->spacingCharacter == '\0') //No monospace?
if(script->spacingCharacter == '\0') //No monospace?
width = drawingFont->GetCharWidth((int) *str);
else
width = drawingFont->GetCharWidth((int) SBarInfoScript->spacingCharacter);
width = drawingFont->GetCharWidth((int) script->spacingCharacter);
FTexture* character = drawingFont->GetChar((int) *str, &width);
if(character == NULL) //missing character.
{
str++;
continue;
}
if(SBarInfoScript->spacingCharacter == '\0') //If we are monospaced lets use the offset
if(script->spacingCharacter == '\0') //If we are monospaced lets use the offset
x += (character->LeftOffset+1); //ignore x offsets since we adapt to character size
int rx, ry, rw, rh;
@ -1512,10 +1514,10 @@ void DSBarInfo::DrawString(const char* str, int x, int y, int xOffset, int yOffs
DTA_HUDRules, HUD_Normal,
TAG_DONE);
}
if(SBarInfoScript->spacingCharacter == '\0')
if(script->spacingCharacter == '\0')
x += width + spacing - (character->LeftOffset+1);
else //width gets changed at the call to GetChar()
x += drawingFont->GetCharWidth((int) SBarInfoScript->spacingCharacter) + spacing;
x += drawingFont->GetCharWidth((int) script->spacingCharacter) + spacing;
str++;
}
}
@ -1542,10 +1544,10 @@ void DSBarInfo::DrawNumber(int num, int len, int x, int y, int xOffset, int yOff
value.Insert(0, "0");
}
}
if(SBarInfoScript->spacingCharacter == '\0')
if(script->spacingCharacter == '\0')
x -= int(drawingFont->StringWidth(value)+(spacing * value.Len()));
else //monospaced, so just multiplay the character size
x -= int((drawingFont->GetCharWidth((int) SBarInfoScript->spacingCharacter) + spacing) * value.Len());
x -= int((drawingFont->GetCharWidth((int) script->spacingCharacter) + spacing) * value.Len());
DrawString(value, x, y, xOffset, yOffset, alpha, fullScreenOffsets, translation, spacing, drawshadow);
}
@ -1651,7 +1653,14 @@ FRemapTable* DSBarInfo::getTranslation()
IMPLEMENT_CLASS(DSBarInfo);
DBaseStatusBar *CreateCustomStatusBar ()
DBaseStatusBar *CreateCustomStatusBar (int script)
{
return new DSBarInfo;
if(SBarInfoScript[script] == NULL)
I_FatalError("Tried to create a status bar with no script!");
return new DSBarInfo(SBarInfoScript[script]);
}
DBaseStatusBar *CreateDoomStatusBar ()
{
return new DSBarInfo(SBarInfoScript[1]);
}

View file

@ -47,7 +47,15 @@
#include "i_system.h"
#include "g_level.h"
SBarInfo *SBarInfoScript;
SBarInfo *SBarInfoScript[NUM_SCRIPTS] = {NULL,NULL,NULL,NULL,NULL};
static const char *DefaultScriptNames[NUM_SCRIPTS] =
{
"SBARINFO", //Custom
"sbarinfo/doom.txt",
NULL, //Heretic
NULL, //Hexen
NULL //Strife
};
static const char *SBarInfoTopLevel[] =
{
@ -105,29 +113,48 @@ static const char *SBarInfoRoutineLevel[] =
static void FreeSBarInfoScript()
{
if (SBarInfoScript != NULL)
for(int i = 0;i < NUM_SCRIPTS;i++)
{
delete SBarInfoScript;
SBarInfoScript = NULL;
if (SBarInfoScript[i] != NULL)
{
delete SBarInfoScript[i];
SBarInfoScript[i] = NULL;
}
}
}
void SBarInfo::Load()
{
if(Wads.CheckNumForName("SBARINFO") != -1)
Printf ("ParseSBarInfo: Loading default status bar definitions.\n");
for(int i = 1;i < NUM_SCRIPTS;i++) // Read in default bars if they exist
{
if(DefaultScriptNames[i] != NULL)
{
int lump = Wads.CheckNumForFullName(DefaultScriptNames[i], true);
if(lump != -1)
{
if(SBarInfoScript[i] == NULL)
SBarInfoScript[i] = new SBarInfo(lump);
else
SBarInfoScript[i]->ParseSBarInfo(lump);
}
}
}
if(Wads.CheckNumForName(DefaultScriptNames[SCRIPT_CUSTOM]) != -1)
{
Printf ("ParseSBarInfo: Loading custom status bar definition.\n");
int lastlump, lump;
lastlump = 0;
while((lump = Wads.FindLump("SBARINFO", &lastlump)) != -1)
while((lump = Wads.FindLump(DefaultScriptNames[SCRIPT_CUSTOM], &lastlump)) != -1)
{
if(SBarInfoScript == NULL)
SBarInfoScript = new SBarInfo(lump);
if(SBarInfoScript[SCRIPT_CUSTOM] == NULL)
SBarInfoScript[SCRIPT_CUSTOM] = new SBarInfo(lump);
else //We now have to load multiple SBarInfo Lumps so the 2nd time we need to use this method instead.
SBarInfoScript->ParseSBarInfo(lump);
SBarInfoScript[SCRIPT_CUSTOM]->ParseSBarInfo(lump);
}
atterm(FreeSBarInfoScript);
}
atterm(FreeSBarInfoScript);
}
//SBarInfo Script Reader
@ -155,7 +182,12 @@ void SBarInfo::ParseSBarInfo(int lump)
if(!sc.CheckToken(TK_None))
sc.MustGetToken(TK_Identifier);
if(sc.Compare("Doom"))
gameType = GAME_Doom;
{
int lump = Wads.CheckNumForFullName("sbarinfo/doom.txt", true);
if(lump == -1)
sc.ScriptError("Standard Doom Status Bar not found.");
ParseSBarInfo(lump);
}
else if(sc.Compare("Heretic"))
gameType = GAME_Heretic;
else if(sc.Compare("Hexen"))