mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-05-05 16:02:09 +00:00
- eliminated the native PowerupGiver class.
- scriptified the respawn invulnerability code into a virtual OnRespawn function for PlayerPawn so that custom effects can be implemented.
This commit is contained in:
parent
98f9219334
commit
232b64d332
17 changed files with 138 additions and 130 deletions
|
@ -456,9 +456,7 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld, bool s
|
||||||
auto def = GetDefaultByType(p);
|
auto def = GetDefaultByType(p);
|
||||||
if (def != nullptr)
|
if (def != nullptr)
|
||||||
{
|
{
|
||||||
def->Class = p;
|
|
||||||
def->DObject::PointerSubstitution(old, notOld);
|
def->DObject::PointerSubstitution(old, notOld);
|
||||||
def->Class = nullptr; // reset pointer. Defaults should not have a valid class pointer.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,7 +208,6 @@ enum EObjectFlags
|
||||||
OF_SerialSuccess = 1 << 9, // For debugging Serialize() calls
|
OF_SerialSuccess = 1 << 9, // For debugging Serialize() calls
|
||||||
OF_Sentinel = 1 << 10, // Object is serving as the sentinel in a ring list
|
OF_Sentinel = 1 << 10, // Object is serving as the sentinel in a ring list
|
||||||
OF_Transient = 1 << 11, // Object should not be archived (references to it will be nulled on disk)
|
OF_Transient = 1 << 11, // Object should not be archived (references to it will be nulled on disk)
|
||||||
OF_SuperCall = 1 << 12, // A super call from the VM is about to be performed
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T> class TObjPtr;
|
template<class T> class TObjPtr;
|
||||||
|
@ -453,6 +452,8 @@ public:
|
||||||
|
|
||||||
void *ScriptVar(FName field, PType *type);
|
void *ScriptVar(FName field, PType *type);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DObject ();
|
DObject ();
|
||||||
DObject (PClass *inClass);
|
DObject (PClass *inClass);
|
||||||
|
|
|
@ -1782,6 +1782,18 @@ PClassPointer::PClassPointer(PClass *restrict)
|
||||||
else mDescriptiveName = "ClassPointer";
|
else mDescriptiveName = "ClassPointer";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PClassPointer - isCompatible
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool PClassPointer::isCompatible(PType *type)
|
||||||
|
{
|
||||||
|
auto other = dyn_cast<PClassPointer>(type);
|
||||||
|
return (other != nullptr && other->ClassRestriction->IsDescendantOf(ClassRestriction));
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PClassPointer :: IsMatch
|
// PClassPointer :: IsMatch
|
||||||
|
@ -3333,6 +3345,20 @@ void PClass::InitializeDefaults()
|
||||||
{
|
{
|
||||||
assert(Defaults == NULL);
|
assert(Defaults == NULL);
|
||||||
Defaults = (BYTE *)M_Malloc(Size);
|
Defaults = (BYTE *)M_Malloc(Size);
|
||||||
|
|
||||||
|
// run the constructor on the defaults to set the vtbl pointer which is needed to run class-aware functions on them.
|
||||||
|
// bSerialOverride prevents linking into the thinker chains.
|
||||||
|
auto s = DThinker::bSerialOverride;
|
||||||
|
DThinker::bSerialOverride = true;
|
||||||
|
ConstructNative(Defaults);
|
||||||
|
DThinker::bSerialOverride = s;
|
||||||
|
// We must unlink the defaults from the class list because it's just a static block of data to the engine.
|
||||||
|
DObject *optr = (DObject*)Defaults;
|
||||||
|
GC::Root = optr->ObjNext;
|
||||||
|
optr->ObjNext = nullptr;
|
||||||
|
optr->SetClass(this);
|
||||||
|
|
||||||
|
|
||||||
if (ParentClass->Defaults != NULL)
|
if (ParentClass->Defaults != NULL)
|
||||||
{
|
{
|
||||||
memcpy(Defaults, ParentClass->Defaults, ParentClass->Size);
|
memcpy(Defaults, ParentClass->Defaults, ParentClass->Size);
|
||||||
|
|
|
@ -599,6 +599,7 @@ public:
|
||||||
|
|
||||||
// this is only here to block PPointer's implementation
|
// this is only here to block PPointer's implementation
|
||||||
void SetPointer(void *base, unsigned offset, TArray<size_t> *special = NULL) const override {}
|
void SetPointer(void *base, unsigned offset, TArray<size_t> *special = NULL) const override {}
|
||||||
|
bool isCompatible(PType *type);
|
||||||
|
|
||||||
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
|
|
|
@ -1263,10 +1263,11 @@ void G_PlayerFinishLevel (int player, EFinishLevelType mode, int flags)
|
||||||
|
|
||||||
// Strip all current powers, unless moving in a hub and the power is okay to keep.
|
// Strip all current powers, unless moving in a hub and the power is okay to keep.
|
||||||
item = p->mo->Inventory;
|
item = p->mo->Inventory;
|
||||||
|
auto ptype = PClass::FindActor(NAME_Powerup);
|
||||||
while (item != NULL)
|
while (item != NULL)
|
||||||
{
|
{
|
||||||
next = item->Inventory;
|
next = item->Inventory;
|
||||||
if (item->IsKindOf (RUNTIME_CLASS(APowerup)))
|
if (item->IsKindOf (ptype))
|
||||||
{
|
{
|
||||||
if (deathmatch || ((mode != FINISH_SameHub || !(item->ItemFlags & IF_HUBPOWER))
|
if (deathmatch || ((mode != FINISH_SameHub || !(item->ItemFlags & IF_HUBPOWER))
|
||||||
&& !(item->ItemFlags & IF_PERSISTENTPOWER))) // Keep persistent powers in non-deathmatch games
|
&& !(item->ItemFlags & IF_PERSISTENTPOWER))) // Keep persistent powers in non-deathmatch games
|
||||||
|
|
|
@ -48,35 +48,6 @@ IMPLEMENT_CLASS(APowerup, false, false)
|
||||||
// Powerup-Giver -------------------------------------------------------------
|
// Powerup-Giver -------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
IMPLEMENT_CLASS(APowerupGiver, false, true)
|
|
||||||
|
|
||||||
IMPLEMENT_POINTERS_START(APowerupGiver)
|
|
||||||
IMPLEMENT_POINTER(PowerupType)
|
|
||||||
IMPLEMENT_POINTERS_END
|
|
||||||
|
|
||||||
DEFINE_FIELD(APowerupGiver, PowerupType)
|
|
||||||
DEFINE_FIELD(APowerupGiver, EffectTics)
|
|
||||||
DEFINE_FIELD(APowerupGiver, BlendColor)
|
|
||||||
DEFINE_FIELD(APowerupGiver, Mode)
|
|
||||||
DEFINE_FIELD(APowerupGiver, Strength)
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// APowerupGiver :: Serialize
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void APowerupGiver::Serialize(FSerializer &arc)
|
|
||||||
{
|
|
||||||
Super::Serialize (arc);
|
|
||||||
auto def = (APowerupGiver*)GetDefault();
|
|
||||||
arc("poweruptype", PowerupType, def->PowerupType)
|
|
||||||
("effecttics", EffectTics, def->EffectTics)
|
|
||||||
("blendcolor", BlendColor, def->BlendColor)
|
|
||||||
("mode", Mode, def->Mode)
|
|
||||||
("strength", Strength, def->Strength);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Powerup -------------------------------------------------------------------
|
// Powerup -------------------------------------------------------------------
|
||||||
|
|
||||||
DEFINE_FIELD(APowerup, EffectTics)
|
DEFINE_FIELD(APowerup, EffectTics)
|
||||||
|
@ -101,4 +72,3 @@ void APowerup::Serialize(FSerializer &arc)
|
||||||
("strength", Strength, def->Strength)
|
("strength", Strength, def->Strength)
|
||||||
("colormap", Colormap, def->Colormap);
|
("colormap", Colormap, def->Colormap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,22 +23,4 @@ public:
|
||||||
friend void EndAllPowerupEffects(AInventory *item);
|
friend void EndAllPowerupEffects(AInventory *item);
|
||||||
friend void InitAllPowerupEffects(AInventory *item);
|
friend void InitAllPowerupEffects(AInventory *item);
|
||||||
};
|
};
|
||||||
|
|
||||||
// An artifact is an item that gives the player a powerup when activated.
|
|
||||||
class APowerupGiver : public AInventory
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (APowerupGiver, AInventory)
|
|
||||||
HAS_OBJECT_POINTERS
|
|
||||||
public:
|
|
||||||
virtual void Serialize(FSerializer &arc) override;
|
|
||||||
|
|
||||||
|
|
||||||
PClassActor *PowerupType;
|
|
||||||
int EffectTics; // Non-0 to override the powerup's default tics
|
|
||||||
PalEntry BlendColor; // Non-0 to override the powerup's default blend
|
|
||||||
FNameNoInit Mode; // Meaning depends on powerup - used for Invulnerability and Invisibility
|
|
||||||
double Strength; // Meaning depends on powerup - currently used only by Invisibility
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //__A_ARTIFACTS_H__
|
#endif //__A_ARTIFACTS_H__
|
||||||
|
|
|
@ -594,11 +594,12 @@ bool P_MorphedDeath(AActor *actor, AActor **morphed, int *morphedstyle, int *mor
|
||||||
|
|
||||||
void EndAllPowerupEffects(AInventory *item)
|
void EndAllPowerupEffects(AInventory *item)
|
||||||
{
|
{
|
||||||
|
auto ptype = PClass::FindActor(NAME_Powerup);
|
||||||
while (item != NULL)
|
while (item != NULL)
|
||||||
{
|
{
|
||||||
if (item->IsKindOf(RUNTIME_CLASS(APowerup)))
|
if (item->IsKindOf(ptype))
|
||||||
{
|
{
|
||||||
IFVIRTUALPTR(item, APowerup, EndEffect)
|
IFVIRTUALPTRNAME(item, NAME_Powerup, EndEffect)
|
||||||
{
|
{
|
||||||
VMValue params[1] = { item };
|
VMValue params[1] = { item };
|
||||||
VMFrameStack stack;
|
VMFrameStack stack;
|
||||||
|
@ -619,11 +620,12 @@ void EndAllPowerupEffects(AInventory *item)
|
||||||
|
|
||||||
void InitAllPowerupEffects(AInventory *item)
|
void InitAllPowerupEffects(AInventory *item)
|
||||||
{
|
{
|
||||||
|
auto ptype = PClass::FindActor(NAME_Powerup);
|
||||||
while (item != NULL)
|
while (item != NULL)
|
||||||
{
|
{
|
||||||
if (item->IsKindOf(RUNTIME_CLASS(APowerup)))
|
if (item->IsKindOf(ptype))
|
||||||
{
|
{
|
||||||
IFVIRTUALPTR(item, APowerup, InitEffect)
|
IFVIRTUALPTRNAME(item, NAME_Powerup, EndEffect)
|
||||||
{
|
{
|
||||||
VMValue params[1] = { item };
|
VMValue params[1] = { item };
|
||||||
VMFrameStack stack;
|
VMFrameStack stack;
|
||||||
|
|
|
@ -1158,10 +1158,10 @@ class CommandDrawNumber : public CommandDrawString
|
||||||
if(!parenthesized || !sc.CheckToken(TK_StringConst))
|
if(!parenthesized || !sc.CheckToken(TK_StringConst))
|
||||||
sc.MustGetToken(TK_Identifier);
|
sc.MustGetToken(TK_Identifier);
|
||||||
inventoryItem = PClass::FindActor(sc.String);
|
inventoryItem = PClass::FindActor(sc.String);
|
||||||
if(inventoryItem == NULL || !RUNTIME_CLASS(APowerupGiver)->IsAncestorOf(inventoryItem))
|
if(inventoryItem == NULL || !PClass::FindActor(NAME_PowerupGiver)->IsAncestorOf(inventoryItem))
|
||||||
{
|
{
|
||||||
sc.ScriptMessage("'%s' is not a type of PowerupGiver.", sc.String);
|
sc.ScriptMessage("'%s' is not a type of PowerupGiver.", sc.String);
|
||||||
inventoryItem = RUNTIME_CLASS(APowerupGiver);
|
inventoryItem = PClass::FindActor(NAME_PowerupGiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(parenthesized) sc.MustGetToken(')');
|
if(parenthesized) sc.MustGetToken(')');
|
||||||
|
@ -1433,11 +1433,14 @@ class CommandDrawNumber : public CommandDrawString
|
||||||
break;
|
break;
|
||||||
case POWERUPTIME:
|
case POWERUPTIME:
|
||||||
{
|
{
|
||||||
//Get the PowerupType and check to see if the player has any in inventory.
|
// num = statusBar.CPlayer.mo.GetEffectTicsForItem(inventoryItem) / TICRATE + 1;
|
||||||
PClassActor* powerupType = ((APowerupGiver*) GetDefaultByType(inventoryItem))->PowerupType;
|
static VMFunction *func = nullptr;
|
||||||
APowerup* powerup = (APowerup*) statusBar->CPlayer->mo->FindInventory(powerupType);
|
if (func == nullptr) func = static_cast<PFunction*>(RUNTIME_CLASS(APlayerPawn)->Symbols.FindSymbol("GetEffectTicsForItem", false))->Variants[0].Implementation;
|
||||||
if(powerup != NULL)
|
VMValue params[] = { statusBar->CPlayer->mo, inventoryItem };
|
||||||
num = powerup->EffectTics / TICRATE + 1;
|
int retv;
|
||||||
|
VMReturn ret(&retv);
|
||||||
|
GlobalVMStack.Call(func, params, 2, &ret, 1);
|
||||||
|
num = retv / TICRATE + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case INVENTORY:
|
case INVENTORY:
|
||||||
|
@ -2655,10 +2658,10 @@ class CommandDrawBar : public SBarInfoCommand
|
||||||
if(!parenthesized || !sc.CheckToken(TK_StringConst))
|
if(!parenthesized || !sc.CheckToken(TK_StringConst))
|
||||||
sc.MustGetToken(TK_Identifier);
|
sc.MustGetToken(TK_Identifier);
|
||||||
data.inventoryItem = PClass::FindActor(sc.String);
|
data.inventoryItem = PClass::FindActor(sc.String);
|
||||||
if(data.inventoryItem == NULL || !RUNTIME_CLASS(APowerupGiver)->IsAncestorOf(data.inventoryItem))
|
if(data.inventoryItem == NULL || !PClass::FindActor(NAME_PowerupGiver)->IsAncestorOf(data.inventoryItem))
|
||||||
{
|
{
|
||||||
sc.ScriptMessage("'%s' is not a type of PowerupGiver.", sc.String);
|
sc.ScriptMessage("'%s' is not a type of PowerupGiver.", sc.String);
|
||||||
data.inventoryItem = RUNTIME_CLASS(APowerupGiver);
|
data.inventoryItem = PClass::FindActor(NAME_PowerupGiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(parenthesized) sc.MustGetToken(')');
|
if(parenthesized) sc.MustGetToken(')');
|
||||||
|
@ -2822,18 +2825,16 @@ class CommandDrawBar : public SBarInfoCommand
|
||||||
break;
|
break;
|
||||||
case POWERUPTIME:
|
case POWERUPTIME:
|
||||||
{
|
{
|
||||||
//Get the PowerupType and check to see if the player has any in inventory.
|
static VMFunction *func = nullptr;
|
||||||
APowerupGiver *powerupGiver = (APowerupGiver*) GetDefaultByType(data.inventoryItem);
|
if (func == nullptr) func = static_cast<PFunction*>(RUNTIME_CLASS(APlayerPawn)->Symbols.FindSymbol("GetEffectTicsForItem", false))->Variants[0].Implementation;
|
||||||
PClassActor *powerupType = powerupGiver->PowerupType;
|
VMValue params[] = { statusBar->CPlayer->mo, data.inventoryItem };
|
||||||
APowerup *powerup = (APowerup*) statusBar->CPlayer->mo->FindInventory(powerupType);
|
VMReturn ret[2];
|
||||||
if(powerup != NULL && powerupType != NULL && powerupGiver != NULL)
|
int ival;
|
||||||
{
|
ret[0].IntAt(&ival);
|
||||||
value = powerup->EffectTics + 1;
|
ret[1].IntAt(&max);
|
||||||
if(powerupGiver->EffectTics == 0) //if 0 we need to get the default from the powerup
|
GlobalVMStack.Call(func, params, 2, ret, 2);
|
||||||
max = ((APowerup*) GetDefaultByType(powerupType))->EffectTics + 1;
|
value = ival + 1;
|
||||||
else
|
max++;
|
||||||
max = powerupGiver->EffectTics + 1;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SAVEPERCENT:
|
case SAVEPERCENT:
|
||||||
|
|
|
@ -709,6 +709,13 @@ xx(Wi_NoAutostartMap)
|
||||||
xx(MorphStyle)
|
xx(MorphStyle)
|
||||||
xx(MorphFlash)
|
xx(MorphFlash)
|
||||||
xx(UnMorphFlash)
|
xx(UnMorphFlash)
|
||||||
|
xx(Powerup)
|
||||||
|
xx(EffectTics)
|
||||||
|
xx(PowerupGiver)
|
||||||
|
xx(BlendColor)
|
||||||
|
xx(Strength)
|
||||||
|
xx(Mode)
|
||||||
|
xx(PowerupType)
|
||||||
|
|
||||||
// Decorate compatibility functions
|
// Decorate compatibility functions
|
||||||
xx(BuiltinTypeCheck)
|
xx(BuiltinTypeCheck)
|
||||||
|
|
|
@ -5719,7 +5719,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
|
||||||
if (argCount >= 2)
|
if (argCount >= 2)
|
||||||
{
|
{
|
||||||
PClassActor *powerupclass = PClass::FindActor(FBehavior::StaticLookupString(args[1]));
|
PClassActor *powerupclass = PClass::FindActor(FBehavior::StaticLookupString(args[1]));
|
||||||
if (powerupclass == NULL || !RUNTIME_CLASS(APowerup)->IsAncestorOf(powerupclass))
|
if (powerupclass == NULL || !powerupclass->IsDescendantOf(PClass::FindActor(NAME_Powerup)))
|
||||||
{
|
{
|
||||||
Printf("'%s' is not a type of Powerup.\n", FBehavior::StaticLookupString(args[1]));
|
Printf("'%s' is not a type of Powerup.\n", FBehavior::StaticLookupString(args[1]));
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -5381,15 +5381,13 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
|
||||||
oldactor->DestroyAllInventory();
|
oldactor->DestroyAllInventory();
|
||||||
}
|
}
|
||||||
// [BC] Handle temporary invulnerability when respawned
|
// [BC] Handle temporary invulnerability when respawned
|
||||||
if ((state == PST_REBORN || state == PST_ENTER) &&
|
if (state == PST_REBORN || state == PST_ENTER)
|
||||||
(dmflags2 & DF2_YES_RESPAWN_INVUL) &&
|
|
||||||
(multiplayer || alwaysapplydmflags))
|
|
||||||
{
|
{
|
||||||
APowerup *invul = static_cast<APowerup*>(p->mo->GiveInventoryType (PClass::FindActor(NAME_PowerInvulnerable)));
|
IFVIRTUALPTR(p->mo, APlayerPawn, OnRespawn)
|
||||||
invul->EffectTics = 3*TICRATE;
|
{
|
||||||
invul->BlendColor = 0; // don't mess with the view
|
VMValue param = p->mo;
|
||||||
invul->ItemFlags |= IF_UNDROPPABLE; // Don't drop this
|
GlobalVMStack.Call(func, ¶m, 1, nullptr, 0);
|
||||||
p->mo->effects |= FX_RESPAWNINVUL; // [RH] special effect
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StatusBar != NULL && (playernum == consoleplayer || StatusBar->GetPlayer() == playernum))
|
if (StatusBar != NULL && (playernum == consoleplayer || StatusBar->GetPlayer() == playernum))
|
||||||
|
|
|
@ -1166,7 +1166,7 @@ void APlayerPawn::FilterCoopRespawnInventory (APlayerPawn *oldplayer)
|
||||||
}
|
}
|
||||||
else if ((dmflags & DF_COOP_LOSE_POWERUPS) &&
|
else if ((dmflags & DF_COOP_LOSE_POWERUPS) &&
|
||||||
defitem == NULL &&
|
defitem == NULL &&
|
||||||
item->IsKindOf(RUNTIME_CLASS(APowerupGiver)))
|
item->IsKindOf(PClass::FindActor(NAME_PowerupGiver)))
|
||||||
{
|
{
|
||||||
item->Destroy();
|
item->Destroy();
|
||||||
}
|
}
|
||||||
|
|
|
@ -464,10 +464,17 @@ int MatchString (const char *in, const char **strings)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
static bool PointerCheck(PType *symtype, PType *checktype)
|
||||||
|
{
|
||||||
|
auto symptype = dyn_cast<PClassPointer>(symtype);
|
||||||
|
auto checkptype = dyn_cast<PClassPointer>(checktype);
|
||||||
|
return symptype != nullptr && checkptype != nullptr && symptype->ClassRestriction->IsDescendantOf(checkptype->ClassRestriction);
|
||||||
|
}
|
||||||
|
|
||||||
static void *ScriptVar(DObject *obj, PClass *cls, FName field, PType *type)
|
static void *ScriptVar(DObject *obj, PClass *cls, FName field, PType *type)
|
||||||
{
|
{
|
||||||
auto sym = dyn_cast<PField>(cls->Symbols.FindSymbol(field, true));
|
auto sym = dyn_cast<PField>(cls->Symbols.FindSymbol(field, true));
|
||||||
if (sym && sym->Type == type)
|
if (sym && (sym->Type == type || PointerCheck(sym->Type, type)))
|
||||||
{
|
{
|
||||||
return (((char*)obj) + sym->Offset);
|
return (((char*)obj) + sym->Offset);
|
||||||
}
|
}
|
||||||
|
@ -2278,14 +2285,11 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, color, C_f, Inventory)
|
||||||
|
|
||||||
int alpha;
|
int alpha;
|
||||||
PalEntry *pBlendColor;
|
PalEntry *pBlendColor;
|
||||||
|
bool isgiver = info->IsDescendantOf(PClass::FindActor(NAME_PowerupGiver));
|
||||||
|
|
||||||
if (info->IsDescendantOf(RUNTIME_CLASS(APowerup)))
|
if (info->IsDescendantOf(PClass::FindActor(NAME_Powerup)) || isgiver)
|
||||||
{
|
{
|
||||||
pBlendColor = &((APowerup*)defaults)->BlendColor;
|
pBlendColor = &TypedScriptVar<PalEntry>(defaults, info, NAME_BlendColor, TypeColor);
|
||||||
}
|
|
||||||
else if (info->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
|
|
||||||
{
|
|
||||||
pBlendColor = &((APowerupGiver*)defaults)->BlendColor;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2307,7 +2311,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, color, C_f, Inventory)
|
||||||
*pBlendColor = MakeSpecialColormap(v);
|
*pBlendColor = MakeSpecialColormap(v);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!stricmp(name, "none") && info->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
|
else if (!stricmp(name, "none") && isgiver)
|
||||||
{
|
{
|
||||||
*pBlendColor = MakeSpecialColormap(65535);
|
*pBlendColor = MakeSpecialColormap(65535);
|
||||||
return;
|
return;
|
||||||
|
@ -2333,13 +2337,9 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, colormap, FFFfff, Inventory)
|
||||||
{
|
{
|
||||||
PalEntry * pBlendColor;
|
PalEntry * pBlendColor;
|
||||||
|
|
||||||
if (info->IsDescendantOf(RUNTIME_CLASS(APowerup)))
|
if (info->IsDescendantOf(PClass::FindActor(NAME_Powerup)) || info->IsDescendantOf(PClass::FindActor(NAME_PowerupGiver)))
|
||||||
{
|
{
|
||||||
pBlendColor = &((APowerup*)defaults)->BlendColor;
|
pBlendColor = &TypedScriptVar<PalEntry>(defaults, info, NAME_BlendColor, TypeColor);
|
||||||
}
|
|
||||||
else if (info->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
|
|
||||||
{
|
|
||||||
pBlendColor = &((APowerupGiver*)defaults)->BlendColor;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2377,13 +2377,9 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, duration, I, Inventory)
|
||||||
{
|
{
|
||||||
int *pEffectTics;
|
int *pEffectTics;
|
||||||
|
|
||||||
if (info->IsDescendantOf(RUNTIME_CLASS(APowerup)))
|
if (info->IsDescendantOf(PClass::FindActor(NAME_Powerup)) || info->IsDescendantOf(PClass::FindActor(NAME_PowerupGiver)))
|
||||||
{
|
{
|
||||||
pEffectTics = &((APowerup*)defaults)->EffectTics;
|
pEffectTics = &TypedScriptVar<int>(defaults, info, NAME_EffectTics, TypeSInt32);
|
||||||
}
|
|
||||||
else if (info->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
|
|
||||||
{
|
|
||||||
pEffectTics = &((APowerupGiver*)defaults)->EffectTics;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2402,13 +2398,9 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, strength, F, Inventory)
|
||||||
{
|
{
|
||||||
double *pStrength;
|
double *pStrength;
|
||||||
|
|
||||||
if (info->IsDescendantOf(RUNTIME_CLASS(APowerup)))
|
if (info->IsDescendantOf(PClass::FindActor(NAME_Powerup)) || info->IsDescendantOf(PClass::FindActor(NAME_PowerupGiver)))
|
||||||
{
|
{
|
||||||
pStrength = &((APowerup*)defaults)->Strength;
|
pStrength = &TypedScriptVar<double>(defaults, info, NAME_Strength, TypeFloat64);
|
||||||
}
|
|
||||||
else if (info->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
|
|
||||||
{
|
|
||||||
pStrength = &((APowerupGiver*)defaults)->Strength;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2426,13 +2418,10 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, mode, S, Inventory)
|
||||||
{
|
{
|
||||||
PROP_STRING_PARM(str, 0);
|
PROP_STRING_PARM(str, 0);
|
||||||
FName *pMode;
|
FName *pMode;
|
||||||
if (info->IsDescendantOf(RUNTIME_CLASS(APowerup)))
|
|
||||||
|
if (info->IsDescendantOf(PClass::FindActor(NAME_Powerup)) || info->IsDescendantOf(PClass::FindActor(NAME_PowerupGiver)))
|
||||||
{
|
{
|
||||||
pMode = &((APowerup*)defaults)->Mode;
|
pMode = &TypedScriptVar<FName>(defaults, info, NAME_Mode, TypeName);
|
||||||
}
|
|
||||||
else if (info->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
|
|
||||||
{
|
|
||||||
pMode = &((APowerupGiver*)defaults)->Mode;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2445,7 +2434,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, mode, S, Inventory)
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
DEFINE_CLASS_PROPERTY_PREFIX(powerup, type, S, PowerupGiver)
|
DEFINE_SCRIPTED_PROPERTY_PREFIX(powerup, type, S, PowerupGiver)
|
||||||
{
|
{
|
||||||
PROP_STRING_PARM(str, 0);
|
PROP_STRING_PARM(str, 0);
|
||||||
|
|
||||||
|
@ -2465,8 +2454,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, type, S, PowerupGiver)
|
||||||
I_Error("Unknown powerup type %s", str);
|
I_Error("Unknown powerup type %s", str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TypedScriptVar<PClassActor*>(defaults, info, NAME_PowerupType, NewClassPointer(RUNTIME_CLASS(AActor))) = cls;
|
||||||
defaults->PowerupType = cls;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -393,6 +393,11 @@ struct VMReturn
|
||||||
TagOfs = 0;
|
TagOfs = 0;
|
||||||
RegType = REGT_POINTER;
|
RegType = REGT_POINTER;
|
||||||
}
|
}
|
||||||
|
VMReturn() { }
|
||||||
|
VMReturn(int *loc) { IntAt(loc); }
|
||||||
|
VMReturn(double *loc) { FloatAt(loc); }
|
||||||
|
VMReturn(FString *loc) { StringAt(loc); }
|
||||||
|
VMReturn(void **loc) { PointerAt(loc); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VMRegisters;
|
struct VMRegisters;
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
class PowerupGiver : Inventory native
|
class PowerupGiver : Inventory
|
||||||
{
|
{
|
||||||
|
|
||||||
native Class<Actor> PowerupType;
|
Class<Actor> PowerupType;
|
||||||
native int EffectTics; // Non-0 to override the powerup's default tics
|
int EffectTics; // Non-0 to override the powerup's default tics
|
||||||
native color BlendColor; // Non-0 to override the powerup's default blend
|
color BlendColor; // Non-0 to override the powerup's default blend
|
||||||
native Name Mode; // Meaning depends on powerup - used for Invulnerability and Invisibility
|
Name Mode; // Meaning depends on powerup - used for Invulnerability and Invisibility
|
||||||
native double Strength; // Meaning depends on powerup - currently used only by Invisibility
|
double Strength; // Meaning depends on powerup - currently used only by Invisibility
|
||||||
|
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
|
@ -56,8 +56,6 @@ class PowerupGiver : Inventory native
|
||||||
power.GoAwayAndDie ();
|
power.GoAwayAndDie ();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Powerup : Inventory native
|
class Powerup : Inventory native
|
||||||
|
|
|
@ -102,6 +102,36 @@ class PlayerPawn : Actor native
|
||||||
virtual void MorphPlayerThink()
|
virtual void MorphPlayerThink()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void OnRespawn()
|
||||||
|
{
|
||||||
|
if (sv_respawnprotect && (multiplayer || alwaysapplydmflags))
|
||||||
|
{
|
||||||
|
let invul = Powerup(Spawn("PowerInvulnerable"));
|
||||||
|
invul.EffectTics = 3 * TICRATE;
|
||||||
|
invul.BlendColor = 0; // don't mess with the view
|
||||||
|
invul.bUndroppable = true; // Don't drop this
|
||||||
|
bRespawnInvul = true; // [RH] special effect
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is for SBARINFO.
|
||||||
|
int/*, int*/ GetEffectTicsForItem(class<Inventory> item)
|
||||||
|
{
|
||||||
|
let pg = (class<PowerupGiver>)(item);
|
||||||
|
if (pg != null)
|
||||||
|
{
|
||||||
|
let powerupType = (class<Powerup>)(GetDefaultByType(pg).PowerupType);
|
||||||
|
let powerup = Powerup(FindInventory(powerupType));
|
||||||
|
if(powerup != null)
|
||||||
|
{
|
||||||
|
let maxtics = GetDefaultByType(powerupType).EffectTics;
|
||||||
|
if (maxtics == 0) maxtics = powerup.default.EffectTics;
|
||||||
|
return powerup.EffectTics/*, maxtics*/;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0/*, 0*/;
|
||||||
|
}
|
||||||
|
|
||||||
native int GetMaxHealth();
|
native int GetMaxHealth();
|
||||||
native bool ResetAirSupply (bool playgasp = false);
|
native bool ResetAirSupply (bool playgasp = false);
|
||||||
|
|
Loading…
Reference in a new issue