diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 2adc83c92..a6b9ba5a9 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -1690,7 +1690,7 @@ static int PatchWeapon (int weapNum) } else if (stricmp (Line1, "Min ammo") == 0) { - info->MinAmmo1 = val; + info->MinSelAmmo1 = val; } else { diff --git a/src/d_player.h b/src/d_player.h index 774aba83d..cf2fffa0a 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -94,7 +94,6 @@ public: virtual bool UseInventory (AInventory *item) override; virtual void MarkPrecacheSounds () const override; virtual void BeginPlay () override; - virtual void Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOfDeath) override; virtual bool UpdateWaterLevel (bool splash) override; bool ResetAirSupply (bool playgasp = true); diff --git a/src/g_inventory/a_weapons.h b/src/g_inventory/a_weapons.h index 747f0bdb3..fcc3b1134 100644 --- a/src/g_inventory/a_weapons.h +++ b/src/g_inventory/a_weapons.h @@ -119,9 +119,9 @@ public: TObjPtr SisterWeapon; float FOVScale; int Crosshair; // 0 to use player's crosshair - bool GivenAsMorphWeapon; + bool GivenAsMorphWeapon; // *** only accessed from ZScript. - bool bAltFire; // Set when this weapon's alternate fire is used. + bool bAltFire; // *** only accessed from ZScript. Set when this weapon's alternate fire is used. virtual void MarkPrecacheSounds() const; diff --git a/src/g_level.cpp b/src/g_level.cpp index 775d226fa..392e1e63e 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1513,6 +1513,7 @@ void G_InitLevelLocals () level.fogdensity = info->fogdensity; level.outsidefogdensity = info->outsidefogdensity; level.skyfog = info->skyfog; + level.deathsequence = info->deathsequence; level.pixelstretch = info->pixelstretch; @@ -2238,6 +2239,7 @@ DEFINE_FIELD(FLevelLocals, fogdensity) DEFINE_FIELD(FLevelLocals, outsidefogdensity) DEFINE_FIELD(FLevelLocals, skyfog) DEFINE_FIELD(FLevelLocals, pixelstretch) +DEFINE_FIELD(FLevelLocals, deathsequence) DEFINE_FIELD_BIT(FLevelLocals, flags, noinventorybar, LEVEL_NOINVENTORYBAR) DEFINE_FIELD_BIT(FLevelLocals, flags, monsterstelefrag, LEVEL_MONSTERSTELEFRAG) DEFINE_FIELD_BIT(FLevelLocals, flags, actownspecial, LEVEL_ACTOWNSPECIAL) @@ -2304,3 +2306,12 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, ChangeSky) R_InitSkyMap(); return 0; } + +DEFINE_ACTION_FUNCTION(FLevelLocals, StartIntermission) +{ + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + PARAM_NAME(seq); + PARAM_INT(state); + F_StartIntermission(seq, (uint8_t)state); + return 0; +} diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 86050b68c..ffb4aad61 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -175,6 +175,7 @@ struct FLevelLocals int outsidefogdensity; int skyfog; + FName deathsequence; float pixelstretch; float MusicVolume; diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index 30ef3fa40..65f31910e 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -872,7 +872,6 @@ void F_StartIntermission(FName seq, uint8_t state) } } - //========================================================================== // // Called by main loop. diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index ff375974c..3dea0a8a7 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -4512,8 +4512,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DropItem) PARAM_INT(amount); PARAM_INT(chance); - P_DropItem(self, spawntype, amount, chance); - return 0; + ACTION_RETURN_OBJECT(P_DropItem(self, spawntype, amount, chance)); } //=========================================================================== diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index a87e0c812..0e2968d9b 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -3225,7 +3225,7 @@ void ModifyDropAmount(AInventory *inv, int dropamount) CVAR(Int, sv_dropstyle, 0, CVAR_SERVERINFO | CVAR_ARCHIVE); -AInventory *P_DropItem (AActor *source, PClassActor *type, int dropamount, int chance) +AActor *P_DropItem (AActor *source, PClassActor *type, int dropamount, int chance) { if (type != NULL && pr_dropitem() <= chance) { @@ -3276,9 +3276,8 @@ AInventory *P_DropItem (AActor *source, PClassActor *type, int dropamount, int c return NULL; } } - return inv; } - // we can't really return an AInventory pointer to a non-inventory item here, can we? + return mo; } } return NULL; diff --git a/src/p_enemy.h b/src/p_enemy.h index 0e917e0af..4dff6f810 100644 --- a/src/p_enemy.h +++ b/src/p_enemy.h @@ -53,7 +53,7 @@ bool P_CheckMeleeRange2 (AActor *actor); bool P_Move (AActor *actor); bool P_TryWalk (AActor *actor); void P_NewChaseDir (AActor *actor); -AInventory *P_DropItem (AActor *source, PClassActor *type, int special, int chance); +AActor *P_DropItem (AActor *source, PClassActor *type, int special, int chance); void P_TossItem (AActor *item); bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params); void A_Weave(AActor *self, int xyspeed, int zspeed, double xydist, double zdist); diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index fa1e6f105..5436cfbe7 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -972,6 +972,7 @@ void G_SerializeLevel(FSerializer &arc, bool hubload) ("level.fogdensity", level.fogdensity) ("level.outsidefogdensity", level.outsidefogdensity) ("level.skyfog", level.skyfog) + ("level.deathsequence", level.deathsequence) ("level.bodyqueslot", level.bodyqueslot) .Array("level.bodyque", level.bodyque, level.BODYQUESIZE); diff --git a/src/p_user.cpp b/src/p_user.cpp index e70543a8b..e4f964df3 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1351,88 +1351,6 @@ void APlayerPawn::GiveDefaultInventory () } } -//=========================================================================== -// -// APlayerPawn :: Die -// -//=========================================================================== - -void APlayerPawn::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOfDeath) -{ - Super::Die (source, inflictor, dmgflags, MeansOfDeath); - - if (player != NULL && player->mo == this) player->bonuscount = 0; - - if (player != NULL && player->mo != this) - { // Make the real player die, too - player->mo->CallDie (source, inflictor, dmgflags, MeansOfDeath); - } - else - { - if (player != NULL && (dmflags2 & DF2_YES_WEAPONDROP)) - { // Voodoo dolls don't drop weapons - AWeapon *weap = player->ReadyWeapon; - if (weap != NULL) - { - AInventory *item; - - // kgDROP - start - modified copy from a_action.cpp - auto di = weap->GetDropItems(); - - if (di != NULL) - { - while (di != NULL) - { - if (di->Name != NAME_None) - { - PClassActor *ti = PClass::FindActor(di->Name); - if (ti) P_DropItem (player->mo, ti, di->Amount, di->Probability); - } - di = di->Next; - } - } else - // kgDROP - end - if (weap->SpawnState != NULL && - weap->SpawnState != ::GetDefault()->SpawnState) - { - item = P_DropItem (this, weap->GetClass(), -1, 256); - if (item != NULL && item->IsKindOf(NAME_Weapon)) - { - if (weap->AmmoGive1 && weap->Ammo1) - { - static_cast(item)->AmmoGive1 = weap->Ammo1->Amount; - } - if (weap->AmmoGive2 && weap->Ammo2) - { - static_cast(item)->AmmoGive2 = weap->Ammo2->Amount; - } - item->ItemFlags |= IF_IGNORESKILL; - } - } - else - { - item = P_DropItem (this, weap->AmmoType1, -1, 256); - if (item != NULL) - { - item->Amount = weap->Ammo1->Amount; - item->ItemFlags |= IF_IGNORESKILL; - } - item = P_DropItem (this, weap->AmmoType2, -1, 256); - if (item != NULL) - { - item->Amount = weap->Ammo2->Amount; - item->ItemFlags |= IF_IGNORESKILL; - } - } - } - } - if (!multiplayer && level.info->deathsequence != NAME_None) - { - F_StartIntermission(level.info->deathsequence, FSTATE_EndingGame); - } - } -} - //=========================================================================== // // A_PlayerScream diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 49762d994..3db5669f9 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -1070,7 +1070,7 @@ class Actor : Thinker native native void A_Quake(int intensity, int duration, int damrad, int tremrad, sound sfx = "world/quake"); native void A_QuakeEx(int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, sound sfx = "world/quake", int flags = 0, double mulWaveX = 1, double mulWaveY = 1, double mulWaveZ = 1, int falloff = 0, int highpoint = 0, double rollIntensity = 0, double rollWave = 0); action native void A_SetTics(int tics); - native void A_DropItem(class item, int dropamount = -1, int chance = 256); + native Actor A_DropItem(class item, int dropamount = -1, int chance = 256); native void A_DamageSelf(int amount, name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); native void A_DamageTarget(int amount, name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); native void A_DamageMaster(int amount, name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 0bf5cc175..67c1893cc 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -655,6 +655,7 @@ struct LevelLocals native native readonly int outsidefogdensity; native readonly int skyfog; native readonly float pixelstretch; + native name deathsequence; // level_info_t *info cannot be done yet. native String GetUDMFString(int type, int index, Name key); @@ -670,6 +671,7 @@ struct LevelLocals native native bool IsJumpingAllowed() const; native bool IsCrouchingAllowed() const; native bool IsFreelookAllowed() const; + native void StartIntermission(Name type, int state) const; native static clearscope bool IsPointInMap(vector3 p); diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index fe2c8a901..8a1240f10 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1257,3 +1257,11 @@ enum RadiusDamageFlags RADF_THRUSTZ = 16, RADF_OLDRADIUSDAMAGE = 32 }; + +enum IntermissionSequenceType +{ + FSTATE_EndingGame = 0, + FSTATE_ChangingLevel = 1, + FSTATE_InLevel = 2 +}; + diff --git a/wadsrc/static/zscript/shared/morph.txt b/wadsrc/static/zscript/shared/morph.txt index 4c6762125..3a1662915 100644 --- a/wadsrc/static/zscript/shared/morph.txt +++ b/wadsrc/static/zscript/shared/morph.txt @@ -560,7 +560,7 @@ extend class PlayerPawn override Actor, int, int MorphedDeath() { // Voodoo dolls should not unmorph the real player here. - if ((player.mo == self) && + if (player && (player.mo == self) && (player.morphTics) && (player.MorphStyle & MRF_UNDOBYDEATH) && (alternative)) diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 72cee7276..9747ef1dd 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -154,7 +154,7 @@ class PlayerPawn : Actor native let invul = Powerup(Spawn("PowerInvulnerable")); invul.EffectTics = 3 * TICRATE; invul.BlendColor = 0; // don't mess with the view - invul.bUndroppable = true; // Don't drop this + invul.bUndroppable = true; // Don't drop self bRespawnInvul = true; // [RH] special effect } } @@ -363,7 +363,7 @@ class PlayerPawn : Actor native // // PROC P_CheckWeaponChange // - // The player can change to another weapon at this time. + // The player can change to another weapon at self time. // [GZ] This was cut from P_CheckWeaponFire. // //--------------------------------------------------------------------------- @@ -537,6 +537,84 @@ class PlayerPawn : Actor native } } + //=========================================================================== + // + // APlayerPawn :: Die + // + //=========================================================================== + + override void Die (Actor source, Actor inflictor, int dmgflags, Name MeansOfDeath) + { + Super.Die (source, inflictor, dmgflags, MeansOfDeath); + + if (player != NULL && player.mo == self) player.bonuscount = 0; + + if (player != NULL && player.mo != self) + { // Make the real player die, too + player.mo.Die (source, inflictor, dmgflags, MeansOfDeath); + } + else + { + if (player != NULL && sv_weapondrop) + { // Voodoo dolls don't drop weapons + let weap = player.ReadyWeapon; + if (weap != NULL) + { + // kgDROP - start - modified copy from a_action.cpp + let di = weap.GetDropItems(); + + if (di != NULL) + { + while (di != NULL) + { + if (di.Name != 'None') + { + class ti = di.Name; + if (ti) A_DropItem (ti, di.Amount, di.Probability); + } + di = di.Next; + } + } + else if (weap.SpawnState != NULL && + weap.SpawnState != GetDefaultByType('Actor').SpawnState) + { + let weapitem = Weapon(A_DropItem (weap.GetClass(), -1, 256)); + if (weapitem) + { + if (weap.AmmoGive1 && weap.Ammo1) + { + weapitem.AmmoGive1 = weap.Ammo1.Amount; + } + if (weap.AmmoGive2 && weap.Ammo2) + { + weapitem.AmmoGive2 = weap.Ammo2.Amount; + } + weapitem.bIgnoreSkill = true; + } + } + else + { + let item = Inventory(A_DropItem (weap.AmmoType1, -1, 256)); + if (item != NULL) + { + item.Amount = weap.Ammo1.Amount; + item.bIgnoreSkill = true; + } + item = Inventory(A_DropItem (weap.AmmoType2, -1, 256)); + if (item != NULL) + { + item.Amount = weap.Ammo2.Amount; + item.bIgnoreSkill = true; + } + } + } + } + if (!multiplayer && level.deathsequence != 'None') + { + level.StartIntermission(level.deathsequence, FSTATE_EndingGame); + } + } + } //---------------------------------------------------------------------------- // // PROC P_CheckFOV @@ -1244,7 +1322,7 @@ class PlayerPawn : Actor native CheckUse(); CheckUndoMorph(); // Cycle psprites. - // Note that after this point the PlayerPawn may have changed due to getting unmorphed so 'self' is no longer safe to use. + // Note that after self point the PlayerPawn may have changed due to getting unmorphed so 'self' is no longer safe to use. player.mo.TickPSprites(); // Other Counters if (player.damagecount) player.damagecount--; @@ -1285,7 +1363,7 @@ class PlayerPawn : Actor native let weapon = player.PendingWeapon; - // If the player has a tome of power, use this weapon's powered up + // If the player has a tome of power, use self weapon's powered up // version, if one is available. if (weapon != null && weapon.SisterWeapon && @@ -1345,7 +1423,7 @@ class PlayerPawn : Actor native weap.Ammo1.GetClass() != ammotype)) continue; - // Don't select it if the Tome is active and this isn't the powered-up version. + // Don't select it if the Tome is active and self isn't the powered-up version. if (tomed && weap.SisterWeapon != NULL && weap.SisterWeapon.bPowered_Up) continue; @@ -1400,7 +1478,7 @@ class PlayerPawn : Actor native // // APlayerPawn :: PickNewWeapon // - // Picks a new weapon for this player. Used mostly for running out of ammo, + // Picks a new weapon for self player. Used mostly for running out of ammo, // but it also works when an ACS script explicitly takes the ready weapon // away or the player picks up some ammo they had previously run out of. // @@ -1632,7 +1710,7 @@ enum EPlayerGender GENDER_OTHER } -struct PlayerInfo native play // this is what internally is known as player_t +struct PlayerInfo native play // self is what internally is known as player_t { // technically engine constants but the only part of the playsim using them is the player. const NOFIXEDCOLORMAP = -1;