From 153a2a4c2cb909477443ba656b8e7de656deddfa Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 6 Dec 2008 10:22:37 +0000 Subject: [PATCH] - 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) --- docs/rh-log.txt | 19 + src/CMakeLists.txt | 1 - src/actor.h | 1 + src/d_main.cpp | 5 +- src/g_doom/a_archvile.cpp | 27 +- src/g_doom/a_keen.cpp | 9 +- src/g_doom/doom_sbar.cpp | 907 --------------------------- src/g_game.cpp | 5 + src/g_level.cpp | 23 +- src/g_shared/a_armor.cpp | 34 +- src/g_shared/a_pickups.h | 7 + src/g_shared/sbar.h | 3 +- src/g_shared/sbarinfo.h | 15 +- src/g_shared/sbarinfo_display.cpp | 89 +-- src/g_shared/sbarinfo_parser.cpp | 54 +- src/p_doors.cpp | 1 + src/p_lnspec.cpp | 16 +- src/p_local.h | 1 + src/p_things.cpp | 14 + src/r_things.cpp | 2 +- src/thingdef/thingdef_codeptr.cpp | 85 +++ src/thingdef/thingdef_data.cpp | 1 + src/thingdef/thingdef_properties.cpp | 51 +- src/version.h | 2 +- wadsrc/static/actors/actor.txt | 10 +- zdoom.vcproj | 4 - 26 files changed, 367 insertions(+), 1019 deletions(-) delete mode 100644 src/g_doom/doom_sbar.cpp diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 0b29453730..9dfd9d61c0 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,22 @@ +December 6, 2008 (Changes by Graf Zahl) +- Fixed: G_DoPlayDemo did not free the demobuffer or the CVAR backups when it + failed to start the demo. + +December 2, 2008 (Changes by Graf Zahl) +- 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. + +December 1, 2008 (Changes by Graf Zahl) +- 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. + December 1, 2008 - Restored the multiplayer scoreboard's former centering so that it doesn't look awful on widescreen intermissions. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1cc622c870..7640890274 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -538,7 +538,6 @@ add_executable( zdoom WIN32 zstrformat.cpp zstring.cpp g_doom/a_doommisc.cpp - g_doom/doom_sbar.cpp g_heretic/a_hereticmisc.cpp g_heretic/heretic_sbar.cpp g_hexen/a_hexenmisc.cpp diff --git a/src/actor.h b/src/actor.h index 01df7412ef..d023be81cb 100644 --- a/src/actor.h +++ b/src/actor.h @@ -302,6 +302,7 @@ enum // dependence of main engine code of specific actor types. MF5_SUMMONEDMONSTER = 0x02000000, // To mark the friendly Minotaur. Hopefully to be generalized later. MF5_NOVERTICALMELEERANGE=0x04000000,// Does not check vertical distance for melee range + MF5_BRIGHT = 0x08000000, // Actor is always rendered fullbright // --- mobj.renderflags --- diff --git a/src/d_main.cpp b/src/d_main.cpp index b73f161ad6..bc230f6cd9 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -138,6 +138,7 @@ EXTERN_CVAR (Float, m_pitch) EXTERN_CVAR (Float, m_yaw) EXTERN_CVAR (Bool, invertmouse) EXTERN_CVAR (Bool, lookstrafe) +EXTERN_CVAR (Int, screenblocks) extern gameinfo_t SharewareGameInfo; extern gameinfo_t RegisteredGameInfo; @@ -636,13 +637,13 @@ void D_Display () R_RefreshViewBorder (); } - if (hud_althud && viewheight == SCREENHEIGHT) + if (hud_althud && viewheight == SCREENHEIGHT && screenblocks > 10) { if (DrawFSHUD || automapactive) DrawHUD(); StatusBar->DrawTopStuff (HUD_None); } else - if (viewheight == SCREENHEIGHT && viewactive) + if (viewheight == SCREENHEIGHT && viewactive && screenblocks > 10) { StatusBar->Draw (DrawFSHUD ? HUD_Fullscreen : HUD_None); StatusBar->DrawTopStuff (DrawFSHUD ? HUD_Fullscreen : HUD_None); diff --git a/src/g_doom/a_archvile.cpp b/src/g_doom/a_archvile.cpp index 25df2087e5..64eb22f122 100644 --- a/src/g_doom/a_archvile.cpp +++ b/src/g_doom/a_archvile.cpp @@ -13,8 +13,7 @@ // PIT_VileCheck // Detect a corpse that could be raised. // -DECLARE_ACTION(A_Fire) - +void A_Fire(AActor *self, int height); // @@ -33,16 +32,24 @@ DEFINE_ACTION_FUNCTION(AActor, A_VileStart) DEFINE_ACTION_FUNCTION(AActor, A_StartFire) { S_Sound (self, CHAN_BODY, "vile/firestrt", 1, ATTN_NORM); - CALL_ACTION(A_Fire, self); + A_Fire (self, 0); } DEFINE_ACTION_FUNCTION(AActor, A_FireCrackle) { S_Sound (self, CHAN_BODY, "vile/firecrkl", 1, ATTN_NORM); - CALL_ACTION(A_Fire, self); + A_Fire (self, 0); } -DEFINE_ACTION_FUNCTION(AActor, A_Fire) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Fire) +{ + ACTION_PARAM_START(1); + ACTION_PARAM_FIXED(height,0); + + A_Fire(self, height); +} + +void A_Fire(AActor *self, int height) { AActor *dest; angle_t an; @@ -59,7 +66,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Fire) self->SetOrigin (dest->x + FixedMul (24*FRACUNIT, finecosine[an]), dest->y + FixedMul (24*FRACUNIT, finesine[an]), - dest->z); + dest->z + height); } @@ -68,8 +75,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_Fire) // A_VileTarget // Spawn the hellfire // -DEFINE_ACTION_FUNCTION(AActor, A_VileTarget) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileTarget) { + ACTION_PARAM_START(1); + ACTION_PARAM_CLASS(fire,0); AActor *fog; if (!self->target) @@ -77,13 +86,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_VileTarget) A_FaceTarget (self); - fog = Spawn ("ArchvileFire", self->target->x, self->target->y, + fog = Spawn (fire, self->target->x, self->target->y, self->target->z, ALLOW_REPLACE); self->tracer = fog; fog->target = self; fog->tracer = self->target; - CALL_ACTION(A_Fire, fog); + A_Fire(fog, 0); } diff --git a/src/g_doom/a_keen.cpp b/src/g_doom/a_keen.cpp index 7c7be9f486..42231a915c 100644 --- a/src/g_doom/a_keen.cpp +++ b/src/g_doom/a_keen.cpp @@ -11,9 +11,9 @@ // // A_KeenDie // DOOM II special, map 32. -// Uses special tag 666. +// Uses special tag 666 by default. // -DEFINE_ACTION_FUNCTION(AActor, A_KeenDie) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KeenDie) { CALL_ACTION(A_NoBlocking, self); @@ -31,7 +31,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_KeenDie) } } - EV_DoDoor (DDoor::doorOpen, NULL, NULL, 666, 2*FRACUNIT, 0, 0, 0); + ACTION_PARAM_START(1); + ACTION_PARAM_INT(doortag, 0); + + EV_DoDoor (DDoor::doorOpen, NULL, NULL, doortag, 2*FRACUNIT, 0, 0, 0); } diff --git a/src/g_doom/doom_sbar.cpp b/src/g_doom/doom_sbar.cpp deleted file mode 100644 index 0349182c13..0000000000 --- a/src/g_doom/doom_sbar.cpp +++ /dev/null @@ -1,907 +0,0 @@ -#include "doomtype.h" -#include "doomstat.h" -#include "v_font.h" -#include "v_video.h" -#include "sbar.h" -#include "r_defs.h" -#include "w_wad.h" -#include "m_random.h" -#include "d_player.h" -#include "st_stuff.h" -#include "r_local.h" -#include "m_swap.h" -#include "a_keys.h" -#include "templates.h" -#include "i_system.h" -#include "r_translate.h" -#include "sbarinfo.h" -#include "g_level.h" -#include "v_palette.h" - - -#define ST_EVILGRINCOUNT (2*TICRATE) -#define ST_STRAIGHTFACECOUNT (TICRATE/2) -#define ST_TURNCOUNT (1*TICRATE) -#define ST_OUCHCOUNT (1*TICRATE) - -EXTERN_CVAR (Bool, vid_fps) - -class DDoomStatusBar : public DBaseStatusBar -{ - DECLARE_CLASS(DDoomStatusBar, DBaseStatusBar) -public: - DDoomStatusBar () : DBaseStatusBar (32) - { - static const char *sharedLumpNames[] = - { - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, "STTMINUS", "STTNUM0", "STTNUM1", - "STTNUM2", "STTNUM3", "STTNUM4", "STTNUM5", "STTNUM6", - "STTNUM7", "STTNUM8", "STTNUM9", "STYSNUM0", "STYSNUM1", - "STYSNUM2", "STYSNUM3", "STYSNUM4", "STYSNUM5", "STYSNUM6", - "STYSNUM7", "STYSNUM8", "STYSNUM9" - }; - FTexture *tex; - - DBaseStatusBar::Images.Init (sharedLumpNames, NUM_BASESB_IMAGES); - tex = DBaseStatusBar::Images[imgBNumbers]; - BigWidth = tex->GetWidth(); - BigHeight = tex->GetHeight(); - - DoCommonInit (); - } - - ~DDoomStatusBar () - { - } - - void NewGame () - { - Images.Uninit (); - DoCommonInit (); - if (CPlayer != NULL) - { - AttachToPlayer (CPlayer); - } - } - - void AddFaceToImageCollection (void *skn, FImageCollection *images) - { - AddFaceToImageCollectionActual (skn, images, true); - } - - void MultiplayerChanged () - { - DBaseStatusBar::MultiplayerChanged (); - if (multiplayer) - { - // set face background color - StatusBarTex.SetPlayerRemap(translationtables[TRANSLATION_Players][int(CPlayer - players)]); - } - } - - void AttachToPlayer (player_t *player) - { - player_t *oldplayer = CPlayer; - - DBaseStatusBar::AttachToPlayer (player); - if (oldplayer != CPlayer || savegamerestore/*added for morphing*/) - { - SetFace (&skins[CPlayer->morphTics ? CPlayer->MorphedPlayerClass : CPlayer->userinfo.skin]); - } - if (multiplayer) - { - // set face background color - StatusBarTex.SetPlayerRemap(translationtables[TRANSLATION_Players][int(CPlayer - players)]); - } - MugShot.bEvilGrin = false; - } - - void Tick () - { - DBaseStatusBar::Tick (); - RandomNumber = M_Random (); - - //Do some stuff related to the mug shot that has to be done at 35fps - MugShot.Tick(CPlayer); - } - - void Draw (EHudState state) - { - DBaseStatusBar::Draw (state); - - if (state == HUD_Fullscreen) - { - SB_state = screen->GetPageCount (); - DrawFullScreenStuff (); - } - else if (state == HUD_StatusBar) - { - if (SB_state != 0) - { - SB_state--; - DrawImage (&StatusBarTex, 0, 0); - memset (OldArms, 255, sizeof(OldArms)); - OldKeys = -1; - memset (OldAmmo, 255, sizeof(OldAmmo)); - memset (OldMaxAmmo, 255, sizeof(OldMaxAmmo)); - OldHealth = -1; - OldArmor = -1; - OldActiveAmmo = -1; - OldFrags = -9999; - } - DrawMainBar (); - if (CPlayer->inventorytics > 0 && !(level.flags & LEVEL_NOINVENTORYBAR)) - { - DrawInventoryBar (); - SB_state = screen->GetPageCount (); - } - } - } - -private: - struct FDoomStatusBarTexture : public FTexture - { - void DrawToBar (const char *name, int x, int y, const BYTE *colormap_in = NULL); - - public: - FDoomStatusBarTexture (); - const BYTE *GetColumn (unsigned int column, const Span **spans_out); - const BYTE *GetPixels (); - void Unload (); - ~FDoomStatusBarTexture (); - void SetPlayerRemap(FRemapTable *remap); - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); - - FTextureFormat GetFormat() - { - return TEX_RGB; - } - - - protected: - void MakeTexture (); - - FTexture *BaseTexture; - BYTE *Pixels; - FRemapTable *STFBRemap; - } - StatusBarTex; - - void DoCommonInit () - { - static const char *doomLumpNames[] = - { - "STKEYS0", "STKEYS1", "STKEYS2", "STKEYS3", "STKEYS4", - "STKEYS5", "STKEYS6", "STKEYS7", "STKEYS8", - "STGNUM2", "STGNUM3", "STGNUM4", "STGNUM5", "STGNUM6", - "STGNUM7", "MEDIA0", "ARTIBOX", "SELECTBO", "INVGEML1", - "INVGEML2", "INVGEMR1", "INVGEMR2", - }; - - Images.Init (doomLumpNames, NUM_DOOMSB_IMAGES); - - // In case somebody wants to use the Heretic status bar graphics... - { - FTexture *artibox = Images[imgARTIBOX]; - FTexture *selectbox = Images[imgSELECTBOX]; - if (artibox != NULL && selectbox != NULL) - { - selectbox->LeftOffset = artibox->LeftOffset; - selectbox->TopOffset = artibox->TopOffset; - } - } - - StatusBarTex.Unload (); - - SB_state = screen->GetPageCount (); - } - - void DrawMainBar () - { - int amount; - - DrawAmmoStats (); - DrawFace (); - DrawKeys (); - if (!deathmatch) - { - DrawArms (); - } - else - { - if (OldFrags != CPlayer->fragcount) - { - OldFrags = CPlayer->fragcount; - FragsRefresh = screen->GetPageCount (); - } - if (FragsRefresh) - { - FragsRefresh--; - DrawNumber (OldFrags, 138/*110*/, 3, 2); - } - } - if (CPlayer->health != OldHealth) - { - OldHealth = CPlayer->health; - HealthRefresh = screen->GetPageCount (); - } - if (HealthRefresh) - { - HealthRefresh--; - DrawNumber (OldHealth, 90/*48*/, 3); - } - AInventory *armor = CPlayer->mo->FindInventory(); - int armorpoints = armor != NULL ? armor->Amount : 0; - if (armorpoints != OldArmor) - { - OldArmor = armorpoints; - ArmorRefresh = screen->GetPageCount (); - } - if (ArmorRefresh) - { - ArmorRefresh--; - DrawNumber (OldArmor, 221/*179*/, 3); - } - if (CPlayer->ReadyWeapon != NULL) - { - AAmmo *ammo = CPlayer->ReadyWeapon->Ammo1; - amount = ammo != NULL ? ammo->Amount : -9999; - } - else - { - amount = -9999; - } - if (amount != OldActiveAmmo) - { - OldActiveAmmo = amount; - ActiveAmmoRefresh = screen->GetPageCount (); - } - if (ActiveAmmoRefresh) - { - ActiveAmmoRefresh--; - if (OldActiveAmmo != -9999) - { - DrawNumber (OldActiveAmmo, 44/*2*/, 3); - } - else - { - DrawPartialImage (&StatusBarTex, 2, BigWidth*3); - } - } - } - - void DrawArms () - { - BYTE arms[6]; - int i, j; - - // Catalog the weapons the player owns - memset (arms, 0, sizeof(arms)); - for (i = 0; i < 6; i++) - { - for (j = 0; j < MAX_WEAPONS_PER_SLOT; j++) - { - const PClass *weap = LocalWeapons.Slots[i+2].GetWeapon (j); - if (weap != NULL && CPlayer->mo->FindInventory (weap) != NULL) - { - arms[i] = 1; - break; - } - } - } - - // Draw slots that have changed ownership since last time - for (i = 0; i < 6; i++) - { - if (arms[i] != OldArms[i]) - { - ArmsRefresh[i%3] = screen->GetPageCount (); - } - } - - // Remember the arms state for next time - memcpy (OldArms, arms, sizeof(arms)); - - for (i = 0; i < 3; i++) - { - if (ArmsRefresh[i]) - { - ArmsRefresh[i]--; - int x = 111 + i * 12; - - DrawArm (arms[i], i, x, 4, true); - DrawArm (arms[i+3], i+3, x, 14, false); - } - } - } - - void DrawArm (int on, int picnum, int x, int y, bool drawBackground) - { - int w; - FTexture *pic = on ? DBaseStatusBar::Images[imgSmNumbers + 2 + picnum] : Images[imgGNUM2 + picnum]; - - if (pic != NULL) - { - w = pic->GetWidth(); - x -= pic->LeftOffset; - y -= pic->TopOffset; - - if (drawBackground) - { - DrawPartialImage (&StatusBarTex, x, w); - } - DrawImage (pic, x, y); - } - } - - void DrawAmmoStats () - { - static const ENamedName ammoTypes[4] = - { - NAME_Clip, - NAME_Shell, - NAME_RocketAmmo, - NAME_Cell - }; - int ammo[4], maxammo[4]; - int i; - - // Catalog the player's ammo - for (i = 0; i < 4; i++) - { - const PClass *type = PClass::FindClass (ammoTypes[i]); - AInventory *item = CPlayer->mo->FindInventory (type); - if (item != NULL) - { - ammo[i] = item->Amount; - maxammo[i] = item->MaxAmount; - } - else - { - ammo[i] = 0; - maxammo[i] = ((AInventory *)GetDefaultByType (type))->MaxAmount; - } - } - - // Draw ammo amounts that have changed since last time - for (i = 0; i < 4; i++) - { - if (ammo[i] != OldAmmo[i]) - { - AmmoRefresh = screen->GetPageCount (); - } - if (maxammo[i] != OldMaxAmmo[i]) - { - MaxAmmoRefresh = screen->GetPageCount (); - } - } - - // Remember ammo counts for next time - memcpy (OldAmmo, ammo, sizeof(ammo)); - memcpy (OldMaxAmmo, maxammo, sizeof(ammo)); - - if (AmmoRefresh) - { - AmmoRefresh--; - DrawPartialImage (&StatusBarTex, 276, 4*3); - for (i = 0; i < 4; i++) - { - DrSmallNumber (ammo[i], 276, 5 + 6*i); - } - } - if (MaxAmmoRefresh) - { - MaxAmmoRefresh--; - DrawPartialImage (&StatusBarTex, 302, 4*3); - for (i = 0; i < 4; i++) - { - DrSmallNumber (maxammo[i], 302, 5 + 6*i); - } - } - } - - void DrawKeys () - { - AInventory *item; - int keys; - - // Catalog the player's current keys - keys = 0; - for (item = CPlayer->mo->Inventory; item != NULL; item = item->Inventory) - { - if (item->IsKindOf (RUNTIME_CLASS(AKey))) - { - int keynum = static_cast(item)->KeyNumber; - if (keynum >= 1 && keynum <= 6) - { - keys |= 1 << (keynum-1); - } - } - } - - // Remember keys for next time - if (OldKeys != keys) - { - OldKeys = keys; - KeysRefresh = screen->GetPageCount (); - } - - // Draw keys that have changed since last time - if (KeysRefresh) - { - KeysRefresh--; - DrawPartialImage (&StatusBarTex, 239, 8); - - // Blue Keys - switch (keys & (2|16)) - { - case 2: DrawImage (Images[imgKEYS0], 239, 3); break; - case 16: DrawImage (Images[imgKEYS3], 239, 3); break; - case 18: DrawImage (Images[imgKEYS6], 239, 3); break; - } - - // Yellow Keys - switch (keys & (4|32)) - { - case 4: DrawImage (Images[imgKEYS1], 239, 13); break; - case 32: DrawImage (Images[imgKEYS4], 239, 13); break; - case 36: DrawImage (Images[imgKEYS7], 239, 13); break; - } - - // Red Keys - switch (keys & (1|8)) - { - case 1: DrawImage (Images[imgKEYS2], 239, 23); break; - case 8: DrawImage (Images[imgKEYS5], 239, 23); break; - case 9: DrawImage (Images[imgKEYS8], 239, 23); break; - } - } - } - -//--------------------------------------------------------------------------- -// -// PROC DrawInventoryBar -// -//--------------------------------------------------------------------------- - - void DrawInventoryBar () - { - AInventory *item; - int i; - - // If the player has no artifacts, don't draw the bar - CPlayer->mo->InvFirst = ValidateInvFirst (7); - if (CPlayer->mo->InvFirst != NULL) - { - for (item = CPlayer->mo->InvFirst, i = 0; item != NULL && i < 7; item = item->NextInv(), ++i) - { - DrawImage (Images[imgARTIBOX], 50+i*31, 2); - DrawDimImage (TexMan(item->Icon), 50+i*31, 2, item->Amount <= 0); - if (item->Amount != 1) - { - DrSmallNumber (item->Amount, 66+i*31, 24); - } - if (item == CPlayer->mo->InvSel) - { - DrawImage (Images[imgSELECTBOX], 50+i*31, 2); - } - } - for (; i < 7; ++i) - { - DrawImage (Images[imgARTIBOX], 50+i*31, 2); - } - // Is there something to the left? - if (CPlayer->mo->FirstInv() != CPlayer->mo->InvFirst) - { - DrawImage (Images[!(gametic & 4) ? - imgINVLFGEM1 : imgINVLFGEM2], 38, 2); - } - // Is there something to the right? - if (item != NULL) - { - DrawImage (Images[!(gametic & 4) ? - imgINVRTGEM1 : imgINVRTGEM2], 269, 2); - } - } - } - - void DrawNumber (int val, int x, int y, int size=3) - { - DrawPartialImage (&StatusBarTex, x-BigWidth*size, size*BigWidth); - DrBNumber (val, x, y, size); - } - - void DrawFullScreenStuff () - { - AInventory *item; - int i; - int ammotop; - - // Draw health - screen->DrawTexture (Images[imgMEDI], 20, -2, - DTA_HUDRules, HUD_Normal, - DTA_CenterBottomOffset, true, - TAG_DONE); - DrBNumberOuter (CPlayer->health, 40, -BigHeight-4); - - // Draw armor - ABasicArmor *armor = CPlayer->mo->FindInventory(); - if (armor != NULL && armor->Amount != 0) - { - screen->DrawTexture (TexMan(armor->Icon), 20, -24, - DTA_HUDRules, HUD_Normal, - DTA_CenterBottomOffset, true, - TAG_DONE); - DrBNumberOuter (armor->Amount, 40, -39); - } - - // Draw ammo - AAmmo *ammo1, *ammo2; - int ammocount1, ammocount2; - - GetCurrentAmmo (ammo1, ammo2, ammocount1, ammocount2); - ammotop = -1; - if (ammo1 != NULL) - { - FTexture *ammoIcon = TexMan(ammo1->Icon); - // Draw primary ammo in the bottom-right corner - screen->DrawTexture (ammoIcon, -14, -4, - DTA_HUDRules, HUD_Normal, - DTA_CenterBottomOffset, true, - TAG_DONE); - DrBNumberOuter (ammo1->Amount, -67, -4 - BigHeight); - ammotop = -4 - BigHeight; - if (ammo2 != NULL && ammo2!=ammo1) - { - // Draw secondary ammo just above the primary ammo - int y = MIN (-6 - BigHeight, -6 - (ammoIcon != NULL ? ammoIcon->GetHeight() : 0)); - screen->DrawTexture (TexMan(ammo2->Icon), -14, y, - DTA_HUDRules, HUD_Normal, - DTA_CenterBottomOffset, true, - TAG_DONE); - DrBNumberOuter (ammo2->Amount, -67, y - BigHeight); - ammotop = y - BigHeight; - } - } - - if (deathmatch) - { // Draw frags (in DM) - DrBNumberOuter (CPlayer->fragcount, -44, 1); - } - else - { // Draw keys (not DM) - int maxw = 0; - int count = 0; - int x = -2; - int y = vid_fps? 12 : 2; - - for (item = CPlayer->mo->Inventory; item != NULL; item = item->Inventory) - { - if (item->Icon.isValid() && item->IsKindOf (RUNTIME_CLASS(AKey))) - { - FTexture *keypic = TexMan(item->Icon); - if (keypic != NULL) - { - int w = keypic->GetWidth (); - int h = keypic->GetHeight (); - if (w > maxw) - { - maxw = w; - } - screen->DrawTexture (keypic, x, y, - DTA_LeftOffset, w, - DTA_TopOffset, 0, - DTA_HUDRules, HUD_Normal, - TAG_DONE); - if (++count == 3) - { - count = 0; - y = vid_fps? 12 : 2; - x -= maxw + 2; - maxw = 0; - } - else - { - y += h + 2; - } - } - } - } - } - - // Draw inventory - if (!(level.flags & LEVEL_NOINVENTORYBAR)) - { - if (CPlayer->inventorytics == 0) - { - if (CPlayer->mo->InvSel != NULL) - { - screen->DrawTexture (TexMan(CPlayer->mo->InvSel->Icon), -14, ammotop - 1/*-24*/, - DTA_HUDRules, HUD_Normal, - DTA_CenterBottomOffset, true, - DTA_ColorOverlay, CPlayer->mo->InvSel->Amount > 0 ? 0 : DIM_OVERLAY, - TAG_DONE); - DrBNumberOuter (CPlayer->mo->InvSel->Amount, -68, ammotop - 18/*-41*/); - } - } - else - { - CPlayer->mo->InvFirst = ValidateInvFirst (7); - i = 0; - if (CPlayer->mo->InvFirst != NULL) - { - for (item = CPlayer->mo->InvFirst; item != NULL && i < 7; item = item->NextInv(), ++i) - { - screen->DrawTexture (Images[imgARTIBOX], -106+i*31, -32, - DTA_HUDRules, HUD_HorizCenter, - DTA_Alpha, HX_SHADOW, - TAG_DONE); - screen->DrawTexture (TexMan(item->Icon), -105+i*31, -32, - DTA_HUDRules, HUD_HorizCenter, - DTA_ColorOverlay, item->Amount > 0 ? 0 : DIM_OVERLAY, - TAG_DONE); - if (item->Amount != 1) - { - DrSmallNumberOuter (item->Amount, -90+i*31, -10, true); - } - if (item == CPlayer->mo->InvSel) - { - screen->DrawTexture (Images[imgSELECTBOX], -91+i*31, -2, - DTA_HUDRules, HUD_HorizCenter, - DTA_CenterBottomOffset, true, - TAG_DONE); - } - } - for (; i < 7; i++) - { - screen->DrawTexture (Images[imgARTIBOX], -106+i*31, -32, - DTA_HUDRules, HUD_HorizCenter, - DTA_Alpha, HX_SHADOW, - TAG_DONE); - } - // Is there something to the left? - if (CPlayer->mo->FirstInv() != CPlayer->mo->InvFirst) - { - screen->DrawTexture (Images[!(gametic & 4) ? - imgINVLFGEM1 : imgINVLFGEM2], -118, -33, - DTA_HUDRules, HUD_HorizCenter, - TAG_DONE); - } - // Is there something to the right? - if (item != NULL) - { - screen->DrawTexture (Images[!(gametic & 4) ? - imgINVRTGEM1 : imgINVRTGEM2], 113, -33, - DTA_HUDRules, HUD_HorizCenter, - TAG_DONE); - } - } - } - } - } - - int CalcPainOffset () - { - int health; - static int lastcalc; - static int oldhealth = -1; - - health = CPlayer->health > 100 ? 100 : CPlayer->health; - - if (health != oldhealth) - { - lastcalc = ST_FACESTRIDE * (((100 - health) * ST_NUMPAINFACES) / 101); - oldhealth = health; - } - return lastcalc; - } - - void ReceivedWeapon (AWeapon *weapon) - { - MugShot.bEvilGrin = true; - } - - void DrawFace() - { - // If a player has an inventory item selected, it takes the place of the - // face, for lack of a better place to put it. - if (CPlayer->mo->InvSel == NULL || (level.flags & LEVEL_NOINVENTORYBAR)) - { - FTexture *face = MugShot.GetFace(CPlayer, "STF", 5); - if (face != NULL) - { - DrawPartialImage(&StatusBarTex, 142, 37); - DrawImage(face, 143, 0); - } - } - else - { - DrawDimImage(TexMan(CPlayer->mo->InvSel->Icon), 144, 0, CPlayer->mo->InvSel->Amount <= 0); - if (CPlayer->mo->InvSel->Amount != 1) - { - DrSmallNumber(CPlayer->mo->InvSel->Amount, 165, 24); - } - } - } - - void SetMugShotState (const char *state_name, bool wait_till_done, bool reset) - { - MugShot.SetState(state_name, wait_till_done, reset); - } - - enum - { - imgKEYS0, - imgKEYS1, - imgKEYS2, - imgKEYS3, - imgKEYS4, - imgKEYS5, - imgKEYS6, - imgKEYS7, - imgKEYS8, - imgGNUM2, - imgGNUM3, - imgGNUM4, - imgGNUM5, - imgGNUM6, - imgGNUM7, - imgMEDI, - imgARTIBOX, - imgSELECTBOX, - imgINVLFGEM1, - imgINVLFGEM2, - imgINVRTGEM1, - imgINVRTGEM2, - - NUM_DOOMSB_IMAGES - }; - - FImageCollection Images; - - int BigWidth; - int BigHeight; - - int RandomNumber; - BYTE OldArms[6]; - int OldKeys; - int OldAmmo[4]; - int OldMaxAmmo[4]; - int OldHealth; - int OldArmor; - int OldActiveAmmo; - int OldFrags; - - char HealthRefresh; - char ArmorRefresh; - char ActiveAmmoRefresh; - char FragsRefresh; - char ArmsRefresh[3]; - char AmmoRefresh; - char MaxAmmoRefresh; - char KeysRefresh; - - FMugShot MugShot; -}; - -IMPLEMENT_CLASS(DDoomStatusBar) - -DDoomStatusBar::FDoomStatusBarTexture::FDoomStatusBarTexture () -{ - BaseTexture = TexMan["STBAR"]; - if (BaseTexture==NULL) - { - I_Error("Fatal error: STBAR not found"); - } - UseType = FTexture::TEX_MiscPatch; - Name[0]=0; // doesn't need a name - - // now copy all the properties from the base texture - CopySize(BaseTexture); - Pixels = NULL; - STFBRemap = NULL; -} - -const BYTE *DDoomStatusBar::FDoomStatusBarTexture::GetColumn (unsigned int column, const Span **spans_out) -{ - if (Pixels == NULL) - { - MakeTexture (); - } - - BaseTexture->GetColumn(column, spans_out); - return Pixels + column*Height; -} - -const BYTE *DDoomStatusBar::FDoomStatusBarTexture::GetPixels () -{ - if (Pixels == NULL) - { - MakeTexture (); - } - return Pixels; -} - -void DDoomStatusBar::FDoomStatusBarTexture::Unload () -{ - if (Pixels != NULL) - { - delete[] Pixels; - Pixels = NULL; - } -} - -DDoomStatusBar::FDoomStatusBarTexture::~FDoomStatusBarTexture () -{ - Unload (); -} - - -void DDoomStatusBar::FDoomStatusBarTexture::MakeTexture () -{ - Pixels = new BYTE[Width*Height]; - const BYTE *pix = BaseTexture->GetPixels(); - memcpy(Pixels, pix, Width*Height); - if (!deathmatch) DrawToBar("STARMS", 104, 0, NULL); - DrawToBar("STTPRCNT", 90, 3, NULL); - DrawToBar("STTPRCNT", 221, 3, NULL); - if (multiplayer) DrawToBar("STFBANY", 143, 1, STFBRemap? STFBRemap->Remap : NULL); -} - -int DDoomStatusBar::FDoomStatusBarTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) -{ - FTexture *tex; - - // rotate and inf are never used here - BaseTexture->CopyTrueColorPixels(bmp, x, y); - if (!deathmatch) - { - tex = TexMan["STARMS"]; - if (tex != NULL) - { - tex->CopyTrueColorPixels(bmp, x+104, y); - } - } - - tex = TexMan["STTPRCNT"]; - if (tex != NULL) - { - tex->CopyTrueColorPixels(bmp, x+90, y+3); - tex->CopyTrueColorPixels(bmp, x+221, y+3); - } - if (multiplayer) - { - tex = TexMan["STFBANY"]; - if (tex != NULL) - { - tex->CopyTrueColorTranslated(bmp, x+143, y+1, 0, STFBRemap); - } - } - return -1; -} - - - -void DDoomStatusBar::FDoomStatusBarTexture::DrawToBar (const char *name, int x, int y, const BYTE *colormap) -{ - FTexture *pic = TexMan[name]; - if (pic != NULL) - { - x -= pic->LeftOffset; - pic->CopyToBlock (Pixels, Width, Height, x, y, colormap); - } -} - -void DDoomStatusBar::FDoomStatusBarTexture::SetPlayerRemap(FRemapTable *remap) -{ - Unload(); - KillNative(); - STFBRemap = remap; -} - -DBaseStatusBar *CreateDoomStatusBar () -{ - return new DDoomStatusBar; -} diff --git a/src/g_game.cpp b/src/g_game.cpp index 12a3492c4b..e5b5475743 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -2493,6 +2493,9 @@ void G_DoPlayDemo (void) { const char *eek = "Cannot play non-ZDoom demos.\n(They would go out of sync badly.)\n"; + C_RestoreCVars(); + M_Free(demobuffer); + demo_p = demobuffer = NULL; if (singledemo) { I_Error (eek); @@ -2505,11 +2508,13 @@ void G_DoPlayDemo (void) } else if (G_ProcessIFFDemo (mapname)) { + C_RestoreCVars(); gameaction = ga_nothing; demoplayback = false; } else { + // don't spend a lot of time in loadlevel precache = false; demonew = true; diff --git a/src/g_level.cpp b/src/g_level.cpp index e2dc034b2b..5d1d337c0f 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1727,15 +1727,12 @@ void G_InitNew (const char *mapname, bool bTitleLevel) { StatusBar = new DBaseStatusBar (0); } - else if (SBarInfoScript != NULL) + else if (SBarInfoScript[SCRIPT_CUSTOM] != NULL) { - int cstype = SBarInfoScript->GetGameType(); + int cstype = SBarInfoScript[SCRIPT_CUSTOM]->GetGameType(); - if(cstype & GAME_DoomChex) //Did the user specify a "base" - { - StatusBar = CreateDoomStatusBar (); - } - else if(cstype == GAME_Heretic) + //Did the user specify a "base" + if(cstype == GAME_Heretic) { StatusBar = CreateHereticStatusBar(); } @@ -1747,16 +1744,20 @@ void G_InitNew (const char *mapname, bool bTitleLevel) { StatusBar = CreateStrifeStatusBar(); } - else //Use the default, empty or custom. + else if(cstype == GAME_Any) //Use the default, empty or custom. { - StatusBar = CreateCustomStatusBar(); + StatusBar = CreateCustomStatusBar(SCRIPT_CUSTOM); + } + else + { + StatusBar = CreateCustomStatusBar(GETSBARINFOSCRIPT(gameinfo.gametype)); } } if (StatusBar == NULL) { if (gameinfo.gametype & GAME_DoomChex) { - StatusBar = CreateDoomStatusBar (); + StatusBar = CreateCustomStatusBar (GETSBARINFOSCRIPT(gameinfo.gametype)); } else if (gameinfo.gametype == GAME_Heretic) { @@ -1780,7 +1781,7 @@ void G_InitNew (const char *mapname, bool bTitleLevel) StatusBar->NewGame (); setsizeneeded = true; - if (gameinfo.gametype == GAME_Strife || (SBarInfoScript != NULL && SBarInfoScript->GetGameType() == GAME_Strife)) + if (gameinfo.gametype == GAME_Strife || (SBarInfoScript != NULL && SBarInfoScript[SCRIPT_CUSTOM]->GetGameType() == GAME_Strife)) { // Set the initial quest log text for Strife. for (i = 0; i < MAXPLAYERS; ++i) diff --git a/src/g_shared/a_armor.cpp b/src/g_shared/a_armor.cpp index 9cca7f2501..bba36616c3 100644 --- a/src/g_shared/a_armor.cpp +++ b/src/g_shared/a_armor.cpp @@ -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 (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); diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 8858ffd1a0..63c92fa532 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -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; diff --git a/src/g_shared/sbar.h b/src/g_shared/sbar.h index c174d9f11a..89e2b8e7ad 100644 --- a/src/g_shared/sbar.h +++ b/src/g_shared/sbar.h @@ -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); diff --git a/src/g_shared/sbarinfo.h b/src/g_shared/sbarinfo.h index ac739382b8..bd7ef19d77 100644 --- a/src/g_shared/sbarinfo.h +++ b/src/g_shared/sbarinfo.h @@ -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; diff --git a/src/g_shared/sbarinfo_display.cpp b/src/g_shared/sbarinfo_display.cpp index 5fe27d8bc3..224312400e 100644 --- a/src/g_shared/sbarinfo_display.cpp +++ b/src/g_shared/sbarinfo_display.cpp @@ -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 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(); @@ -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(); 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]); } diff --git a/src/g_shared/sbarinfo_parser.cpp b/src/g_shared/sbarinfo_parser.cpp index 5d385ca402..582ed9306e 100644 --- a/src/g_shared/sbarinfo_parser.cpp +++ b/src/g_shared/sbarinfo_parser.cpp @@ -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")) diff --git a/src/p_doors.cpp b/src/p_doors.cpp index 6179c5aa95..7401e3d1b1 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -797,6 +797,7 @@ bool EV_SlidingDoor (line_t *line, AActor *actor, int tag, int speed, int delay) { rtn = true; new DAnimatedDoor (sec, line, speed, delay); + break; } } } diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 52d34ee8f3..313de44246 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -1105,18 +1105,6 @@ FUNC(LS_Thing_Deactivate) return false; } -static void RemoveThing(AActor * actor) -{ - // Don't remove live players. - if (actor->player == NULL || actor != actor->player->mo) - { - // be friendly to the level statistics. ;) - if (actor->CountsAsKill() && actor->health > 0) level.total_monsters--; - if (actor->flags&MF_COUNTITEM) level.total_items--; - actor->Destroy (); - } -} - FUNC(LS_Thing_Remove) // Thing_Remove (tid) { @@ -1130,13 +1118,13 @@ FUNC(LS_Thing_Remove) { AActor *temp = iterator.Next (); - RemoveThing(actor); + P_RemoveThing(actor); actor = temp; } } else if (it != NULL) { - RemoveThing(it); + P_RemoveThing(it); } return true; diff --git a/src/p_local.h b/src/p_local.h index e2fd46142a..2ff6ff4b3d 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -139,6 +139,7 @@ bool P_Thing_Projectile (int tid, AActor *source, int type, const char * type_na bool P_MoveThing(AActor *source, fixed_t x, fixed_t y, fixed_t z, bool fog); bool P_Thing_Move (int tid, AActor *source, int mapspot, bool fog); int P_Thing_Damage (int tid, AActor *whofor0, int amount, FName type); +void P_RemoveThing(AActor * actor); // // P_ENEMY diff --git a/src/p_things.cpp b/src/p_things.cpp index deaddd233b..dc4690da13 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -412,6 +412,19 @@ int P_Thing_Damage (int tid, AActor *whofor0, int amount, FName type) return count; } +void P_RemoveThing(AActor * actor) +{ + // Don't remove live players. + if (actor->player == NULL || actor != actor->player->mo) + { + // be friendly to the level statistics. ;) + if (actor->CountsAsKill() && actor->health > 0) level.total_monsters--; + if (actor->flags&MF_COUNTITEM) level.total_items--; + actor->Destroy (); + } +} + + CCMD (dumpspawnables) { int i; @@ -424,3 +437,4 @@ CCMD (dumpspawnables) } } } + diff --git a/src/r_things.cpp b/src/r_things.cpp index de1e794c14..9c3279e796 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1474,7 +1474,7 @@ void R_ProjectSprite (AActor *thing, int fakeside) // fixed map vis->colormap = fixedcolormap; } - else if (!foggy && (thing->renderflags & RF_FULLBRIGHT)) + else if (!foggy && ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT))) { // full bright if (invertcolormap) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 82b9e8c8ec..06d5b0eba4 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1788,6 +1788,25 @@ DEFINE_ACTION_FUNCTION(AActor, A_KillChildren) } } +//=========================================================================== +// +// A_KillSiblings +// +//=========================================================================== +DEFINE_ACTION_FUNCTION(AActor, A_KillSiblings) +{ + TThinkerIterator it; + AActor * mo; + + while ( (mo = it.Next()) ) + { + if (mo->master == self->master && mo != self) + { + P_DamageMobj(mo, self, self, mo->health, NAME_None, DMG_NO_ARMOR); + } + } +} + //=========================================================================== // // A_CountdownArg @@ -2129,6 +2148,39 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren) // [KS] *** End of my modifications *** +//=========================================================================== +// +// A_DamageSiblings (amount) +// Damages the siblings of this master by the specified amount. Negative values heal. +// +//=========================================================================== +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings) +{ + TThinkerIterator it; + AActor * mo; + + ACTION_PARAM_START(2); + ACTION_PARAM_INT(amount, 0); + ACTION_PARAM_NAME(DamageType, 1); + + while ( (mo = it.Next()) ) + { + if (mo->master == self->master && mo != self) + { + if (amount > 0) + { + P_DamageMobj(mo, self, self, amount, DamageType, DMG_NO_ARMOR); + } + else if (amount < 0) + { + amount = -amount; + P_GiveBody(mo, amount); + } + } + } +} + + //=========================================================================== // // Modified code pointer from Skulltag @@ -2254,3 +2306,36 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag) } } +//=========================================================================== +// +// A_RemoveMaster +// +//=========================================================================== +DEFINE_ACTION_FUNCTION(AActor, A_RemoveMaster) +{ + if (self->master != NULL) + { + P_RemoveThing(self->master); + } +} + +//=========================================================================== +// +// A_RemoveChildren +// +//=========================================================================== +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveChildren) +{ + TThinkerIterator it; + AActor * mo; + ACTION_PARAM_START(1); + ACTION_PARAM_BOOL(removeall,0); + + while ( (mo = it.Next()) ) + { + if ( ( mo->master == self ) && ( ( mo->health <= 0 ) || removeall) ) + { + P_RemoveThing(mo); + } + } +} \ No newline at end of file diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index e4c39310c4..c2cba26392 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -205,6 +205,7 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF5, SPECIALFIREDAMAGE, AActor, flags5), DEFINE_FLAG(MF5, SUMMONEDMONSTER, AActor, flags5), DEFINE_FLAG(MF5, NOVERTICALMELEERANGE, AActor, flags5), + DEFINE_FLAG(MF5, BRIGHT, AActor, flags5), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index d922501bd9..3642d268ee 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -1039,19 +1039,62 @@ DEFINE_CLASS_PROPERTY(savepercent, F, Armor) { PROP_FIXED_PARM(i, 0); - i = clamp(i, 0, 100*FRACUNIT)/100; // Special case here because this property has to work for 2 unrelated classes if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup))) { - ((ABasicArmorPickup*)defaults)->SavePercent = i; + ((ABasicArmorPickup*)defaults)->SavePercent=i; } else if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus))) { - ((ABasicArmorBonus*)defaults)->SavePercent = i; + ((ABasicArmorBonus*)defaults)->SavePercent=i; } else { - I_Error("\"Armor.SavePercent\" requires an actor of type \"Armor\"\n"); + I_Error("\"Armor.SavePercent\" requires an actor of type \"Armor\""); + } +} + +//========================================================================== +// +//========================================================================== +DEFINE_CLASS_PROPERTY(maxabsorb, I, Armor) +{ + PROP_INT_PARM(i, 0); + + // Special case here because this property has to work for 2 unrelated classes + if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup))) + { + ((ABasicArmorPickup*)defaults)->MaxAbsorb = i; + } + else if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus))) + { + ((ABasicArmorBonus*)defaults)->MaxAbsorb = i; + } + else + { + I_Error("\"Armor.MaxAbsorb\" requires an actor of type \"Armor\"\n"); + } +} + +//========================================================================== +// +//========================================================================== +DEFINE_CLASS_PROPERTY(maxfullabsorb, I, Armor) +{ + PROP_INT_PARM(i, 0); + + // Special case here because this property has to work for 2 unrelated classes + if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup))) + { + ((ABasicArmorPickup*)defaults)->MaxFullAbsorb = i; + } + else if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus))) + { + ((ABasicArmorBonus*)defaults)->MaxFullAbsorb = i; + } + else + { + I_Error("\"Armor.MaxFullAbsorb\" requires an actor of type \"Armor\"\n"); } } diff --git a/src/version.h b/src/version.h index d6746d4d34..28ebf9d4cf 100644 --- a/src/version.h +++ b/src/version.h @@ -75,7 +75,7 @@ // SAVESIG should match SAVEVER. // MINSAVEVER is the minimum level snapshot version that can be loaded. -#define MINSAVEVER 1271 +#define MINSAVEVER 1304 #if SVN_REVISION_NUMBER < MINSAVEVER // Never write a savegame with a version lower than what we need diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index cbcfb83031..4fcae343c0 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -54,10 +54,10 @@ ACTOR Actor native //: Thinker action native A_SPosAttackUseAtkSound(); action native A_VileChase(); action native A_VileStart(); - action native A_VileTarget(); + action native A_VileTarget(class fire = "ArchvileFire"); action native A_VileAttack(); action native A_StartFire(); - action native A_Fire(); + action native A_Fire(float spawnheight = 0); action native A_FireCrackle(); action native A_Tracer(); action native A_SkelWhoosh(); @@ -84,7 +84,7 @@ ACTOR Actor native //: Thinker action native A_PainAttack(class spawntype = "LostSoul"); action native A_DualPainAttack(class spawntype = "LostSoul"); action native A_PainDie(class spawntype = "LostSoul"); - action native A_KeenDie(); + action native A_KeenDie(int doortag = 666); action native A_BrainPain(); action native A_BrainScream(); action native A_BrainDie(); @@ -189,8 +189,11 @@ ACTOR Actor native //: Thinker action native A_SetBlend(color color1, float alpha, int tics, color color2 = ""); action native A_ChangeFlag(string flagname, bool value); action native A_JumpIf(bool expression, state label); + action native A_RemoveMaster(); + action native A_RemoveChildren(bool removeall = false); action native A_KillMaster(); action native A_KillChildren(); + action native A_KillSiblings(); action native A_CheckFloor(state label); action native A_PlayerSkinCheck(state label); action native A_BasicAttack(int meleedamage, sound meleesound, class missiletype, float missileheight); @@ -216,6 +219,7 @@ ACTOR Actor native //: Thinker action native A_JumpIfTargetInLOS (state label, float fov = 0, bool projectiletarget = false); action native A_DamageMaster(int amount, name damagetype = "none"); action native A_DamageChildren(int amount, name damagetype = "none"); + action native A_DamageSiblings(int amount, name damagetype = "none"); action native A_SelectWeapon(class whichweapon); action native A_Punch(); action native A_Feathers(); diff --git a/zdoom.vcproj b/zdoom.vcproj index e869a987ab..f18aab9a07 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -2828,10 +2828,6 @@ /> - -