mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-01-31 04:50:48 +00:00
- 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:
parent
75d3f42d4f
commit
14f2c39e58
21 changed files with 559 additions and 461 deletions
|
@ -1326,6 +1326,12 @@ void C_HideConsole ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(_Console, HideConsole)
|
||||||
|
{
|
||||||
|
C_HideConsole();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer)
|
static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer)
|
||||||
{
|
{
|
||||||
int data1 = ev->data1;
|
int data1 = ev->data1;
|
||||||
|
|
|
@ -219,6 +219,7 @@ DEFINE_FIELD_X(DehInfo, DehInfo, ExplosionStyle)
|
||||||
DEFINE_FIELD_X(DehInfo, DehInfo, ExplosionAlpha)
|
DEFINE_FIELD_X(DehInfo, DehInfo, ExplosionAlpha)
|
||||||
DEFINE_FIELD_X(DehInfo, DehInfo, NoAutofreeze)
|
DEFINE_FIELD_X(DehInfo, DehInfo, NoAutofreeze)
|
||||||
DEFINE_FIELD_X(DehInfo, DehInfo, BFGCells)
|
DEFINE_FIELD_X(DehInfo, DehInfo, BFGCells)
|
||||||
|
DEFINE_FIELD_X(DehInfo, DehInfo, BlueAC)
|
||||||
|
|
||||||
// Doom identified pickup items by their sprites. ZDoom prefers to use their
|
// Doom identified pickup items by their sprites. ZDoom prefers to use their
|
||||||
// class type to identify them instead. To support the traditional Doom
|
// class type to identify them instead. To support the traditional Doom
|
||||||
|
|
|
@ -1288,6 +1288,19 @@ bool FWeaponSlots::LocateWeapon (PClassWeapon *type, int *const slot, int *const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FWeaponSlots, LocateWeapon)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(FWeaponSlots);
|
||||||
|
PARAM_CLASS(weap, AWeapon);
|
||||||
|
int slot = 0, index = 0;
|
||||||
|
bool retv = self->LocateWeapon(weap, &slot, &index);
|
||||||
|
if (numret >= 1) ret[0].SetInt(retv);
|
||||||
|
if (numret >= 2) ret[1].SetInt(slot);
|
||||||
|
if (numret >= 3) ret[2].SetInt(index);
|
||||||
|
return MIN(numret, 3);
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// FindMostRecentWeapon
|
// FindMostRecentWeapon
|
||||||
|
|
|
@ -45,6 +45,10 @@
|
||||||
|
|
||||||
gameinfo_t gameinfo;
|
gameinfo_t gameinfo;
|
||||||
|
|
||||||
|
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, backpacktype)
|
||||||
|
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, Armor2Percent)
|
||||||
|
|
||||||
|
|
||||||
const char *GameNames[17] =
|
const char *GameNames[17] =
|
||||||
{
|
{
|
||||||
NULL, "Doom", "Heretic", NULL, "Hexen", NULL, NULL, NULL, "Strife", NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Chex"
|
NULL, "Doom", "Heretic", NULL, "Hexen", NULL, NULL, NULL, "Strife", NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Chex"
|
||||||
|
|
2
src/gi.h
2
src/gi.h
|
@ -148,7 +148,7 @@ struct gameinfo_t
|
||||||
FString translator;
|
FString translator;
|
||||||
DWORD defaultbloodcolor;
|
DWORD defaultbloodcolor;
|
||||||
DWORD defaultbloodparticlecolor;
|
DWORD defaultbloodparticlecolor;
|
||||||
FString backpacktype;
|
FName backpacktype;
|
||||||
FString statusbar;
|
FString statusbar;
|
||||||
FString intermissionMusic;
|
FString intermissionMusic;
|
||||||
int intermissionOrder;
|
int intermissionOrder;
|
||||||
|
|
442
src/m_cheat.cpp
442
src/m_cheat.cpp
|
@ -50,6 +50,7 @@
|
||||||
#include "a_armor.h"
|
#include "a_armor.h"
|
||||||
#include "a_ammo.h"
|
#include "a_ammo.h"
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
|
#include "virtual.h"
|
||||||
|
|
||||||
// [RH] Actually handle the cheat. The cheat code in st_stuff.c now just
|
// [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
|
// 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
|
else
|
||||||
{
|
{
|
||||||
|
player->mo->Revive();
|
||||||
player->playerstate = PST_LIVE;
|
player->playerstate = PST_LIVE;
|
||||||
player->health = player->mo->health = player->mo->GetDefault()->health;
|
player->health = player->mo->health = player->mo->GetDefault()->health;
|
||||||
player->viewheight = ((APlayerPawn *)player->mo->GetDefault())->ViewHeight;
|
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->renderflags &= ~RF_INVISIBLE;
|
||||||
player->mo->Height = player->mo->GetDefault()->Height;
|
player->mo->Height = player->mo->GetDefault()->Height;
|
||||||
player->mo->radius = player->mo->GetDefault()->radius;
|
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->Translation = TRANSLATION(TRANSLATION_Players, BYTE(player-players));
|
||||||
}
|
}
|
||||||
player->mo->DamageType = NAME_None;
|
|
||||||
if (player->ReadyWeapon != nullptr)
|
if (player->ReadyWeapon != nullptr)
|
||||||
{
|
{
|
||||||
P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->GetUpState());
|
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)
|
void cht_Give (player_t *player, const char *name, int amount)
|
||||||
{
|
{
|
||||||
enum { ALL_NO, ALL_YES, ALL_YESYES } giveall;
|
if (player->mo == nullptr) return;
|
||||||
int i;
|
|
||||||
PClassActor *type;
|
|
||||||
|
|
||||||
if (player != &players[consoleplayer])
|
IFVIRTUALPTR(player->mo, APlayerPawn, CheatGive)
|
||||||
Printf ("%s is a cheater: give %s\n", player->userinfo.GetName(), name);
|
|
||||||
|
|
||||||
if (player->mo == NULL || player->health <= 0)
|
|
||||||
{
|
{
|
||||||
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)
|
void cht_Take (player_t *player, const char *name, int amount)
|
||||||
{
|
{
|
||||||
bool takeall;
|
if (player->mo == nullptr) return;
|
||||||
PClassActor *type;
|
|
||||||
|
|
||||||
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
|
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)
|
CCMD (mdk)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1224,22 +1224,6 @@ DEFINE_ACTION_FUNCTION(AActor, CheckInventory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// State jump function
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, CheckArmorType)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
PARAM_NAME (type);
|
|
||||||
PARAM_INT_DEF(amount);
|
|
||||||
|
|
||||||
ABasicArmor *armor = (ABasicArmor *)self->FindInventory(NAME_BasicArmor);
|
|
||||||
|
|
||||||
ACTION_RETURN_BOOL(armor && armor->ArmorType == type && armor->Amount >= amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Parameterized version of A_Explode
|
// Parameterized version of A_Explode
|
||||||
|
|
|
@ -822,11 +822,13 @@ bool AActor::GiveInventory(PClassInventory *type, int amount, bool givecheat)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, Inventory)
|
DEFINE_ACTION_FUNCTION(AActor, GiveInventory)
|
||||||
{
|
{
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
PARAM_OBJECT_NOT_NULL(item, AInventory);
|
PARAM_CLASS(type, AInventory);
|
||||||
ACTION_RETURN_BOOL(self->UseInventory(item));
|
PARAM_INT(amount);
|
||||||
|
PARAM_BOOL_DEF(givecheat);
|
||||||
|
ACTION_RETURN_BOOL(self->GiveInventory(type, amount, givecheat));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -918,6 +920,16 @@ bool AActor::TakeInventory(PClassActor *itemclass, int amount, bool fromdecorate
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, TakeInventory)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
PARAM_OBJECT_NOT_NULL(item, AInventory);
|
||||||
|
PARAM_INT(amount);
|
||||||
|
PARAM_BOOL_DEF(fromdecorate);
|
||||||
|
PARAM_BOOL_DEF(notakeinfinite);
|
||||||
|
self->RemoveInventory(item);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
//
|
//
|
||||||
|
|
|
@ -638,6 +638,14 @@ void player_t::SendPitchLimits() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(_PlayerInfo, GetUserName)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(player_t);
|
||||||
|
ACTION_RETURN_STRING(self->userinfo.GetName());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// APlayerPawn
|
// APlayerPawn
|
||||||
|
|
|
@ -4362,9 +4362,8 @@ ExpEmit FxDotCross::Emit(VMFunctionBuilder *build)
|
||||||
FxTypeCheck::FxTypeCheck(FxExpression *l, FxExpression *r)
|
FxTypeCheck::FxTypeCheck(FxExpression *l, FxExpression *r)
|
||||||
: FxExpression(EFX_TypeCheck, l->ScriptPosition)
|
: FxExpression(EFX_TypeCheck, l->ScriptPosition)
|
||||||
{
|
{
|
||||||
left = new FxTypeCast(l, NewPointer(RUNTIME_CLASS(DObject)), false);
|
left = l;
|
||||||
right = new FxClassTypeCast(NewClassPointer(RUNTIME_CLASS(DObject)), r);
|
right = r;
|
||||||
EmitTail = false;
|
|
||||||
ValueType = TypeBool;
|
ValueType = TypeBool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4389,9 +4388,27 @@ FxTypeCheck::~FxTypeCheck()
|
||||||
FxExpression *FxTypeCheck::Resolve(FCompileContext& ctx)
|
FxExpression *FxTypeCheck::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
|
// This must resolve the cast separately so that it can set the proper type for class descriptors.
|
||||||
RESOLVE(left, ctx);
|
RESOLVE(left, ctx);
|
||||||
RESOLVE(right, ctx);
|
RESOLVE(right, ctx);
|
||||||
ABORT(right && left);
|
ABORT(right && left);
|
||||||
|
|
||||||
|
if (left->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||||
|
{
|
||||||
|
left = new FxClassTypeCast(NewClassPointer(RUNTIME_CLASS(DObject)), left);
|
||||||
|
ClassCheck = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
left = new FxTypeCast(left, NewPointer(RUNTIME_CLASS(DObject)), false);
|
||||||
|
ClassCheck = false;
|
||||||
|
}
|
||||||
|
right = new FxClassTypeCast(NewClassPointer(RUNTIME_CLASS(DObject)), right);
|
||||||
|
|
||||||
|
RESOLVE(left, ctx);
|
||||||
|
RESOLVE(right, ctx);
|
||||||
|
ABORT(right && left);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4408,7 +4425,8 @@ ExpEmit FxTypeCheck::EmitCommon(VMFunctionBuilder *build)
|
||||||
castee.Free(build);
|
castee.Free(build);
|
||||||
casttype.Free(build);
|
casttype.Free(build);
|
||||||
ExpEmit ares(build, REGT_POINTER);
|
ExpEmit ares(build, REGT_POINTER);
|
||||||
build->Emit(casttype.Konst ? OP_DYNCAST_K : OP_DYNCAST_R, ares.RegNum, castee.RegNum, casttype.RegNum);
|
if (!ClassCheck) build->Emit(casttype.Konst ? OP_DYNCAST_K : OP_DYNCAST_R, ares.RegNum, castee.RegNum, casttype.RegNum);
|
||||||
|
else build->Emit(casttype.Konst ? OP_DYNCASTC_K : OP_DYNCASTC_R, ares.RegNum, castee.RegNum, casttype.RegNum);
|
||||||
return ares;
|
return ares;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1086,7 +1086,7 @@ class FxTypeCheck : public FxExpression
|
||||||
public:
|
public:
|
||||||
FxExpression *left;
|
FxExpression *left;
|
||||||
FxExpression *right;
|
FxExpression *right;
|
||||||
bool EmitTail;
|
bool ClassCheck;
|
||||||
|
|
||||||
FxTypeCheck(FxExpression*, FxExpression*);
|
FxTypeCheck(FxExpression*, FxExpression*);
|
||||||
~FxTypeCheck();
|
~FxTypeCheck();
|
||||||
|
|
|
@ -788,6 +788,11 @@ void InitThingdef()
|
||||||
PField *dehf = new PField("deh", dstruct, VARF_Native | VARF_Static, (intptr_t)&deh);
|
PField *dehf = new PField("deh", dstruct, VARF_Native | VARF_Static, (intptr_t)&deh);
|
||||||
GlobalSymbols.AddSymbol(dehf);
|
GlobalSymbols.AddSymbol(dehf);
|
||||||
|
|
||||||
|
// set up a variable for the global gameinfo data
|
||||||
|
PStruct *gistruct = NewNativeStruct("GameInfoStruct", nullptr);
|
||||||
|
PField *gi = new PField("gameinfo", gistruct, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&gameinfo);
|
||||||
|
GlobalSymbols.AddSymbol(gi);
|
||||||
|
|
||||||
// set up a variable for the global players array.
|
// set up a variable for the global players array.
|
||||||
PStruct *pstruct = NewNativeStruct("PlayerInfo", nullptr);
|
PStruct *pstruct = NewNativeStruct("PlayerInfo", nullptr);
|
||||||
pstruct->Size = sizeof(player_t);
|
pstruct->Size = sizeof(player_t);
|
||||||
|
@ -796,6 +801,9 @@ void InitThingdef()
|
||||||
PField *playerf = new PField("players", parray, VARF_Native | VARF_Static, (intptr_t)&players);
|
PField *playerf = new PField("players", parray, VARF_Native | VARF_Static, (intptr_t)&players);
|
||||||
GlobalSymbols.AddSymbol(playerf);
|
GlobalSymbols.AddSymbol(playerf);
|
||||||
|
|
||||||
|
pstruct->AddNativeField("weapons", NewNativeStruct("WeaponSlots", nullptr), myoffsetof(player_t, weapons), VARF_Native);
|
||||||
|
|
||||||
|
|
||||||
parray = NewArray(TypeBool, MAXPLAYERS);
|
parray = NewArray(TypeBool, MAXPLAYERS);
|
||||||
playerf = new PField("playeringame", parray, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&playeringame);
|
playerf = new PField("playeringame", parray, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&playeringame);
|
||||||
GlobalSymbols.AddSymbol(playerf);
|
GlobalSymbols.AddSymbol(playerf);
|
||||||
|
|
|
@ -401,7 +401,7 @@ begin:
|
||||||
OP(MOVEA):
|
OP(MOVEA):
|
||||||
{
|
{
|
||||||
ASSERTA(a); ASSERTA(B);
|
ASSERTA(a); ASSERTA(B);
|
||||||
int b = B;
|
b = B;
|
||||||
reg.a[a] = reg.a[b];
|
reg.a[a] = reg.a[b];
|
||||||
reg.atag[a] = reg.atag[b];
|
reg.atag[a] = reg.atag[b];
|
||||||
NEXTOP;
|
NEXTOP;
|
||||||
|
@ -409,7 +409,7 @@ begin:
|
||||||
OP(MOVEV2):
|
OP(MOVEV2):
|
||||||
{
|
{
|
||||||
ASSERTF(a); ASSERTF(B);
|
ASSERTF(a); ASSERTF(B);
|
||||||
int b = B;
|
b = B;
|
||||||
reg.f[a] = reg.f[b];
|
reg.f[a] = reg.f[b];
|
||||||
reg.f[a + 1] = reg.f[b + 1];
|
reg.f[a + 1] = reg.f[b + 1];
|
||||||
NEXTOP;
|
NEXTOP;
|
||||||
|
@ -417,7 +417,7 @@ begin:
|
||||||
OP(MOVEV3):
|
OP(MOVEV3):
|
||||||
{
|
{
|
||||||
ASSERTF(a); ASSERTF(B);
|
ASSERTF(a); ASSERTF(B);
|
||||||
int b = B;
|
b = B;
|
||||||
reg.f[a] = reg.f[b];
|
reg.f[a] = reg.f[b];
|
||||||
reg.f[a + 1] = reg.f[b + 1];
|
reg.f[a + 1] = reg.f[b + 1];
|
||||||
reg.f[a + 2] = reg.f[b + 2];
|
reg.f[a + 2] = reg.f[b + 2];
|
||||||
|
@ -435,6 +435,18 @@ begin:
|
||||||
reg.a[a] = (reg.a[b] && ((DObject*)(reg.a[b]))->IsKindOf((PClass*)(konsta[C].o))) ? reg.a[b] : nullptr;
|
reg.a[a] = (reg.a[b] && ((DObject*)(reg.a[b]))->IsKindOf((PClass*)(konsta[C].o))) ? reg.a[b] : nullptr;
|
||||||
reg.atag[a] = ATAG_OBJECT;
|
reg.atag[a] = ATAG_OBJECT;
|
||||||
NEXTOP;
|
NEXTOP;
|
||||||
|
OP(DYNCASTC_R) :
|
||||||
|
ASSERTA(a); ASSERTA(B); ASSERTA(C);
|
||||||
|
b = B;
|
||||||
|
reg.a[a] = (reg.a[b] && ((PClass*)(reg.a[b]))->IsDescendantOf((PClass*)(reg.a[C]))) ? reg.a[b] : nullptr;
|
||||||
|
reg.atag[a] = ATAG_OBJECT;
|
||||||
|
NEXTOP;
|
||||||
|
OP(DYNCASTC_K) :
|
||||||
|
ASSERTA(a); ASSERTA(B); ASSERTKA(C);
|
||||||
|
b = B;
|
||||||
|
reg.a[a] = (reg.a[b] && ((PClass*)(reg.a[b]))->IsDescendantOf((PClass*)(konsta[C].o))) ? reg.a[b] : nullptr;
|
||||||
|
reg.atag[a] = ATAG_OBJECT;
|
||||||
|
NEXTOP;
|
||||||
OP(CAST):
|
OP(CAST):
|
||||||
if (C == CAST_I2F)
|
if (C == CAST_I2F)
|
||||||
{
|
{
|
||||||
|
@ -1746,9 +1758,21 @@ static void DoCast(const VMRegisters ®, const VMFrame *f, int a, int b, int c
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CAST_P2S:
|
case CAST_P2S:
|
||||||
|
{
|
||||||
ASSERTS(a); ASSERTA(b);
|
ASSERTS(a); ASSERTA(b);
|
||||||
reg.s[a].Format("%s<%p>", reg.atag[b] == ATAG_OBJECT ? (reg.a[b] == nullptr? "Object" : ((DObject*)reg.a[b])->GetClass()->TypeName.GetChars() ) : "Pointer", reg.a[b]);
|
if (reg.a[b] == nullptr) reg.s[a] = "null";
|
||||||
break;
|
else if (reg.atag[b] == ATAG_OBJECT)
|
||||||
|
{
|
||||||
|
auto op = static_cast<DObject*>(reg.a[b]);
|
||||||
|
if (op->IsKindOf(RUNTIME_CLASS(PClass))) reg.s[a].Format("Class<%s>", static_cast<PClass*>(op)->TypeName.GetChars());
|
||||||
|
else reg.s[a].Format("Object<%p>", ((DObject*)reg.a[b])->GetClass()->TypeName.GetChars());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reg.s[a].Format("%s<%p>", "Pointer", reg.a[b]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case CAST_S2I:
|
case CAST_S2I:
|
||||||
ASSERTD(a); ASSERTS(b);
|
ASSERTD(a); ASSERTS(b);
|
||||||
|
|
|
@ -86,6 +86,8 @@ xx(CAST, cast, CAST, NOP, 0, 0), // xA = xB, conversion specified by C
|
||||||
xx(CASTB, castb, CAST, NOP, 0, 0), // xA = !!xB, type specified by C
|
xx(CASTB, castb, CAST, NOP, 0, 0), // xA = !!xB, type specified by C
|
||||||
xx(DYNCAST_R, dyncast, RPRPRP, NOP, 0, 0), // aA = dyn_cast<aC>(aB);
|
xx(DYNCAST_R, dyncast, RPRPRP, NOP, 0, 0), // aA = dyn_cast<aC>(aB);
|
||||||
xx(DYNCAST_K, dyncast, RPRPKP, NOP, 0, 0), // aA = dyn_cast<aKC>(aB);
|
xx(DYNCAST_K, dyncast, RPRPKP, NOP, 0, 0), // aA = dyn_cast<aKC>(aB);
|
||||||
|
xx(DYNCASTC_R, dyncastc, RPRPRP, NOP, 0, 0), // aA = dyn_cast<aC>(aB); for class types
|
||||||
|
xx(DYNCASTC_K, dyncastc, RPRPKP, NOP, 0, 0), // aA = dyn_cast<aKC>(aB);
|
||||||
|
|
||||||
// Control flow.
|
// Control flow.
|
||||||
xx(TEST, test, RII16, NOP, 0, 0), // if (dA != BC) then pc++
|
xx(TEST, test, RII16, NOP, 0, 0), // if (dA != BC) then pc++
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "zscript/inventory/powerups.txt"
|
#include "zscript/inventory/powerups.txt"
|
||||||
|
|
||||||
#include "zscript/shared/player.txt"
|
#include "zscript/shared/player.txt"
|
||||||
|
#include "zscript/shared/player_cheat.txt"
|
||||||
#include "zscript/shared/morph.txt"
|
#include "zscript/shared/morph.txt"
|
||||||
#include "zscript/shared/botstuff.txt"
|
#include "zscript/shared/botstuff.txt"
|
||||||
#include "zscript/shared/sharedmisc.txt"
|
#include "zscript/shared/sharedmisc.txt"
|
||||||
|
|
|
@ -487,6 +487,8 @@ class Actor : Thinker native
|
||||||
native void AddInventory(Inventory inv);
|
native void AddInventory(Inventory inv);
|
||||||
native void RemoveInventory(Inventory inv);
|
native void RemoveInventory(Inventory inv);
|
||||||
native void ClearInventory();
|
native void ClearInventory();
|
||||||
|
native bool GiveInventory(class<Inventory> type, int amount, bool givecheat = false);
|
||||||
|
native bool TakeInventory(class<Inventory> itemclass, int amount, bool fromdecorate = false, bool notakeinfinite = false);
|
||||||
native Inventory FindInventory(class<Inventory> itemtype, bool subclass = false);
|
native Inventory FindInventory(class<Inventory> itemtype, bool subclass = false);
|
||||||
native Inventory GiveInventoryType(class<Inventory> itemtype);
|
native Inventory GiveInventoryType(class<Inventory> itemtype);
|
||||||
native Inventory DropInventory (Inventory item);
|
native Inventory DropInventory (Inventory item);
|
||||||
|
|
|
@ -106,11 +106,15 @@ extend class Actor
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
// rather pointless these days to do it this way.
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
native bool CheckArmorType(name Type, int amount = 1);
|
bool CheckArmorType(name Type, int amount = 1)
|
||||||
|
{
|
||||||
|
let myarmor = BasicArmor(FindInventory("BasicArmor"));
|
||||||
|
return myarmor != null && myarmor.ArmorType == type && myarmor.Amount >= amount;
|
||||||
|
}
|
||||||
|
|
||||||
action state A_JumpIfArmorType(name Type, statelabel label, int amount = 1)
|
action state A_JumpIfArmorType(name Type, statelabel label, int amount = 1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,11 +32,23 @@ struct TexMan
|
||||||
native static TextureID CheckForTexture(String name, int usetype, int flags = TryAny);
|
native static TextureID CheckForTexture(String name, int usetype, int flags = TryAny);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Screen
|
struct Screen native
|
||||||
{
|
{
|
||||||
native static void DrawHUDTexture(TextureID tex, double x, double y);
|
native static void DrawHUDTexture(TextureID tex, double x, double y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Console native
|
||||||
|
{
|
||||||
|
native static void HideConsole();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GameInfoStruct native
|
||||||
|
{
|
||||||
|
// will be extended as needed.
|
||||||
|
native Name backpacktype;
|
||||||
|
native double Armor2Percent;
|
||||||
|
}
|
||||||
|
|
||||||
class Object native
|
class Object native
|
||||||
{
|
{
|
||||||
native bool bDestroyed;
|
native bool bDestroyed;
|
||||||
|
@ -200,6 +212,7 @@ struct DehInfo native
|
||||||
native double ExplosionAlpha;
|
native double ExplosionAlpha;
|
||||||
native int NoAutofreeze;
|
native int NoAutofreeze;
|
||||||
native int BFGCells;
|
native int BFGCells;
|
||||||
|
native int BlueAC;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct State native
|
struct State native
|
||||||
|
|
|
@ -125,3 +125,7 @@ class WeaponPiece : Inventory native
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct WeaponSlots native
|
||||||
|
{
|
||||||
|
native bool, int, int LocateWeapon(class<Weapon> weap);
|
||||||
|
}
|
|
@ -258,11 +258,12 @@ struct PlayerInfo native // this is what internally is known as player_t
|
||||||
native Actor ConversationPC;
|
native Actor ConversationPC;
|
||||||
native double ConversationNPCAngle;
|
native double ConversationNPCAngle;
|
||||||
native bool ConversationFaceTalker;
|
native bool ConversationFaceTalker;
|
||||||
|
//native WeaponSlots weapons; <- defined internally
|
||||||
|
|
||||||
/* these are not doable yet
|
/* these are not doable yet
|
||||||
ticcmd_t cmd;
|
ticcmd_t cmd;
|
||||||
usercmd_t original_cmd;
|
usercmd_t original_cmd;
|
||||||
userinfo_t userinfo; // [RH] who is this?
|
userinfo_t userinfo;
|
||||||
FWeaponSlots weapons;
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -276,5 +277,6 @@ FWeaponSlots weapons;
|
||||||
native PSprite FindPSprite(int id);
|
native PSprite FindPSprite(int id);
|
||||||
native void SetLogNumber (int text);
|
native void SetLogNumber (int text);
|
||||||
native void SetLogText (String text);
|
native void SetLogText (String text);
|
||||||
|
native String GetUserName();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
402
wadsrc/static/zscript/shared/player_cheat.txt
Normal file
402
wadsrc/static/zscript/shared/player_cheat.txt
Normal file
|
@ -0,0 +1,402 @@
|
||||||
|
/*
|
||||||
|
** player_cheat.txt
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 1999-2016 Randy Heit
|
||||||
|
** Copyright 2006-2017 Christoph Oelckers
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
extend class PlayerPawn
|
||||||
|
{
|
||||||
|
enum EAll
|
||||||
|
{
|
||||||
|
ALL_NO,
|
||||||
|
ALL_YES,
|
||||||
|
ALL_YESYES
|
||||||
|
}
|
||||||
|
|
||||||
|
native void CheatSuicide();
|
||||||
|
|
||||||
|
virtual void CheatGive (String name, int amount)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Class<Inventory> type;
|
||||||
|
let player = self.player;
|
||||||
|
|
||||||
|
if (PlayerNumber() != consoleplayer)
|
||||||
|
A_Log(format ("%s is a cheater: give %s\n", player.GetUserName(), name));
|
||||||
|
|
||||||
|
if (player.mo == NULL || player.health <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int giveall = ALL_NO;
|
||||||
|
if (name ~== "all")
|
||||||
|
{
|
||||||
|
giveall = ALL_YES;
|
||||||
|
}
|
||||||
|
else if (name ~== "everything")
|
||||||
|
{
|
||||||
|
giveall = ALL_YESYES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name ~== "health")
|
||||||
|
{
|
||||||
|
if (amount > 0)
|
||||||
|
{
|
||||||
|
health += amount;
|
||||||
|
player.health = health;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
player.health = health = GetMaxHealth();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (giveall || name ~== "backpack")
|
||||||
|
{
|
||||||
|
// Select the correct type of backpack based on the game
|
||||||
|
type = (class<Inventory>)(gameinfo.backpacktype);
|
||||||
|
if (type != NULL)
|
||||||
|
{
|
||||||
|
GiveInventory(type, 1, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!giveall)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (giveall || name ~== "ammo")
|
||||||
|
{
|
||||||
|
// 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 (i = 0; i < AllActorClasses.Size(); ++i)
|
||||||
|
{
|
||||||
|
type = (class<Inventory>)(AllActorClasses[i]);
|
||||||
|
|
||||||
|
if (type != null && type.GetParentClass() == "Ammo")
|
||||||
|
{
|
||||||
|
let ammoitem = FindInventory(type);
|
||||||
|
if (ammoitem == NULL)
|
||||||
|
{
|
||||||
|
ammoitem = Inventory(Spawn (type));
|
||||||
|
ammoitem.AttachToOwner (self);
|
||||||
|
ammoitem.Amount = ammoitem.MaxAmount;
|
||||||
|
}
|
||||||
|
else if (ammoitem.Amount < ammoitem.MaxAmount)
|
||||||
|
{
|
||||||
|
ammoitem.Amount = ammoitem.MaxAmount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!giveall)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (giveall || name ~== "armor")
|
||||||
|
{
|
||||||
|
if (GameType() != GAME_Hexen)
|
||||||
|
{
|
||||||
|
let armoritem = BasicArmorPickup(Spawn("BasicArmorPickup"));
|
||||||
|
armoritem.SaveAmount = 100*deh.BlueAC;
|
||||||
|
armoritem.SavePercent = gameinfo.Armor2Percent > 0? gameinfo.Armor2Percent : 0.5;
|
||||||
|
if (!armoritem.CallTryPickup (self))
|
||||||
|
{
|
||||||
|
armoritem.Destroy ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
let armoritem = Inventory(Spawn("HexenArmor"));
|
||||||
|
armoritem.health = i;
|
||||||
|
armoritem.Amount = 0;
|
||||||
|
if (!armoritem.CallTryPickup (self))
|
||||||
|
{
|
||||||
|
armoritem.Destroy ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!giveall)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (giveall || name ~== "keys")
|
||||||
|
{
|
||||||
|
for (int i = 0; i < AllActorClasses.Size(); ++i)
|
||||||
|
{
|
||||||
|
if (AllActorClasses[i] is "Key")
|
||||||
|
{
|
||||||
|
readonly<Key> keyitem = GetDefaultByType ((class<Key>)(AllActorClasses[i]));
|
||||||
|
if (keyitem.KeyNumber != 0)
|
||||||
|
{
|
||||||
|
let item = Inventory(Spawn(AllActorClasses[i]));
|
||||||
|
if (!item.CallTryPickup (self))
|
||||||
|
{
|
||||||
|
item.Destroy ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!giveall)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (giveall || name ~== "weapons")
|
||||||
|
{
|
||||||
|
let savedpending = player.PendingWeapon;
|
||||||
|
for (i = 0; i < AllActorClasses.Size(); ++i)
|
||||||
|
{
|
||||||
|
let type = (class<Weapon>)(AllActorClasses[i]);
|
||||||
|
if (type != null && type != "Weapon")
|
||||||
|
{
|
||||||
|
// Don't give replaced weapons unless the replacement was done by Dehacked.
|
||||||
|
let rep = GetReplacement(type);
|
||||||
|
if (rep == type || rep is "DehackedPickup")
|
||||||
|
{
|
||||||
|
// Give the weapon only if it is set in a weapon slot.
|
||||||
|
if (player.weapons.LocateWeapon(type))
|
||||||
|
{
|
||||||
|
readonly<Weapon> def = GetDefaultByType (type);
|
||||||
|
if (giveall == ALL_YESYES || !def.bCheatNotWeapon)
|
||||||
|
{
|
||||||
|
GiveInventory(type, 1, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
player.PendingWeapon = savedpending;
|
||||||
|
|
||||||
|
if (!giveall)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (giveall || name ~== "artifacts")
|
||||||
|
{
|
||||||
|
for (i = 0; i < AllActorClasses.Size(); ++i)
|
||||||
|
{
|
||||||
|
type = (class<Inventory>)(AllActorClasses[i]);
|
||||||
|
if (type!= null)
|
||||||
|
{
|
||||||
|
let def = GetDefaultByType (type);
|
||||||
|
if (def.Icon.isValid() && def.MaxAmount > 1 &&
|
||||||
|
!(type is "PuzzleItem") && !(type is "Powerup") && !(type is "Ammo") && !(type is "Armor"))
|
||||||
|
{
|
||||||
|
// Do not give replaced items unless using "give everything"
|
||||||
|
if (giveall == ALL_YESYES || GetReplacement(type) == type)
|
||||||
|
{
|
||||||
|
GiveInventory(type, amount <= 0 ? def.MaxAmount : amount, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!giveall)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (giveall || name ~== "puzzlepieces")
|
||||||
|
{
|
||||||
|
for (i = 0; i < AllActorClasses.Size(); ++i)
|
||||||
|
{
|
||||||
|
let type = (class<PuzzleItem>)(AllActorClasses[i]);
|
||||||
|
if (type != null)
|
||||||
|
{
|
||||||
|
let def = GetDefaultByType (type);
|
||||||
|
if (def.Icon.isValid())
|
||||||
|
{
|
||||||
|
// Do not give replaced items unless using "give everything"
|
||||||
|
if (giveall == ALL_YESYES || GetReplacement(type) == type)
|
||||||
|
{
|
||||||
|
GiveInventory(type, amount <= 0 ? def.MaxAmount : amount, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!giveall)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (giveall)
|
||||||
|
return;
|
||||||
|
|
||||||
|
type = name;
|
||||||
|
if (type == NULL)
|
||||||
|
{
|
||||||
|
if (PlayerNumber() == consoleplayer)
|
||||||
|
A_Log(format("Unknown item \"%s\"\n", name));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GiveInventory(type, amount, true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatTakeType(class<Inventory> deletetype)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < AllActorClasses.Size(); ++i)
|
||||||
|
{
|
||||||
|
let type = (class<Inventory>)(AllActorClasses[i]);
|
||||||
|
|
||||||
|
if (type != null && type is deletetype)
|
||||||
|
{
|
||||||
|
let pack = FindInventory(type);
|
||||||
|
if (pack) pack.Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void CheatTake (String name, int amount)
|
||||||
|
{
|
||||||
|
bool takeall;
|
||||||
|
Class<Inventory> type;
|
||||||
|
let player = self.player;
|
||||||
|
|
||||||
|
|
||||||
|
if (player.mo == NULL || player.health <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
takeall = name ~== "all";
|
||||||
|
|
||||||
|
if (!takeall && name ~== "health")
|
||||||
|
{
|
||||||
|
if (player.mo.health - amount <= 0
|
||||||
|
|| player.health - amount <= 0
|
||||||
|
|| amount == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
CheatSuicide ();
|
||||||
|
|
||||||
|
if (PlayerNumber() == consoleplayer)
|
||||||
|
Console.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 || name ~== "backpack")
|
||||||
|
{
|
||||||
|
CheatTakeType("BackpackItem");
|
||||||
|
if (!takeall)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (takeall || name ~== "ammo")
|
||||||
|
{
|
||||||
|
CheatTakeType("Ammo");
|
||||||
|
if (!takeall)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (takeall || name ~== "armor")
|
||||||
|
{
|
||||||
|
CheatTakeType("Armor");
|
||||||
|
if (!takeall)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (takeall || name ~== "keys")
|
||||||
|
{
|
||||||
|
CheatTakeType("Key");
|
||||||
|
if (!takeall)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (takeall || name ~== "weapons")
|
||||||
|
{
|
||||||
|
CheatTakeType("Weapon");
|
||||||
|
CheatTakeType("WeaponHolder");
|
||||||
|
player.ReadyWeapon = null;
|
||||||
|
player.PendingWeapon = WP_NOCHANGE;
|
||||||
|
|
||||||
|
if (!takeall)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (takeall || name ~== "artifacts")
|
||||||
|
{
|
||||||
|
for (int i = 0; i < AllActorClasses.Size(); ++i)
|
||||||
|
{
|
||||||
|
type = (class<Inventory>)(AllActorClasses[i]);
|
||||||
|
if (type!= null && !(type is "PuzzleItem") && !(type is "Powerup") && !(type is "Ammo") && !(type is "Armor"))
|
||||||
|
{
|
||||||
|
let pack = FindInventory(type);
|
||||||
|
if (pack) pack.Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!takeall)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (takeall || name ~== "puzzlepieces")
|
||||||
|
{
|
||||||
|
CheatTakeType("PuzzleItem");
|
||||||
|
if (!takeall)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (takeall)
|
||||||
|
return;
|
||||||
|
|
||||||
|
type = name;
|
||||||
|
if (type == NULL)
|
||||||
|
{
|
||||||
|
if (PlayerNumber() == consoleplayer)
|
||||||
|
A_Log(format("Unknown item \"%s\"\n", name));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TakeInventory(type, max(amount, 1));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue