mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-11 07:12:16 +00:00
- P_UndoPlayerMorph scriptified.
Not tested yet and still missing a new native interface.
This commit is contained in:
parent
192104aea2
commit
78d6832d14
10 changed files with 301 additions and 67 deletions
|
@ -105,7 +105,6 @@ public:
|
|||
void GiveDeathmatchInventory ();
|
||||
void FilterCoopRespawnInventory (APlayerPawn *oldplayer);
|
||||
|
||||
void SetupWeaponSlots ();
|
||||
void GiveDefaultInventory ();
|
||||
|
||||
// These are virtual on the script side only.
|
||||
|
|
|
@ -382,31 +382,6 @@ DEFINE_ACTION_FUNCTION(AWeapon, DepleteAmmo)
|
|||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AWeapon :: PostMorphWeapon
|
||||
//
|
||||
// Bring this weapon up after a player unmorphs.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void AWeapon::PostMorphWeapon ()
|
||||
{
|
||||
DPSprite *pspr;
|
||||
if (Owner == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Owner->player->PendingWeapon = WP_NOCHANGE;
|
||||
Owner->player->ReadyWeapon = this;
|
||||
Owner->player->refire = 0;
|
||||
|
||||
pspr = Owner->player->GetPSprite(PSP_WEAPON);
|
||||
pspr->y = WEAPONBOTTOM;
|
||||
pspr->ResetInterpolation();
|
||||
pspr->SetState(GetUpState());
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AWeapon :: GetUpState
|
||||
|
@ -1382,6 +1357,49 @@ void P_PlaybackKeyConfWeapons(FWeaponSlots *slots)
|
|||
PlayingKeyConf = nullptr;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APlayerPawn :: SetupWeaponSlots
|
||||
//
|
||||
// Sets up the default weapon slots for this player. If this is also the
|
||||
// local player, determines local modifications and sends those across the
|
||||
// network. Ignores voodoo dolls.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FWeaponSlots::SetupWeaponSlots(APlayerPawn *pp)
|
||||
{
|
||||
auto player = pp->player;
|
||||
if (player != nullptr && player->mo == pp)
|
||||
{
|
||||
player->weapons.StandardSetup(pp->GetClass());
|
||||
// If we're the local player, then there's a bit more work to do.
|
||||
// This also applies if we're a bot and this is the net arbitrator.
|
||||
if (player - players == consoleplayer ||
|
||||
(player->Bot != nullptr && consoleplayer == Net_Arbitrator))
|
||||
{
|
||||
FWeaponSlots local_slots(player->weapons);
|
||||
if (player->Bot != nullptr)
|
||||
{ // Bots only need weapons from KEYCONF, not INI modifications.
|
||||
P_PlaybackKeyConfWeapons(&local_slots);
|
||||
}
|
||||
else
|
||||
{
|
||||
local_slots.LocalSetup(pp->GetClass());
|
||||
}
|
||||
local_slots.SendDifferences(int(player - players), player->weapons);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FWeaponSlots, SetupWeaponSlots)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_OBJECT(pawn, APlayerPawn);
|
||||
FWeaponSlots::SetupWeaponSlots(pawn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// P_SetupWeapons_ntohton
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "a_pickups.h"
|
||||
class PClassActor;
|
||||
class AWeapon;
|
||||
class APlayerPawn;
|
||||
|
||||
class FWeaponSlot
|
||||
{
|
||||
|
@ -71,6 +72,7 @@ struct FWeaponSlots
|
|||
void SendDifferences(int playernum, const FWeaponSlots &other);
|
||||
int RestoreSlots (FConfigFile *config, const char *section);
|
||||
void PrintSettings();
|
||||
static void SetupWeaponSlots(APlayerPawn *pp);
|
||||
|
||||
void AddSlot(int slot, PClassActor *type, bool feedback);
|
||||
void AddSlotDefault(int slot, PClassActor *type, bool feedback);
|
||||
|
@ -126,8 +128,6 @@ public:
|
|||
void Finalize(FStateDefinitions &statedef) override;
|
||||
void Serialize(FSerializer &arc) override;
|
||||
|
||||
void PostMorphWeapon();
|
||||
|
||||
// scripted virtuals.
|
||||
FState *GetUpState ();
|
||||
FState *GetDownState ();
|
||||
|
|
|
@ -38,6 +38,18 @@
|
|||
|
||||
static FRandom pr_morphmonst ("MorphMonster");
|
||||
|
||||
|
||||
bool P_MorphPlayer(player_t *activator, player_t *p, PClassActor *spawntype, int duration, int style, PClassActor *enter_flash, PClassActor *exit_flash)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool P_UndoPlayerMorph(player_t *activator, player_t *player, int unmorphflag, bool force)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void EndAllPowerupEffects(AInventory *item);
|
||||
void InitAllPowerupEffects(AInventory *item);
|
||||
|
||||
|
@ -336,7 +348,7 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag,
|
|||
beastweap = player->ReadyWeapon;
|
||||
if (player->PremorphWeapon != nullptr)
|
||||
{
|
||||
player->PremorphWeapon->PostMorphWeapon ();
|
||||
player->PremorphWeapon-> P ostMorphWeapon ();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -386,9 +398,11 @@ DEFINE_ACTION_FUNCTION(_PlayerInfo, UndoPlayerMorph)
|
|||
PARAM_POINTER_NOT_NULL(player, player_t);
|
||||
PARAM_INT(unmorphflag);
|
||||
PARAM_BOOL(force);
|
||||
ACTION_RETURN_BOOL(P_UndoPlayerMorph(self, player, unmorphflag, force));
|
||||
ACTION_RETURN_BOOL(P_UndoPlayerMorph(player, self, unmorphflag, force));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_MorphMonster
|
||||
|
|
|
@ -1025,7 +1025,7 @@ void G_SerializeLevel(FSerializer &arc, bool hubload)
|
|||
{
|
||||
if (playeringame[i] && players[i].mo != NULL)
|
||||
{
|
||||
players[i].mo->SetupWeaponSlots();
|
||||
FWeaponSlots::SetupWeaponSlots(players[i].mo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -916,7 +916,7 @@ void APlayerPawn::Tick()
|
|||
void APlayerPawn::PostBeginPlay()
|
||||
{
|
||||
Super::PostBeginPlay();
|
||||
SetupWeaponSlots();
|
||||
FWeaponSlots::SetupWeaponSlots(this);
|
||||
|
||||
// Voodoo dolls: restore original floorz/ceilingz logic
|
||||
if (player == NULL || player->mo != this)
|
||||
|
@ -931,40 +931,6 @@ void APlayerPawn::PostBeginPlay()
|
|||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APlayerPawn :: SetupWeaponSlots
|
||||
//
|
||||
// Sets up the default weapon slots for this player. If this is also the
|
||||
// local player, determines local modifications and sends those across the
|
||||
// network. Ignores voodoo dolls.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void APlayerPawn::SetupWeaponSlots()
|
||||
{
|
||||
if (player != NULL && player->mo == this)
|
||||
{
|
||||
player->weapons.StandardSetup(GetClass());
|
||||
// If we're the local player, then there's a bit more work to do.
|
||||
// This also applies if we're a bot and this is the net arbitrator.
|
||||
if (player - players == consoleplayer ||
|
||||
(player->Bot != NULL && consoleplayer == Net_Arbitrator))
|
||||
{
|
||||
FWeaponSlots local_slots(player->weapons);
|
||||
if (player->Bot != NULL)
|
||||
{ // Bots only need weapons from KEYCONF, not INI modifications.
|
||||
P_PlaybackKeyConfWeapons(&local_slots);
|
||||
}
|
||||
else
|
||||
{
|
||||
local_slots.LocalSetup(GetClass());
|
||||
}
|
||||
local_slots.SendDifferences(int(player - players), player->weapons);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APlayerPawn :: AddInventory
|
||||
|
|
|
@ -186,6 +186,7 @@ PFunction *FindClassMemberFunction(PContainerType *selfcls, PContainerType *func
|
|||
auto cls_target = funcsym ? PType::toClass(funcsym->OwningClass) : nullptr;
|
||||
if (funcsym == nullptr)
|
||||
{
|
||||
if (PClass::FindClass(name)) return nullptr; // Special case when a class's member variable hides a global class name. This should still work.
|
||||
sc.Message(MSG_ERROR, "%s is not a member function of %s", name.GetChars(), selfcls->TypeName.GetChars());
|
||||
}
|
||||
else if ((funcsym->Variants[0].Flags & VARF_Private) && symtable != &funccls->Symbols)
|
||||
|
|
|
@ -677,6 +677,33 @@ class Weapon : StateProvider native
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Weapon :: PostMorphWeapon
|
||||
//
|
||||
// Bring this weapon up after a player unmorphs.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void PostMorphWeapon ()
|
||||
{
|
||||
if (Owner == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
let p = owner.player;
|
||||
p.PendingWeapon = WP_NOCHANGE;
|
||||
p.ReadyWeapon = self;
|
||||
p.refire = 0;
|
||||
|
||||
let pspr = p.GetPSprite(PSP_WEAPON);
|
||||
pspr.y = WEAPONBOTTOM;
|
||||
pspr.ResetInterpolation();
|
||||
pspr.SetState(GetUpState());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -746,4 +773,5 @@ class WeaponGiver : Weapon
|
|||
struct WeaponSlots native
|
||||
{
|
||||
native bool, int, int LocateWeapon(class<Weapon> weap);
|
||||
native static void SetupWeaponSlots(PlayerPawn pp);
|
||||
}
|
||||
|
|
|
@ -214,6 +214,198 @@ extend class PlayerPawn
|
|||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_UndoPlayerMorph
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
virtual bool UndoPlayerMorph(playerinfo activator, int unmorphflag = 0, bool force = false)
|
||||
{
|
||||
if (alternative == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
let player = self.player;
|
||||
bool DeliberateUnmorphIsOkay = !!(MRF_STANDARDUNDOING & unmorphflag);
|
||||
|
||||
if ((bInvulnerable) // If the player is invulnerable
|
||||
&& ((player != activator) // and either did not decide to unmorph,
|
||||
|| (!((player.MorphStyle & MRF_WHENINVULNERABLE) // or the morph style does not allow it
|
||||
|| (DeliberateUnmorphIsOkay))))) // (but standard morph styles always allow it),
|
||||
{ // Then the player is immune to the unmorph.
|
||||
return false;
|
||||
}
|
||||
|
||||
let altmo = PlayerPawn(alternative);
|
||||
altmo.SetOrigin (Pos, false);
|
||||
altmo.bSolid = true;
|
||||
bSolid = false;
|
||||
if (!force && !altmo.TestMobjLocation())
|
||||
{ // Didn't fit
|
||||
altmo.bSolid = false;
|
||||
bSolid = true;
|
||||
player.morphTics = 2*TICRATE;
|
||||
return false;
|
||||
}
|
||||
// No longer using tracer as morph storage. That is what 'alternative' is for.
|
||||
// If the tracer has changed on the morph, change the original too.
|
||||
altmo.target = target;
|
||||
altmo.tracer = tracer;
|
||||
self.player = null;
|
||||
altmo.alternative = alternative = null;
|
||||
|
||||
// Remove the morph power if the morph is being undone prematurely.
|
||||
for (Inventory item = Inv; item != null;)
|
||||
{
|
||||
let next = item.Inv;
|
||||
if (item is "PowerMorph")
|
||||
{
|
||||
item.Destroy();
|
||||
}
|
||||
item = next;
|
||||
}
|
||||
EndAllPowerupEffects();
|
||||
altmo.ObtainInventory (self);
|
||||
Substitute(altmo);
|
||||
if ((tid != 0) && (player.MorphStyle & MRF_NEWTIDBEHAVIOUR))
|
||||
{
|
||||
altmo.ChangeTid(tid);
|
||||
}
|
||||
altmo.Angle = Angle;
|
||||
altmo.player = player;
|
||||
altmo.reactiontime = 18;
|
||||
altmo.bSolid = !!(special2 & 2);
|
||||
altmo.bShootable = !!(special2 & 4);
|
||||
altmo.bInvisible = !!(special2 & 0x40);
|
||||
altmo.Vel.XY = (0, 0);
|
||||
player.Vel = (0, 0);
|
||||
altmo.Vel.Z = Vel.Z;
|
||||
altmo.floorz = floorz;
|
||||
altmo.bShadow = bShadow;
|
||||
altmo.bNoGravity = bNoGravity;
|
||||
altmo.bGhost = bGhost;
|
||||
altmo.Score = Score;
|
||||
altmo.InitAllPowerupEffects();
|
||||
|
||||
let exit_flash = player.MorphExitFlash;
|
||||
bool correctweapon = !!(player.MorphStyle & MRF_LOSEACTUALWEAPON);
|
||||
bool undobydeathsaves = !!(player.MorphStyle & MRF_UNDOBYDEATHSAVES);
|
||||
|
||||
player.morphTics = 0;
|
||||
player.MorphedPlayerClass = null;
|
||||
player.MorphStyle = 0;
|
||||
player.MorphExitFlash = null;
|
||||
player.viewheight = altmo.ViewHeight;
|
||||
Inventory level2 = altmo.FindInventory("PowerWeaponLevel2", true);
|
||||
if (level2 != null)
|
||||
{
|
||||
level2.Destroy ();
|
||||
}
|
||||
|
||||
if ((player.health > 0) || undobydeathsaves)
|
||||
{
|
||||
player.health = altmo.health = altmo.SpawnHealth();
|
||||
}
|
||||
else // killed when morphed so stay dead
|
||||
{
|
||||
altmo.health = player.health;
|
||||
}
|
||||
|
||||
player.mo = altmo;
|
||||
if (player.camera == self)
|
||||
{
|
||||
player.camera = altmo;
|
||||
}
|
||||
|
||||
// [MH]
|
||||
// If the player that was morphed is the one
|
||||
// taking events, reset up the face, if any;
|
||||
// this is only needed for old-skool skins
|
||||
// and for the original DOOM status bar.
|
||||
if (player == players[consoleplayer])
|
||||
{
|
||||
if (face != 'None')
|
||||
{
|
||||
// Assume root-level base skin to begin with
|
||||
let skinindex = 0;
|
||||
let skin = player.GetSkin();
|
||||
// If a custom skin was in use, then reload it
|
||||
// or else the base skin for the player class.
|
||||
if (skin >= PlayerClasses.Size () && skin < PlayerSkins.Size())
|
||||
{
|
||||
skinindex = skin;
|
||||
}
|
||||
else if (PlayerClasses.Size () > 1)
|
||||
{
|
||||
let whatami = altmo.GetClass();
|
||||
for (int i = 0; i < PlayerClasses.Size (); ++i)
|
||||
{
|
||||
if (PlayerClasses[i].Type == whatami)
|
||||
{
|
||||
skinindex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Actor eflash = null;
|
||||
if (exit_flash != null)
|
||||
{
|
||||
eflash = Spawn(exit_flash, Vec3Angle(20., altmo.Angle, gameinfo.telefogheight), ALLOW_REPLACE);
|
||||
if (eflash) eflash.target = altmo;
|
||||
}
|
||||
WeaponSlots.SetupWeaponSlots(altmo); // Use original class's weapon slots.
|
||||
let beastweap = player.ReadyWeapon;
|
||||
if (player.PremorphWeapon != null)
|
||||
{
|
||||
player.PremorphWeapon.PostMorphWeapon ();
|
||||
}
|
||||
else
|
||||
{
|
||||
player.ReadyWeapon = player.PendingWeapon = null;
|
||||
}
|
||||
if (correctweapon)
|
||||
{ // Better "lose morphed weapon" semantics
|
||||
class<Actor> morphweaponcls = MorphWeapon;
|
||||
if (morphweaponcls != null && morphweaponcls is 'Weapon')
|
||||
{
|
||||
let OriginalMorphWeapon = Weapon(altmo.FindInventory (morphweapon));
|
||||
if ((OriginalMorphWeapon != null) && (OriginalMorphWeapon.GivenAsMorphWeapon))
|
||||
{ // You don't get to keep your morphed weapon.
|
||||
if (OriginalMorphWeapon.SisterWeapon != null)
|
||||
{
|
||||
OriginalMorphWeapon.SisterWeapon.Destroy ();
|
||||
}
|
||||
OriginalMorphWeapon.Destroy ();
|
||||
}
|
||||
}
|
||||
}
|
||||
else // old behaviour (not really useful now)
|
||||
{ // Assumptions made here are no longer valid
|
||||
if (beastweap != null)
|
||||
{ // You don't get to keep your morphed weapon.
|
||||
if (beastweap.SisterWeapon != null)
|
||||
{
|
||||
beastweap.SisterWeapon.Destroy ();
|
||||
}
|
||||
beastweap.Destroy ();
|
||||
}
|
||||
}
|
||||
Destroy ();
|
||||
// Restore playerclass armor to its normal amount.
|
||||
let hxarmor = HexenArmor(altmo.FindInventory('HexenArmor'));
|
||||
if (hxarmor != null)
|
||||
{
|
||||
hxarmor.Slots[4] = altmo.HexenArmor[0];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class MorphProjectile : Actor
|
||||
|
|
|
@ -1358,6 +1358,13 @@ class PSprite : Object native play
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResetInterpolation()
|
||||
{
|
||||
oldx = x;
|
||||
oldy = y;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum EPlayerState
|
||||
|
@ -1480,7 +1487,16 @@ struct PlayerInfo native play // this is what internally is known as player_t
|
|||
return false;
|
||||
}
|
||||
|
||||
native bool UndoPlayerMorph(playerinfo player, int unmorphflag = 0, bool force = false);
|
||||
// This somehow got its arguments mixed up. 'self' should have been the player to be unmorphed, not the activator
|
||||
bool UndoPlayerMorph(playerinfo player, int unmorphflag = 0, bool force = false)
|
||||
{
|
||||
if (player.mo != null)
|
||||
{
|
||||
return player.mo.UndoPlayerMorph(self, unmorphflag, force);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
native bool PoisonPlayer(Actor poisoner, Actor source, int poison);
|
||||
native void PoisonDamage(Actor source, int damage, bool playPainSound);
|
||||
native void SetPsprite(int id, State stat, bool pending = false);
|
||||
|
|
Loading…
Reference in a new issue