- scriptified cht_Give and cht_Take and made them virtual function of PlayerPawn so that this can be better configured for mods that want other options in here.

- improved the class pointer to string cast to print the actual type it describes and not the class pointer's own type.
- fixed: The 'is' operator created non-working code when checking the inheritance of a class pointer, it only worked for objects.
This commit is contained in:
Christoph Oelckers 2017-01-17 17:31:54 +01:00
commit 14f2c39e58
21 changed files with 559 additions and 461 deletions

View file

@ -50,6 +50,7 @@
#include "a_armor.h"
#include "a_ammo.h"
#include "g_levellocals.h"
#include "virtual.h"
// [RH] Actually handle the cheat. The cheat code in st_stuff.c now just
// writes some bytes to the network data stream, and the network code
@ -324,16 +325,10 @@ void cht_DoCheat (player_t *player, int cheat)
}
else
{
player->mo->Revive();
player->playerstate = PST_LIVE;
player->health = player->mo->health = player->mo->GetDefault()->health;
player->viewheight = ((APlayerPawn *)player->mo->GetDefault())->ViewHeight;
player->mo->flags = player->mo->GetDefault()->flags;
player->mo->flags2 = player->mo->GetDefault()->flags2;
player->mo->flags3 = player->mo->GetDefault()->flags3;
player->mo->flags4 = player->mo->GetDefault()->flags4;
player->mo->flags5 = player->mo->GetDefault()->flags5;
player->mo->flags6 = player->mo->GetDefault()->flags6;
player->mo->flags7 = player->mo->GetDefault()->flags7;
player->mo->renderflags &= ~RF_INVISIBLE;
player->mo->Height = player->mo->GetDefault()->Height;
player->mo->radius = player->mo->GetDefault()->radius;
@ -344,7 +339,6 @@ void cht_DoCheat (player_t *player, int cheat)
{
player->mo->Translation = TRANSLATION(TRANSLATION_Players, BYTE(player-players));
}
player->mo->DamageType = NAME_None;
if (player->ReadyWeapon != nullptr)
{
P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->GetUpState());
@ -588,434 +582,24 @@ const char *cht_Morph (player_t *player, PClassPlayerPawn *morphclass, bool quic
void cht_Give (player_t *player, const char *name, int amount)
{
enum { ALL_NO, ALL_YES, ALL_YESYES } giveall;
int i;
PClassActor *type;
if (player->mo == nullptr) return;
if (player != &players[consoleplayer])
Printf ("%s is a cheater: give %s\n", player->userinfo.GetName(), name);
if (player->mo == NULL || player->health <= 0)
IFVIRTUALPTR(player->mo, APlayerPawn, CheatGive)
{
return;
VMValue params[3] = { player->mo, FString(name), amount };
GlobalVMStack.Call(func, params, 3, nullptr, 0);
}
giveall = ALL_NO;
if (stricmp (name, "all") == 0)
{
giveall = ALL_YES;
}
else if (stricmp (name, "everything") == 0)
{
giveall = ALL_YESYES;
}
if (stricmp (name, "health") == 0)
{
if (amount > 0)
{
player->mo->health += amount;
player->health = player->mo->health;
}
else
{
player->health = player->mo->health = player->mo->GetMaxHealth();
}
}
if (giveall || stricmp (name, "backpack") == 0)
{
// Select the correct type of backpack based on the game
type = PClass::FindActor(gameinfo.backpacktype);
if (type != NULL)
{
player->mo->GiveInventory(static_cast<PClassInventory *>(type), 1, true);
}
if (!giveall)
return;
}
if (giveall || stricmp (name, "ammo") == 0)
{
// Find every unique type of ammo. Give it to the player if
// he doesn't have it already, and set each to its maximum.
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
{
PClassActor *type = PClassActor::AllActorClasses[i];
if (type->ParentClass == RUNTIME_CLASS(AAmmo))
{
PClassInventory *atype = static_cast<PClassInventory *>(type);
AInventory *ammo = player->mo->FindInventory(atype);
if (ammo == NULL)
{
ammo = static_cast<AInventory *>(Spawn (atype));
ammo->AttachToOwner (player->mo);
ammo->Amount = ammo->MaxAmount;
}
else if (ammo->Amount < ammo->MaxAmount)
{
ammo->Amount = ammo->MaxAmount;
}
}
}
if (!giveall)
return;
}
if (giveall || stricmp (name, "armor") == 0)
{
if (gameinfo.gametype != GAME_Hexen)
{
ABasicArmorPickup *armor = Spawn<ABasicArmorPickup> ();
armor->SaveAmount = 100*deh.BlueAC;
armor->SavePercent = gameinfo.Armor2Percent > 0? gameinfo.Armor2Percent : 0.5;
if (!armor->CallTryPickup (player->mo))
{
armor->Destroy ();
}
}
else
{
for (i = 0; i < 4; ++i)
{
AHexenArmor *armor = Spawn<AHexenArmor> ();
armor->health = i;
armor->Amount = 0;
if (!armor->CallTryPickup (player->mo))
{
armor->Destroy ();
}
}
}
if (!giveall)
return;
}
if (giveall || stricmp (name, "keys") == 0)
{
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
{
if (PClassActor::AllActorClasses[i]->IsDescendantOf (RUNTIME_CLASS(AKey)))
{
AKey *key = (AKey *)GetDefaultByType (PClassActor::AllActorClasses[i]);
if (key->KeyNumber != 0)
{
key = static_cast<AKey *>(Spawn(static_cast<PClassActor *>(PClassActor::AllActorClasses[i])));
if (!key->CallTryPickup (player->mo))
{
key->Destroy ();
}
}
}
}
if (!giveall)
return;
}
if (giveall || stricmp (name, "weapons") == 0)
{
AWeapon *savedpending = player->PendingWeapon;
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
{
type = PClassActor::AllActorClasses[i];
// Don't give replaced weapons unless the replacement was done by Dehacked.
if (type != RUNTIME_CLASS(AWeapon) &&
type->IsDescendantOf (RUNTIME_CLASS(AWeapon)) &&
(static_cast<PClassActor *>(type)->GetReplacement() == type ||
static_cast<PClassActor *>(type)->GetReplacement()->IsDescendantOf(RUNTIME_CLASS(ADehackedPickup))))
{
// Give the weapon only if it belongs to the current game or
if (player->weapons.LocateWeapon(static_cast<PClassWeapon*>(type), NULL, NULL))
{
AWeapon *def = (AWeapon*)GetDefaultByType (type);
if (giveall == ALL_YESYES || !(def->WeaponFlags & WIF_CHEATNOTWEAPON))
{
player->mo->GiveInventory(static_cast<PClassInventory *>(type), 1, true);
}
}
}
}
player->PendingWeapon = savedpending;
if (!giveall)
return;
}
if (giveall || stricmp (name, "artifacts") == 0)
{
auto pitype = PClass::FindActor(NAME_PuzzleItem);
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
{
type = PClassActor::AllActorClasses[i];
if (type->IsDescendantOf (RUNTIME_CLASS(AInventory)))
{
AInventory *def = (AInventory*)GetDefaultByType (type);
if (def->Icon.isValid() && def->MaxAmount > 1 &&
!type->IsDescendantOf (pitype) &&
!type->IsDescendantOf (RUNTIME_CLASS(APowerup)) &&
!type->IsDescendantOf (RUNTIME_CLASS(AArmor)))
{
// Do not give replaced items unless using "give everything"
if (giveall == ALL_YESYES || type->GetReplacement() == type)
{
player->mo->GiveInventory(static_cast<PClassInventory *>(type), amount <= 0 ? def->MaxAmount : amount, true);
}
}
}
}
if (!giveall)
return;
}
if (giveall || stricmp (name, "puzzlepieces") == 0)
{
auto pitype = PClass::FindActor(NAME_PuzzleItem);
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
{
type = PClassActor::AllActorClasses[i];
if (type->IsDescendantOf (pitype))
{
AInventory *def = (AInventory*)GetDefaultByType (type);
if (def->Icon.isValid())
{
// Do not give replaced items unless using "give everything"
if (giveall == ALL_YESYES || type->GetReplacement() == type)
{
player->mo->GiveInventory(static_cast<PClassInventory *>(type), amount <= 0 ? def->MaxAmount : amount, true);
}
}
}
}
if (!giveall)
return;
}
if (giveall)
return;
type = PClass::FindActor(name);
if (type == NULL || !type->IsDescendantOf (RUNTIME_CLASS(AInventory)))
{
if (player == &players[consoleplayer])
Printf ("Unknown item \"%s\"\n", name);
}
else
{
player->mo->GiveInventory(static_cast<PClassInventory *>(type), amount, true);
}
return;
}
void cht_Take (player_t *player, const char *name, int amount)
{
bool takeall;
PClassActor *type;
if (player->mo == nullptr) return;
if (player->mo == NULL || player->health <= 0)
IFVIRTUALPTR(player->mo, APlayerPawn, CheatTake)
{
return;
VMValue params[3] = { player->mo, FString(name), amount };
GlobalVMStack.Call(func, params, 3, nullptr, 0);
}
takeall = (stricmp (name, "all") == 0);
if (!takeall && stricmp (name, "health") == 0)
{
if (player->mo->health - amount <= 0
|| player->health - amount <= 0
|| amount == 0)
{
cht_Suicide (player);
if (player == &players[consoleplayer])
C_HideConsole ();
return;
}
if (amount > 0)
{
if (player->mo)
{
player->mo->health -= amount;
player->health = player->mo->health;
}
else
{
player->health -= amount;
}
}
if (!takeall)
return;
}
if (takeall || stricmp (name, "backpack") == 0)
{
// Take away all types of backpacks the player might own.
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
{
PClass *type = PClassActor::AllActorClasses[i];
if (type->IsDescendantOf(PClass::FindClass(NAME_BackpackItem)))
{
AInventory *pack = player->mo->FindInventory(static_cast<PClassActor *>(type));
if (pack)
pack->Destroy();
}
}
if (!takeall)
return;
}
if (takeall || stricmp (name, "ammo") == 0)
{
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
{
PClass *type = PClassActor::AllActorClasses[i];
if (type->ParentClass == RUNTIME_CLASS (AAmmo))
{
AInventory *ammo = player->mo->FindInventory(static_cast<PClassActor *>(type));
if (ammo)
ammo->DepleteOrDestroy();
}
}
if (!takeall)
return;
}
if (takeall || stricmp (name, "armor") == 0)
{
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
{
type = PClassActor::AllActorClasses[i];
if (type->IsDescendantOf (RUNTIME_CLASS (AArmor)))
{
AInventory *armor = player->mo->FindInventory(static_cast<PClassActor *>(type));
if (armor)
armor->DepleteOrDestroy();
}
}
if (!takeall)
return;
}
if (takeall || stricmp (name, "keys") == 0)
{
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
{
type = PClassActor::AllActorClasses[i];
if (type->IsDescendantOf (RUNTIME_CLASS (AKey)))
{
AActor *key = player->mo->FindInventory(static_cast<PClassActor *>(type));
if (key)
key->Destroy ();
}
}
if (!takeall)
return;
}
if (takeall || stricmp (name, "weapons") == 0)
{
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
{
type = PClassActor::AllActorClasses[i];
if (type != RUNTIME_CLASS(AWeapon) &&
type->IsDescendantOf (RUNTIME_CLASS (AWeapon)))
{
AActor *weapon = player->mo->FindInventory(static_cast<PClassActor *>(type));
if (weapon)
weapon->Destroy ();
player->ReadyWeapon = nullptr;
player->PendingWeapon = WP_NOCHANGE;
}
}
if (!takeall)
return;
}
if (takeall || stricmp (name, "artifacts") == 0)
{
auto pitype = PClass::FindActor(NAME_PuzzleItem);
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
{
type = PClassActor::AllActorClasses[i];
if (type->IsDescendantOf (RUNTIME_CLASS (AInventory)))
{
if (!type->IsDescendantOf (pitype) &&
!type->IsDescendantOf (RUNTIME_CLASS (APowerup)) &&
!type->IsDescendantOf (RUNTIME_CLASS (AArmor)) &&
!type->IsDescendantOf (RUNTIME_CLASS (AWeapon)) &&
!type->IsDescendantOf (RUNTIME_CLASS (AKey)))
{
AActor *artifact = player->mo->FindInventory(static_cast<PClassActor *>(type));
if (artifact)
artifact->Destroy ();
}
}
}
if (!takeall)
return;
}
if (takeall || stricmp (name, "puzzlepieces") == 0)
{
auto pitype = PClass::FindActor(NAME_PuzzleItem);
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
{
type = PClassActor::AllActorClasses[i];
if (type->IsDescendantOf (pitype))
{
AActor *puzzlepiece = player->mo->FindInventory(static_cast<PClassActor *>(type));
if (puzzlepiece)
puzzlepiece->Destroy ();
}
}
if (!takeall)
return;
}
if (takeall)
return;
type = PClass::FindActor (name);
if (type == NULL || !type->IsDescendantOf (RUNTIME_CLASS (AInventory)))
{
if (player == &players[consoleplayer])
Printf ("Unknown item \"%s\"\n", name);
}
else
{
player->mo->TakeInventory(type, amount ? amount : 1);
}
return;
}
class DSuicider : public DThinker
@ -1070,6 +654,12 @@ void cht_Suicide (player_t *plyr)
}
}
DEFINE_ACTION_FUNCTION(APlayerPawn, CheatSuicide)
{
PARAM_SELF_PROLOGUE(APlayerPawn);
cht_Suicide(self->player);
return 0;
}
CCMD (mdk)
{