mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2025-01-18 22:51:39 +00:00
- scriptified Strife's coins.
- added a String class to allow attaching methods to the builtin string type. This works by checking if the left side of the member accessor is a string and just replacing the tyoe in this one place, all the rest is automatic.
This commit is contained in:
parent
d2ce78fae7
commit
9064a5b0ac
17 changed files with 221 additions and 33 deletions
|
@ -89,6 +89,7 @@ PStateLabel *TypeStateLabel;
|
|||
PStruct *TypeVector2;
|
||||
PStruct *TypeVector3;
|
||||
PStruct *TypeColorStruct;
|
||||
PStruct *TypeStringStruct;
|
||||
PPointer *TypeNullPtr;
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
@ -587,7 +588,8 @@ void PType::StaticInit()
|
|||
TypeTable.AddType(TypeSpriteID = new PSpriteID);
|
||||
TypeTable.AddType(TypeTextureID = new PTextureID);
|
||||
|
||||
TypeColorStruct = new PStruct("@ColorStruct", nullptr); //This name is intentionally obfuscated so that it cannot be used explicitly. The point of this type is to gain access to the single channels of a color value.
|
||||
TypeColorStruct = NewStruct("@ColorStruct", nullptr); //This name is intentionally obfuscated so that it cannot be used explicitly. The point of this type is to gain access to the single channels of a color value.
|
||||
TypeStringStruct = NewNativeStruct(NAME_String, nullptr);
|
||||
#ifdef __BIG_ENDIAN__
|
||||
TypeColorStruct->AddField(NAME_a, TypeUInt8);
|
||||
TypeColorStruct->AddField(NAME_r, TypeUInt8);
|
||||
|
|
|
@ -945,6 +945,7 @@ extern PSpriteID *TypeSpriteID;
|
|||
extern PStruct *TypeVector2;
|
||||
extern PStruct *TypeVector3;
|
||||
extern PStruct *TypeColorStruct;
|
||||
extern PStruct *TypeStringStruct;
|
||||
extern PStatePointer *TypeState;
|
||||
extern PStateLabel *TypeStateLabel;
|
||||
extern PPointer *TypeNullPtr;
|
||||
|
|
|
@ -16,6 +16,7 @@ public:
|
|||
virtual bool HandlePickup (AInventory *item);
|
||||
virtual AInventory *CreateCopy (AActor *other);
|
||||
virtual AInventory *CreateTossable ();
|
||||
|
||||
|
||||
virtual void Serialize(FSerializer &arc);
|
||||
virtual void OwnerDied ();
|
||||
|
|
|
@ -919,6 +919,27 @@ AInventory *AInventory::CreateTossable ()
|
|||
return copy;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AInventory, CreateTossable)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
ACTION_RETURN_OBJECT(self->CreateTossable());
|
||||
}
|
||||
|
||||
AInventory *AInventory::CallCreateTossable()
|
||||
{
|
||||
IFVIRTUAL(AInventory, CreateTossable)
|
||||
{
|
||||
VMValue params[1] = { (DObject*)this };
|
||||
VMReturn ret;
|
||||
VMFrameStack stack;
|
||||
AInventory *retval;
|
||||
ret.PointerAt((void**)&retval);
|
||||
stack.Call(func, params, 1, &ret, 1, nullptr);
|
||||
return retval;
|
||||
}
|
||||
else return CreateTossable();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: BecomeItem
|
||||
|
@ -946,6 +967,13 @@ void AInventory::BecomeItem ()
|
|||
SetState (FindState("Held"));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AInventory, BecomeItem)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
self->BecomeItem();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: BecomePickup
|
||||
|
@ -973,6 +1001,13 @@ void AInventory::BecomePickup ()
|
|||
SetState (SpawnState);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AInventory, BecomePickup)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
self->BecomePickup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: AbsorbDamage
|
||||
|
|
|
@ -196,13 +196,14 @@ public:
|
|||
|
||||
FSoundIDNoInit PickupSound;
|
||||
|
||||
virtual void BecomeItem ();
|
||||
virtual void BecomePickup ();
|
||||
void BecomeItem ();
|
||||
void BecomePickup ();
|
||||
virtual void AttachToOwner (AActor *other);
|
||||
virtual void DetachFromOwner ();
|
||||
virtual AInventory *CreateCopy (AActor *other);
|
||||
AInventory *CallCreateCopy(AActor *other);
|
||||
virtual AInventory *CreateTossable ();
|
||||
AInventory *CallCreateTossable();
|
||||
virtual bool GoAway ();
|
||||
virtual void GoAwayAndDie ();
|
||||
virtual bool HandlePickup (AInventory *item);
|
||||
|
|
|
@ -424,7 +424,7 @@ AInventory *AWeapon::CreateTossable ()
|
|||
(((AWeapon*)SisterWeapon->GetDefault())->AmmoGive1 > 0 ||
|
||||
((AWeapon*)SisterWeapon->GetDefault())->AmmoGive2 > 0))
|
||||
{
|
||||
return SisterWeapon->CreateTossable ();
|
||||
return SisterWeapon->CallCreateTossable ();
|
||||
}
|
||||
AWeapon *copy = static_cast<AWeapon *> (Super::CreateTossable ());
|
||||
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
// Coin ---------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
IMPLEMENT_CLASS(ACoin, false, false)
|
||||
|
||||
/*
|
||||
const char *ACoin::PickupMessage ()
|
||||
{
|
||||
if (Amount == 1)
|
||||
|
@ -23,7 +23,6 @@ const char *ACoin::PickupMessage ()
|
|||
return msg;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
bool ACoin::HandlePickup (AInventory *item)
|
||||
{
|
||||
|
@ -108,3 +107,4 @@ AInventory *ACoin::CreateTossable ()
|
|||
}
|
||||
return tossed;
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -13,16 +13,6 @@ public:
|
|||
bool Use (bool pickup);
|
||||
};
|
||||
|
||||
class ACoin : public AInventory
|
||||
{
|
||||
DECLARE_CLASS (ACoin, AInventory)
|
||||
public:
|
||||
//const char *PickupMessage ();
|
||||
bool HandlePickup (AInventory *item);
|
||||
AInventory *CreateTossable ();
|
||||
AInventory *CreateCopy (AActor *other);
|
||||
};
|
||||
|
||||
class ADummyStrifeItem : public AInventory
|
||||
{
|
||||
DECLARE_CLASS (ADummyStrifeItem, AInventory)
|
||||
|
|
|
@ -82,7 +82,7 @@ bool AHealthTraining::TryPickup (AActor *&toucher)
|
|||
if (Super::TryPickup (toucher))
|
||||
{
|
||||
toucher->GiveInventoryType (PClass::FindActor("GunTraining"));
|
||||
AInventory *coin = Spawn<ACoin> ();
|
||||
AInventory *coin = (AInventory*)Spawn("Coin");
|
||||
if (coin != NULL)
|
||||
{
|
||||
coin->Amount = toucher->player->mo->accuracy*5 + 300;
|
||||
|
|
|
@ -1053,18 +1053,22 @@ public:
|
|||
|
||||
if (ShowGold)
|
||||
{
|
||||
AInventory *coin = cp->ConversationPC->FindInventory (RUNTIME_CLASS(ACoin));
|
||||
char goldstr[32];
|
||||
auto cointype = PClass::FindActor("Coin");
|
||||
if (cointype)
|
||||
{
|
||||
AInventory *coin = cp->ConversationPC->FindInventory(cointype);
|
||||
char goldstr[32];
|
||||
|
||||
mysnprintf (goldstr, countof(goldstr), "%d", coin != NULL ? coin->Amount : 0);
|
||||
screen->DrawText (SmallFont, CR_GRAY, 21, 191, goldstr, DTA_320x200, true,
|
||||
DTA_FillColor, 0, DTA_AlphaF, HR_SHADOW, TAG_DONE);
|
||||
screen->DrawTexture (TexMan(((AInventory *)GetDefaultByType (RUNTIME_CLASS(ACoin)))->Icon),
|
||||
3, 190, DTA_320x200, true,
|
||||
DTA_FillColor, 0, DTA_AlphaF, HR_SHADOW, TAG_DONE);
|
||||
screen->DrawText (SmallFont, CR_GRAY, 20, 190, goldstr, DTA_320x200, true, TAG_DONE);
|
||||
screen->DrawTexture (TexMan(((AInventory *)GetDefaultByType (RUNTIME_CLASS(ACoin)))->Icon),
|
||||
2, 189, DTA_320x200, true, TAG_DONE);
|
||||
mysnprintf(goldstr, countof(goldstr), "%d", coin != NULL ? coin->Amount : 0);
|
||||
screen->DrawText(SmallFont, CR_GRAY, 21, 191, goldstr, DTA_320x200, true,
|
||||
DTA_FillColor, 0, DTA_AlphaF, HR_SHADOW, TAG_DONE);
|
||||
screen->DrawTexture(TexMan(((AInventory *)GetDefaultByType(cointype))->Icon),
|
||||
3, 190, DTA_320x200, true,
|
||||
DTA_FillColor, 0, DTA_AlphaF, HR_SHADOW, TAG_DONE);
|
||||
screen->DrawText(SmallFont, CR_GRAY, 20, 190, goldstr, DTA_320x200, true, TAG_DONE);
|
||||
screen->DrawTexture(TexMan(((AInventory *)GetDefaultByType(cointype))->Icon),
|
||||
2, 189, DTA_320x200, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
y = mYpos;
|
||||
|
|
|
@ -1002,7 +1002,7 @@ bool AActor::UseInventory(AInventory *item)
|
|||
|
||||
AInventory *AActor::DropInventory (AInventory *item)
|
||||
{
|
||||
AInventory *drop = item->CreateTossable ();
|
||||
AInventory *drop = item->CallCreateTossable ();
|
||||
|
||||
if (drop == NULL)
|
||||
{
|
||||
|
|
|
@ -5766,9 +5766,11 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
|
|||
|
||||
// allow accessing the color channels by mapping the type to a matching struct which defines them.
|
||||
if (Object->ValueType == TypeColor)
|
||||
{
|
||||
Object->ValueType = TypeColorStruct;
|
||||
}
|
||||
|
||||
if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
|
||||
else if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
|
||||
{
|
||||
auto ptype = static_cast<PPointer *>(Object->ValueType)->PointedType;
|
||||
if (ptype->IsKindOf(RUNTIME_CLASS(PStruct)))
|
||||
|
@ -7306,6 +7308,12 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
}
|
||||
}
|
||||
|
||||
if (Self->ValueType == TypeString)
|
||||
{
|
||||
// same for String methods. It also uses a hidden struct type to define them.
|
||||
Self->ValueType = TypeStringStruct;
|
||||
}
|
||||
|
||||
if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
|
||||
{
|
||||
auto ptype = static_cast<PPointer *>(Self->ValueType)->PointedType;
|
||||
|
@ -7876,8 +7884,16 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
assert(Self != nullptr);
|
||||
selfemit = Self->Emit(build);
|
||||
assert(selfemit.RegType == REGT_POINTER);
|
||||
build->Emit(OP_PARAM, 0, selfemit.RegType, selfemit.RegNum);
|
||||
assert((selfemit.RegType == REGT_POINTER) || (selfemit.Fixed && selfemit.Target));
|
||||
if (selfemit.Fixed && selfemit.Target)
|
||||
{
|
||||
// Address of a local variable.
|
||||
build->Emit(OP_PARAM, 0, selfemit.RegType | REGT_ADDROF, selfemit.RegNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
build->Emit(OP_PARAM, 0, selfemit.RegType, selfemit.RegNum);
|
||||
}
|
||||
count += 1;
|
||||
if (Function->Variants[0].Flags & VARF_Action)
|
||||
{
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
#include "p_maputl.h"
|
||||
#include "gi.h"
|
||||
#include "p_terrain.h"
|
||||
#include "gstrings.h"
|
||||
#include "zstring.h"
|
||||
|
||||
static TArray<FPropertyInfo*> properties;
|
||||
static TArray<AFuncDesc> AFTable;
|
||||
|
@ -826,3 +828,19 @@ DEFINE_ACTION_FUNCTION(DObject, GameType)
|
|||
PARAM_PROLOGUE;
|
||||
ACTION_RETURN_INT(gameinfo.gametype);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FStringTable, Localize)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_STRING(label);
|
||||
ACTION_RETURN_STRING(GStrings(label));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FString, Replace)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FString);
|
||||
PARAM_STRING(s1);
|
||||
PARAM_STRING(s2);
|
||||
self->Substitute(*s1, *s2);
|
||||
return 0;
|
||||
}
|
|
@ -289,6 +289,10 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
a &= CMP_CHECK | CMP_APPROX;
|
||||
cmp = true;
|
||||
}
|
||||
if (code[i].op == OP_PARAM && code[i].b & REGT_ADDROF)
|
||||
{
|
||||
name = "parama";
|
||||
}
|
||||
if (cmp)
|
||||
{ // Comparison instruction. Modify name for inverted test.
|
||||
if (!(a & CMP_CHECK))
|
||||
|
|
|
@ -98,6 +98,11 @@ struct LevelLocals native
|
|||
// level_info_t *info cannot be done yet.
|
||||
}
|
||||
|
||||
struct StringTable native
|
||||
{
|
||||
native static String Localize(String val);
|
||||
}
|
||||
|
||||
// a few values of this need to be readable by the play code.
|
||||
// Most are handled at load time and are omitted here.
|
||||
struct DehInfo native
|
||||
|
@ -275,3 +280,9 @@ enum EPickStart
|
|||
PPS_FORCERANDOM = 1,
|
||||
PPS_NOBLOCKINGCHECK = 2,
|
||||
}
|
||||
|
||||
// Although String is a builtin type, this is a convenient way to attach methods to it.
|
||||
struct String native
|
||||
{
|
||||
native void Replace(String pattern, String replacement);
|
||||
}
|
||||
|
|
|
@ -29,10 +29,13 @@ class Inventory : Actor native
|
|||
virtual native color GetBlend ();
|
||||
virtual native bool HandlePickup(Inventory item);
|
||||
virtual native Inventory CreateCopy(Actor other);
|
||||
virtual native Inventory CreateTossable();
|
||||
virtual native bool SpecialDropAction (Actor dropper);
|
||||
virtual native String PickupMessage();
|
||||
|
||||
native void GoAwayAndDie();
|
||||
native void BecomeItem();
|
||||
native void BecomePickup();
|
||||
|
||||
// These are regular functions for the item itself.
|
||||
private native void A_RestoreSpecialDoomThing();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
// Coin ---------------------------------------------------------------------
|
||||
|
||||
class Coin : Inventory native
|
||||
class Coin : Inventory
|
||||
{
|
||||
Default
|
||||
{
|
||||
|
@ -20,6 +20,108 @@ class Coin : Inventory native
|
|||
COIN A -1;
|
||||
Stop;
|
||||
}
|
||||
|
||||
// Coin ---------------------------------------------------------------------
|
||||
|
||||
override String PickupMessage ()
|
||||
{
|
||||
if (Amount == 1)
|
||||
{
|
||||
return Super.PickupMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
String msg = StringTable.Localize("TXT_XGOLD");
|
||||
msg.Replace("%d", "" .. Amount);
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
override bool HandlePickup (Inventory item)
|
||||
{
|
||||
if (item is "Coin")
|
||||
{
|
||||
if (Amount < MaxAmount)
|
||||
{
|
||||
if (MaxAmount - Amount < item.Amount)
|
||||
{
|
||||
Amount = MaxAmount;
|
||||
}
|
||||
else
|
||||
{
|
||||
Amount += item.Amount;
|
||||
}
|
||||
item.bPickupGood = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
override Inventory CreateCopy (Actor other)
|
||||
{
|
||||
if (GetClass() == "Coin")
|
||||
{
|
||||
return Super.CreateCopy (other);
|
||||
}
|
||||
Inventory copy = Inventory(Spawn("Coin"));
|
||||
copy.Amount = Amount;
|
||||
copy.BecomeItem ();
|
||||
GoAwayAndDie ();
|
||||
return copy;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// ACoin :: CreateTossable
|
||||
//
|
||||
// Gold drops in increments of 50 if you have that much, less if you don't.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override Inventory CreateTossable ()
|
||||
{
|
||||
Coin tossed;
|
||||
|
||||
if (bUndroppable || Owner == NULL || Amount <= 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (Amount >= 50)
|
||||
{
|
||||
Amount -= 50;
|
||||
tossed = Coin(Spawn("Gold50"));
|
||||
}
|
||||
else if (Amount >= 25)
|
||||
{
|
||||
Amount -= 25;
|
||||
tossed = Coin(Spawn("Gold25"));
|
||||
}
|
||||
else if (Amount >= 10)
|
||||
{
|
||||
Amount -= 10;
|
||||
tossed = Coin(Spawn("Gold10"));
|
||||
}
|
||||
else if (Amount > 1 || bKeepDepleted)
|
||||
{
|
||||
Amount -= 1;
|
||||
tossed = Coin(Spawn("Coin"));
|
||||
}
|
||||
else // Amount == 1 && !(ItemFlags & IF_KEEPDEPLETED)
|
||||
{
|
||||
BecomePickup ();
|
||||
tossed = self;
|
||||
}
|
||||
tossed.bSpecial = false;
|
||||
tossed.bSolid = false;
|
||||
tossed.DropTime = 30;
|
||||
if (tossed != self && Amount <= 0)
|
||||
{
|
||||
Destroy ();
|
||||
}
|
||||
return tossed;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue