- scriptified a_strifeitems.cpp and a_debris.cpp.

- Changed the glass shards so that they do not have to override FloorBounceMissile. It was the only place where this was virtually overridden and provided little usefulness.
- made 'out' variables work.
- fixed virtual call handling for HandlePickup.
This commit is contained in:
Christoph Oelckers 2016-11-29 12:17:05 +01:00
parent 55b549c0c6
commit 3af9232fca
29 changed files with 374 additions and 528 deletions

View file

@ -861,7 +861,6 @@ set( NOT_COMPILED_SOURCE_FILES
sc_man_scanner.re
g_hexen/a_heresiarch.cpp
g_hexen/a_spike.cpp
g_strife/a_strifeitems.cpp
g_strife/a_strifeweapons.cpp
g_shared/sbarinfo_commands.cpp
xlat/xlat_parser.y
@ -1119,7 +1118,6 @@ set (PCH_SOURCES
g_shared/a_artifacts.cpp
g_shared/a_bridge.cpp
g_shared/a_camera.cpp
g_shared/a_debris.cpp
g_shared/a_decals.cpp
g_shared/a_fastprojectile.cpp
g_shared/a_flashfader.cpp

View file

@ -648,7 +648,7 @@ public:
void PlayBounceSound(bool onfloor);
// Called when an actor with MF_MISSILE and MF2_FLOORBOUNCE hits the floor
virtual bool FloorBounceMissile (secplane_t &plane);
bool FloorBounceMissile (secplane_t &plane);
// Called when an actor is to be reflected by a disc of repulsion.
// Returns true to continue normal blast processing.
@ -682,7 +682,7 @@ public:
// Give an item to the actor and pick it up.
// Returns true if the item pickup succeeded.
virtual bool GiveInventory (PClassInventory *type, int amount, bool givecheat = false);
bool GiveInventory (PClassInventory *type, int amount, bool givecheat = false);
// Removes the item from the inventory list.
virtual void RemoveInventory (AInventory *item);
@ -693,8 +693,7 @@ public:
virtual bool TakeInventory (PClassActor *itemclass, int amount, bool fromdecorate = false, bool notakeinfinite = false);
// Uses an item and removes it from the inventory.
virtual bool DoUseInventory (AInventory *item);
bool UseInventory(AInventory *item);
virtual bool UseInventory (AInventory *item);
// Tosses an item out of the inventory.
AInventory *DropInventory (AInventory *item);

View file

@ -109,7 +109,7 @@ public:
virtual void Tick();
virtual void AddInventory (AInventory *item);
virtual void RemoveInventory (AInventory *item);
virtual bool DoUseInventory (AInventory *item);
virtual bool UseInventory (AInventory *item);
virtual void MarkPrecacheSounds () const;
virtual void PlayIdle ();

View file

@ -79,7 +79,6 @@
#include "v_palette.h"
#include "menu/menu.h"
#include "a_sharedglobal.h"
#include "a_strifeglobal.h"
#include "r_data/colormaps.h"
#include "r_renderer.h"
#include "r_utility.h"

View file

@ -1,27 +0,0 @@
#include "actor.h"
#include "info.h"
#include "m_random.h"
#include "m_fixed.h"
// Stained glass ------------------------------------------------------------
class AGlassShard : public AActor
{
DECLARE_CLASS (AGlassShard, AActor)
public:
bool FloorBounceMissile (secplane_t &plane)
{
if (!Super::FloorBounceMissile (plane))
{
if (fabs (Vel.Z) < 0.5)
{
Destroy ();
}
return false;
}
return true;
}
};
IMPLEMENT_CLASS(AGlassShard, false, false)

View file

@ -11,7 +11,6 @@
#include "c_dispatch.h"
#include "gstrings.h"
#include "templates.h"
#include "a_strifeglobal.h"
#include "a_morph.h"
#include "a_specialspot.h"
#include "g_level.h"
@ -751,7 +750,7 @@ bool AInventory::CallHandlePickup(AInventory *item)
auto self = this;
while (self != nullptr)
{
IFVIRTUAL(AInventory, HandlePickup)
IFVIRTUALPTR(self, AInventory, HandlePickup)
{
// Without the type cast this picks the 'void *' assignment...
VMValue params[2] = { (DObject*)self, (DObject*)item };
@ -1684,6 +1683,13 @@ bool AInventory::TryPickup (AActor *&toucher)
return true;
}
DEFINE_ACTION_FUNCTION(AInventory, TryPickup)
{
PARAM_SELF_PROLOGUE(AInventory);
PARAM_POINTER(toucher, AActor*);
ACTION_RETURN_BOOL(self->TryPickup(*toucher));
}
//===========================================================================
//
// AInventory :: TryPickupRestricted
@ -1710,7 +1716,20 @@ bool AInventory::CallTryPickup (AActor *toucher, AActor **toucher_return)
bool res;
if (CanPickup(toucher))
res = TryPickup(toucher);
{
bool res;
IFVIRTUAL(AInventory, TryPickup)
{
VMValue params[2] = { (DObject*)this, (void*)&toucher };
VMReturn ret;
VMFrameStack stack;
int retval;
ret.IntAt(&retval);
stack.Call(func, params, 2, &ret, 1, nullptr);
res = !!retval;
}
else res = TryPickup(toucher);
}
else if (!(ItemFlags & IF_RESTRICTABSOLUTELY))
res = TryPickupRestricted(toucher); // let an item decide for itself how it will handle this
else

View file

@ -222,9 +222,9 @@ public:
virtual PalEntry GetBlend ();
PalEntry CallGetBlend();
protected:
virtual bool TryPickup (AActor *&toucher);
virtual bool TryPickupRestricted (AActor *&toucher);
protected:
bool CanPickup(AActor * toucher);
void GiveQuest(AActor * toucher);
@ -600,5 +600,7 @@ public:
bool TryPickup(AActor *&toucher);
};
extern PClassActor *QuestItemClasses[31];
#endif //__A_PICKUPS_H__

View file

@ -52,7 +52,6 @@
#include "r_data/r_translate.h"
#include "a_artifacts.h"
#include "a_weaponpiece.h"
#include "a_strifeglobal.h"
#include "g_level.h"
#include "v_palette.h"
#include "p_acs.h"

View file

@ -4,42 +4,4 @@
#include "info.h"
#include "a_pickups.h"
// Base class for every humanoid in Strife that can go into
// a fire or electric death.
class ADegninOre : public AInventory
{
DECLARE_CLASS (ADegninOre, AInventory)
public:
bool Use (bool pickup);
};
class ADummyStrifeItem : public AInventory
{
DECLARE_CLASS (ADummyStrifeItem, AInventory)
};
class AUpgradeStamina : public ADummyStrifeItem
{
DECLARE_CLASS (AUpgradeStamina, ADummyStrifeItem)
public:
bool TryPickup (AActor *&toucher);
};
class AUpgradeAccuracy : public ADummyStrifeItem
{
DECLARE_CLASS (AUpgradeAccuracy, ADummyStrifeItem)
public:
bool TryPickup (AActor *&toucher);
};
class ASlideshowStarter : public ADummyStrifeItem
{
DECLARE_CLASS (ASlideshowStarter, ADummyStrifeItem)
public:
bool TryPickup (AActor *&toucher);
};
extern PClassActor *QuestItemClasses[31];
#endif

View file

@ -1,377 +0,0 @@
/*
#include "info.h"
#include "a_pickups.h"
#include "d_player.h"
#include "gstrings.h"
#include "p_local.h"
#include "p_spec.h"
#include "a_strifeglobal.h"
#include "p_lnspec.h"
#include "p_enemy.h"
#include "s_sound.h"
#include "d_event.h"
#include "a_keys.h"
#include "c_console.h"
#include "templates.h"
#include "vm.h"
#include "g_level.h"
#include "doomstat.h"
*/
// Degnin Ore ---------------------------------------------------------------
IMPLEMENT_CLASS(ADegninOre, false, false)
bool ADegninOre::Use (bool pickup)
{
if (pickup)
{
return false;
}
else
{
AInventory *drop;
// Increase the amount by one so that when DropInventory decrements it,
// the actor will have the same number of beacons that he started with.
// When we return to UseInventory, it will take care of decrementing
// Amount again and disposing of this item if there are no more.
Amount++;
drop = Owner->DropInventory (this);
if (drop == NULL)
{
Amount--;
return false;
}
return true;
}
}
// Health Training ----------------------------------------------------------
class AHealthTraining : public AInventory
{
DECLARE_CLASS (AHealthTraining, AInventory)
public:
bool TryPickup (AActor *&toucher);
};
IMPLEMENT_CLASS(AHealthTraining, false, false)
bool AHealthTraining::TryPickup (AActor *&toucher)
{
if (Super::TryPickup (toucher))
{
toucher->GiveInventoryType (PClass::FindActor("GunTraining"));
AInventory *coin = (AInventory*)Spawn("Coin");
if (coin != NULL)
{
coin->Amount = toucher->player->mo->accuracy*5 + 300;
if (!coin->CallTryPickup (toucher))
{
coin->Destroy ();
}
}
return true;
}
return false;
}
// Scanner ------------------------------------------------------------------
class AScanner : public APowerupGiver
{
DECLARE_CLASS (AScanner, APowerupGiver)
public:
bool Use (bool pickup);
};
IMPLEMENT_CLASS(AScanner, false, false)
bool AScanner::Use (bool pickup)
{
if (!(level.flags2 & LEVEL2_ALLMAP))
{
if (Owner->CheckLocalView (consoleplayer))
{
C_MidPrint(SmallFont, GStrings("TXT_NEEDMAP"));
}
return false;
}
return Super::Use (pickup);
}
// Prison Pass --------------------------------------------------------------
class APrisonPass : public AKey
{
DECLARE_CLASS (APrisonPass, AKey)
public:
bool TryPickup (AActor *&toucher);
bool SpecialDropAction (AActor *dropper);
};
IMPLEMENT_CLASS(APrisonPass, false, false)
bool APrisonPass::TryPickup (AActor *&toucher)
{
Super::TryPickup (toucher);
EV_DoDoor (DDoor::doorOpen, NULL, toucher, 223, 2., 0, 0, 0);
toucher->GiveInventoryType (QuestItemClasses[9]);
return true;
}
//============================================================================
//
// APrisonPass :: SpecialDropAction
//
// Trying to make a monster that drops a prison pass turns it into an
// OpenDoor223 item instead. That means the only way to get it in Strife
// is through dialog, which is why it doesn't have its own sprite.
//
//============================================================================
bool APrisonPass::SpecialDropAction (AActor *dropper)
{
EV_DoDoor (DDoor::doorOpen, NULL, dropper, 223, 2., 0, 0, 0);
Destroy ();
return true;
}
//---------------------------------------------------------------------------
// Dummy items. They are just used by Strife to perform ---------------------
// actions and cannot be held. ----------------------------------------------
//---------------------------------------------------------------------------
IMPLEMENT_CLASS(ADummyStrifeItem, false, false)
// Sound the alarm! ---------------------------------------------------------
class ARaiseAlarm : public ADummyStrifeItem
{
DECLARE_CLASS (ARaiseAlarm, ADummyStrifeItem)
public:
bool TryPickup (AActor *&toucher);
bool SpecialDropAction (AActor *dropper);
};
IMPLEMENT_CLASS(ARaiseAlarm, false, false)
bool ARaiseAlarm::TryPickup (AActor *&toucher)
{
P_NoiseAlert (toucher, toucher);
/*
ThinkerIterator it = ThinkerIterator.Create("AlienSpectre3");
Actor spectre = Actor(it.Next());
if (spectre != NULL && spectre.health > 0 && toucher != spectre)
{
spectre.CurSector.SoundTarget = spectre.LastHeard = toucher;
spectre.target = toucher;
spectre.SetState (spectre.SeeState);
}
*/
GoAwayAndDie ();
return true;
}
bool ARaiseAlarm::SpecialDropAction (AActor *dropper)
{
if (dropper->target != nullptr)
{
P_NoiseAlert(dropper->target, dropper->target);
if (dropper->target->CheckLocalView(consoleplayer))
{
Printf("You Fool! You've set off the alarm.\n");
}
}
Destroy ();
return true;
}
// Open door tag 222 --------------------------------------------------------
class AOpenDoor222 : public ADummyStrifeItem
{
DECLARE_CLASS (AOpenDoor222, ADummyStrifeItem)
public:
bool TryPickup (AActor *&toucher);
};
IMPLEMENT_CLASS(AOpenDoor222, false, false)
bool AOpenDoor222::TryPickup (AActor *&toucher)
{
EV_DoDoor (DDoor::doorOpen, NULL, toucher, 222, 2., 0, 0, 0);
GoAwayAndDie ();
return true;
}
// Close door tag 222 -------------------------------------------------------
class ACloseDoor222 : public ADummyStrifeItem
{
DECLARE_CLASS (ACloseDoor222, ADummyStrifeItem)
public:
bool TryPickup (AActor *&toucher);
bool SpecialDropAction (AActor *dropper);
};
IMPLEMENT_CLASS(ACloseDoor222, false, false)
bool ACloseDoor222::TryPickup (AActor *&toucher)
{
EV_DoDoor (DDoor::doorClose, NULL, toucher, 222, 2., 0, 0, 0);
GoAwayAndDie ();
return true;
}
bool ACloseDoor222::SpecialDropAction (AActor *dropper)
{
EV_DoDoor (DDoor::doorClose, NULL, dropper, 222, 2., 0, 0, 0);
if (dropper->target != nullptr)
{
if (dropper->target->CheckLocalView(consoleplayer))
{
Printf("You're dead! You set off the alarm.\n");
}
P_NoiseAlert(dropper->target, dropper->target);
}
Destroy ();
return true;
}
// Open door tag 224 --------------------------------------------------------
class AOpenDoor224 : public ADummyStrifeItem
{
DECLARE_CLASS (AOpenDoor224, ADummyStrifeItem)
public:
bool TryPickup (AActor *&toucher);
bool SpecialDropAction (AActor *dropper);
};
IMPLEMENT_CLASS(AOpenDoor224, false, false)
bool AOpenDoor224::TryPickup (AActor *&toucher)
{
EV_DoDoor (DDoor::doorOpen, NULL, toucher, 224, 2., 0, 0, 0);
GoAwayAndDie ();
return true;
}
bool AOpenDoor224::SpecialDropAction (AActor *dropper)
{
EV_DoDoor (DDoor::doorOpen, NULL, dropper, 224, 2., 0, 0, 0);
Destroy ();
return true;
}
// Ammo ---------------------------------------------------------------------
class AAmmoFillup : public ADummyStrifeItem
{
DECLARE_CLASS (AAmmoFillup, ADummyStrifeItem)
public:
bool TryPickup (AActor *&toucher);
};
IMPLEMENT_CLASS(AAmmoFillup, false, false)
bool AAmmoFillup::TryPickup (AActor *&toucher)
{
PClassActor *clip = PClass::FindActor(NAME_ClipOfBullets);
if (clip != NULL)
{
AInventory *item = toucher->FindInventory(clip);
if (item == NULL)
{
item = toucher->GiveInventoryType (clip);
if (item != NULL)
{
item->Amount = 50;
}
}
else if (item->Amount < 50)
{
item->Amount = 50;
}
else
{
return false;
}
GoAwayAndDie ();
}
return true;
}
// Health -------------------------------------------------------------------
class AHealthFillup : public ADummyStrifeItem
{
DECLARE_CLASS (AHealthFillup, ADummyStrifeItem)
public:
bool TryPickup (AActor *&toucher);
};
IMPLEMENT_CLASS(AHealthFillup, false, false)
bool AHealthFillup::TryPickup (AActor *&toucher)
{
static const int skillhealths[5] = { -100, -75, -50, -50, -100 };
int index = clamp<int>(gameskill, 0,4);
if (!P_GiveBody (toucher, skillhealths[index]))
{
return false;
}
GoAwayAndDie ();
return true;
}
// Upgrade Stamina ----------------------------------------------------------
IMPLEMENT_CLASS(AUpgradeStamina, false, false)
bool AUpgradeStamina::TryPickup (AActor *&toucher)
{
if (toucher->player == NULL)
return false;
toucher->player->mo->stamina += Amount;
if (toucher->player->mo->stamina >= MaxAmount)
toucher->player->mo->stamina = MaxAmount;
P_GiveBody (toucher, -100);
GoAwayAndDie ();
return true;
}
// Upgrade Accuracy ---------------------------------------------------------
IMPLEMENT_CLASS(AUpgradeAccuracy, false, false)
bool AUpgradeAccuracy::TryPickup (AActor *&toucher)
{
if (toucher->player == NULL || toucher->player->mo->accuracy >= 100)
return false;
toucher->player->mo->accuracy += 10;
GoAwayAndDie ();
return true;
}
// Start a slideshow --------------------------------------------------------
IMPLEMENT_CLASS(ASlideshowStarter, false, false)
bool ASlideshowStarter::TryPickup (AActor *&toucher)
{
gameaction = ga_slideshow;
if (level.levelnum == 10)
{
toucher->GiveInventoryType (QuestItemClasses[16]);
}
GoAwayAndDie ();
return true;
}

View file

@ -6,7 +6,6 @@
#include "d_player.h"
#include "a_action.h"
#include "p_local.h"
#include "a_strifeglobal.h"
#include "p_enemy.h"
#include "p_lnspec.h"
#include "c_console.h"
@ -24,7 +23,6 @@
#include "vm.h"
// Include all the other Strife stuff here to reduce compile time
#include "a_strifeitems.cpp"
#include "a_strifeweapons.cpp"
// Notes so I don't forget them:

View file

@ -12,7 +12,6 @@
#include "m_swap.h"
#include "templates.h"
#include "a_keys.h"
#include "a_strifeglobal.h"
#include "gi.h"
#include "g_level.h"
#include "colormatcher.h"

View file

@ -30,7 +30,6 @@
#include "doomstat.h"
#include "gstrings.h"
#include "p_local.h"
#include "a_strifeglobal.h"
#include "gi.h"
#include "p_enemy.h"
#include "sbar.h"

View file

@ -58,7 +58,6 @@
#include "sbar.h"
#include "m_swap.h"
#include "a_sharedglobal.h"
#include "a_strifeglobal.h"
#include "v_video.h"
#include "w_wad.h"
#include "r_sky.h"

View file

@ -44,7 +44,6 @@
#include "m_random.h"
#include "gi.h"
#include "templates.h"
#include "a_strifeglobal.h"
#include "a_keys.h"
#include "p_enemy.h"
#include "gstrings.h"
@ -1357,7 +1356,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
}
}
if (reply->GiveType->IsDescendantOf(RUNTIME_CLASS(ASlideshowStarter)))
if (reply->GiveType->IsDescendantOf(PClass::FindActor("SlideshowStarter")))
gameaction = ga_slideshow;
}
else

View file

@ -50,7 +50,6 @@
#include "gi.h"
#include "m_random.h"
#include "p_conversation.h"
#include "a_strifeglobal.h"
#include "r_data/r_translate.h"
#include "p_3dmidtex.h"
#include "d_net.h"
@ -3220,8 +3219,8 @@ FUNC(LS_GlassBreak)
if (it != NULL)
{
it->GiveInventoryType (QuestItemClasses[28]);
it->GiveInventoryType (RUNTIME_CLASS(AUpgradeAccuracy));
it->GiveInventoryType (RUNTIME_CLASS(AUpgradeStamina));
it->GiveInventoryType (PClass::FindActor("UpgradeAccuracy"));
it->GiveInventoryType (PClass::FindActor("UpgradeStamina"));
}
}
}

View file

@ -942,7 +942,7 @@ AInventory *AActor::FirstInv ()
//
//============================================================================
bool AActor::DoUseInventory (AInventory *item)
bool AActor::UseInventory (AInventory *item)
{
// No using items if you're dead.
if (health <= 0)
@ -973,23 +973,7 @@ DEFINE_ACTION_FUNCTION(AActor, UseInventory)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_OBJECT(item, AInventory);
ACTION_RETURN_BOOL(self->DoUseInventory(item));
}
bool AActor::UseInventory(AInventory *item)
{
IFVIRTUAL(AActor, UseInventory)
{
// Without the type cast this picks the 'void *' assignment...
VMValue params[2] = { (DObject*)this, (DObject*)item };
VMReturn ret;
VMFrameStack stack;
int retval;
ret.IntAt(&retval);
stack.Call(func, params, 2, &ret, 1, nullptr);
return !!retval;
}
else return DoUseInventory(item);
ACTION_RETURN_BOOL(self->UseInventory(item));
}
//===========================================================================
@ -1304,6 +1288,13 @@ bool AActor::CheckLocalView (int playernum) const
return false;
}
DEFINE_ACTION_FUNCTION(AActor, CheckLocalView)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_INT(cp);
ACTION_RETURN_BOOL(self->CheckLocalView(cp));
}
//============================================================================
//
// AActor :: IsInsideVisibleAngles

View file

@ -901,7 +901,7 @@ void APlayerPawn::RemoveInventory (AInventory *item)
//
//===========================================================================
bool APlayerPawn::DoUseInventory (AInventory *item)
bool APlayerPawn::UseInventory (AInventory *item)
{
const PClass *itemtype = item->GetClass();
@ -915,7 +915,7 @@ bool APlayerPawn::DoUseInventory (AInventory *item)
return false;
}
if (!Super::DoUseInventory (item))
if (!Super::UseInventory (item))
{
// Heretic and Hexen advance the inventory cursor if the use failed.
// Should this behavior be retained?

View file

@ -5821,12 +5821,32 @@ bool FxLocalVariable::RequestAddress(FCompileContext &ctx, bool *writable)
}
ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build)
{
// 'Out' variables are actually pointers but this fact must be hidden to the script.
if (Variable->VarFlags & VARF_Out)
{
if (!AddressRequested)
{
ExpEmit reg(build, ValueType->GetRegType(), ValueType->GetRegCount());
build->Emit(ValueType->GetLoadOp(), reg.RegNum, Variable->RegNum, build->GetConstantInt(RegOffset));
return reg;
}
else
{
if (RegOffset == 0) return ExpEmit(Variable->RegNum, REGT_POINTER, false, true);
ExpEmit reg(build, REGT_POINTER);
build->Emit(OP_ADDA_RK, reg.RegNum, Variable->RegNum, build->GetConstantInt(RegOffset));
return reg;
}
}
else
{
ExpEmit ret(Variable->RegNum + RegOffset, Variable->ValueType->GetRegType(), false, true);
ret.RegCount = ValueType->GetRegCount();
if (AddressRequested) ret.Target = true;
return ret;
}
}
//==========================================================================
@ -7781,7 +7801,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
}
FxExpression *x;
if (!(flag & VARF_Ref))
if (!(flag & (VARF_Ref|VARF_Out)))
{
x = new FxTypeCast(ArgList[i], type, false);
x = x->Resolve(ctx);
@ -7793,7 +7813,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
if (ArgList[i] != nullptr && ArgList[i]->ValueType != TypeNullPtr)
{
ArgList[i]->RequestAddress(ctx, &writable);
ArgList[i]->ValueType = NewPointer(ArgList[i]->ValueType);
if (flag & VARF_Ref) ArgList[i]->ValueType = NewPointer(ArgList[i]->ValueType);
// For a reference argument the types must match 100%.
if (type != ArgList[i]->ValueType)
{
@ -9917,10 +9937,15 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build)
{
if (Init == nullptr)
{
if (RegNum == -1) RegNum = build->Registers[ValueType->GetRegType()].Get(RegCount);
if (RegNum == -1)
{
if (!(VarFlags & VARF_Out)) RegNum = build->Registers[ValueType->GetRegType()].Get(RegCount);
else RegNum = build->Registers[REGT_POINTER].Get(1);
}
}
else
{
assert(!(VarFlags & VARF_Out)); // 'out' variables should never be initialized, they can only exist as function parameters.
ExpEmit emitval = Init->Emit(build);
int regtype = emitval.RegType;

View file

@ -48,6 +48,7 @@
#include "p_terrain.h"
#include "gstrings.h"
#include "zstring.h"
#include "d_event.h"
static TArray<FPropertyInfo*> properties;
static TArray<AFuncDesc> AFTable;
@ -743,6 +744,12 @@ void InitThingdef()
playerf = new PField("playeringame", parray, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&playeringame);
GlobalSymbols.AddSymbol(playerf);
playerf = new PField("gameaction", TypeUInt8, VARF_Native | VARF_Static, (intptr_t)&gameaction);
GlobalSymbols.AddSymbol(playerf);
playerf = new PField("consoleplayer", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&consoleplayer);
GlobalSymbols.AddSymbol(playerf);
// Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but it used everywhere as a special flag.
// It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution'
// is to create a static variable from it and reference that in the script. Yuck!!!

View file

@ -2169,17 +2169,16 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
{
auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false);
int flags = 0;
if (p->Flags & ZCC_In) flags |= VARF_In;
if (p->Flags & ZCC_Out) flags |= VARF_Out;
if ((type->IsA(RUNTIME_CLASS(PStruct))) || (flags & VARF_Out))
if (type->IsA(RUNTIME_CLASS(PStruct)) && type != TypeVector2 && type != TypeVector3)
{
// 'out' parameters and all structs except vectors are passed by reference
if ((flags & VARF_Out) || (type != TypeVector2 && type != TypeVector3))
{
type = NewPointer(type);
// Structs are being passed by pointer, but unless marked 'out' that pointer must be readonly.
type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/);
flags |= VARF_Ref;
}
else if (type == TypeVector2)
else if (type->GetRegType() != REGT_NIL)
{
if (p->Flags & ZCC_Out) flags |= VARF_Out;
if (type == TypeVector2)
{
elementcount = 2;
}

View file

@ -7,15 +7,14 @@ inline unsigned GetVirtualIndex(PClass *cls, const char *funcname)
return VIndex;
}
#define IFVIRTUAL(cls, funcname) \
#define IFVIRTUALPTR(self, cls, funcname) \
static unsigned VIndex = ~0u; \
if (VIndex == ~0u) { \
VIndex = GetVirtualIndex(RUNTIME_CLASS(cls), #funcname); \
assert(VIndex != ~0u); \
} \
auto clss = GetClass(); \
auto clss = self->GetClass(); \
VMFunction *func = clss->Virtuals.Size() > VIndex? clss->Virtuals[VIndex] : nullptr; \
if (func != nullptr)
#define IFVIRTUAL(cls, funcname) IFVIRTUALPTR(this, cls, funcname)

View file

@ -267,7 +267,6 @@ class Actor : Thinker native
virtual native int TakeSpecialDamage (Actor inflictor, Actor source, int damage, Name damagetype);
virtual native void Die(Actor source, Actor inflictor, int dmgflags = 0);
virtual native bool Slam(Actor victim);
virtual native bool UseInventory(Inventory item);
virtual native bool SpecialBlastHandling (Actor source, double strength);
virtual native void Touch(Actor toucher);
@ -292,6 +291,7 @@ class Actor : Thinker native
native void ClearBounce();
native TerrainDef GetFloorTerrain();
native Inventory DoDropItem(Class<Actor> type, int dropamount, int chance);
native bool CheckLocalView(int consoleplayer);
native void ExplodeMissile(line lin = null, Actor target = null);
native void RestoreDamage();
@ -378,6 +378,7 @@ class Actor : Thinker native
native Inventory FindInventory(class<Inventory> itemtype, bool subclass = false);
native Inventory GiveInventoryType(class<Inventory> itemtype);
native Inventory DropInventory (Inventory item);
native bool UseInventory(Inventory item);
native bool GiveAmmo (Class<Ammo> type, int amount);
// DECORATE compatible functions

View file

@ -1015,3 +1015,25 @@ enum PaletteFlashFlags
PF_ICE = 4,
PF_HAZARD = 8,
};
enum EGameAction
{
ga_nothing,
ga_loadlevel,
ga_newgame,
ga_newgame2,
ga_recordgame,
ga_loadgame,
ga_loadgamehidecon,
ga_loadgameplaydemo,
ga_autoloadgame,
ga_savegame,
ga_autosave,
ga_playdemo,
ga_completed,
ga_slideshow,
ga_worlddone,
ga_screenshot,
ga_togglemap,
ga_fullconsole,
};

View file

@ -175,7 +175,7 @@ class ScriptedMarine : Actor
//
//============================================================================
private bool GetWeaponStates(int weap, WeaponStates wstates)
private bool GetWeaponStates(int weap, out WeaponStates wstates)
{
static const statelabel MeleeNames[] =
{

View file

@ -187,7 +187,7 @@ class Dirt6 : Actor
// Stained glass ------------------------------------------------------------
class GlassShard : Actor native
class GlassShard : Actor
{
Default
{
@ -199,6 +199,16 @@ class GlassShard : Actor native
BounceType "HexenCompat";
BounceFactor 0.3;
}
override void Tick()
{
Super.Tick();
if (Vel.Z > 0 && Vel.Z < 0.5 && pos.z < floorz + 1)
{
Destroy ();
}
}
}
class SGShard1 : GlassShard

View file

@ -42,6 +42,7 @@ class Inventory : Actor native
private native void A_RestoreSpecialThing1();
private native void A_RestoreSpecialThing2();
virtual native bool TryPickup(in out Actor toucher);
native bool, Actor CallTryPickup(Actor toucher);
States(Actor, Overlay, Weapon, Item)

View file

@ -97,8 +97,8 @@ class Acolyte : StrifeHumanoid
if (i == MAXPLAYERS)
return;
// Make sure all the other blue acolytes are dead.
if (CheckBossDeath())
// Make sure all the other blue acolytes are dead, but do this only once in case of simultaneous kills.
if (CheckBossDeath() && !players[i].mo.FindInventory("QuestItem7"))
{
players[i].mo.GiveInventoryType ("QuestItem7");
players[i].SetLogNumber (14);

View file

@ -389,7 +389,7 @@ class Communicator : Inventory
// Degnin Ore ---------------------------------------------------------------
class DegninOre : Inventory native
class DegninOre : Inventory
{
Default
{
@ -421,6 +421,32 @@ class DegninOre : Inventory native
BNG3 BCDEFGH 3 Bright;
Stop;
}
override bool Use (bool pickup)
{
if (pickup)
{
return false;
}
else
{
Inventory drop;
// Increase the amount by one so that when DropInventory decrements it,
// the actor will have the same number of beacons that he started with.
// When we return to UseInventory, it will take care of decrementing
// Amount again and disposing of this item if there are no more.
Amount++;
drop = Owner.DropInventory (self);
if (drop == NULL)
{
Amount--;
return false;
}
return true;
}
}
}
// Gun Training -------------------------------------------------------------
@ -446,7 +472,7 @@ class GunTraining : Inventory
// Health Training ----------------------------------------------------------
class HealthTraining : Inventory native
class HealthTraining : Inventory
{
Default
{
@ -463,13 +489,23 @@ class HealthTraining : Inventory native
HELT A -1;
Stop;
}
override bool TryPickup (in out Actor toucher)
{
if (Super.TryPickup(toucher))
{
toucher.GiveInventoryType ("GunTraining");
toucher.A_GiveInventory("Coin", toucher.player.mo.accuracy*5 + 300);
return true;
}
return false;
}
}
// Scanner ------------------------------------------------------------------
class Scanner : PowerupGiver native
class Scanner : PowerupGiver
{
Default
{
@ -488,11 +524,25 @@ class Scanner : PowerupGiver native
PMUP AB 6;
Loop;
}
override bool Use (bool pickup)
{
if (!level.AllMap)
{
if (Owner.CheckLocalView (consoleplayer))
{
C_MidPrint("SmallFont", "$TXT_NEEDMAP");
}
return false;
}
return Super.Use (pickup);
}
}
// Prison Pass --------------------------------------------------------------
class PrisonPass : Key native
class PrisonPass : Key
{
Default
{
@ -506,6 +556,32 @@ class PrisonPass : Key native
TOKN A -1;
Stop;
}
override bool TryPickup (in out Actor toucher)
{
Super.TryPickup (toucher);
Door_Open(223, 16);
toucher.GiveInventoryType ("QuestItem10");
return true;
}
//============================================================================
//
// APrisonPass :: SpecialDropAction
//
// Trying to make a monster that drops a prison pass turns it into an
// OpenDoor223 item instead. That means the only way to get it in Strife
// is through dialog, which is why it doesn't have its own sprite.
//
//============================================================================
override bool SpecialDropAction (Actor dropper)
{
Door_Open(223, 16);
Destroy ();
return true;
}
}
//---------------------------------------------------------------------------
@ -513,7 +589,7 @@ class PrisonPass : Key native
// actions and cannot be held. ----------------------------------------------
//---------------------------------------------------------------------------
class DummyStrifeItem : Inventory native
class DummyStrifeItem : Inventory
{
States
{
@ -525,73 +601,221 @@ class DummyStrifeItem : Inventory native
// Sound the alarm! ---------------------------------------------------------
class RaiseAlarm : DummyStrifeItem native
class RaiseAlarm : DummyStrifeItem
{
Default
{
Tag "$TAG_ALARM";
}
override bool TryPickup (in out Actor toucher)
{
toucher.NoiseAlert (toucher);
ThinkerIterator it = ThinkerIterator.Create("AlienSpectre3");
Actor spectre = Actor(it.Next());
if (spectre != NULL && spectre.health > 0 && toucher != spectre)
{
spectre.CurSector.SoundTarget = spectre.LastHeard = toucher;
spectre.target = toucher;
spectre.SetState (spectre.SeeState);
}
GoAwayAndDie ();
return true;
}
override bool SpecialDropAction (Actor dropper)
{
if (dropper.target != null)
{
dropper.target.NoiseAlert(dropper.target);
if (dropper.target.CheckLocalView(consoleplayer))
{
A_Log("You Fool! You've set off the alarm.");
}
}
Destroy ();
return true;
}
}
// Open door tag 222 --------------------------------------------------------
class OpenDoor222 : DummyStrifeItem native
class OpenDoor222 : DummyStrifeItem
{
override bool TryPickup (in out Actor toucher)
{
Door_Open(222, 16);
GoAwayAndDie ();
return true;
}
}
// Close door tag 222 -------------------------------------------------------
class CloseDoor222 : DummyStrifeItem native
class CloseDoor222 : DummyStrifeItem
{
override bool TryPickup (in out Actor toucher)
{
Door_Close(222, 16);
GoAwayAndDie ();
return true;
}
override bool SpecialDropAction (Actor dropper)
{
Door_Close(222, 16);
if (dropper.target != null)
{
if (dropper.target.CheckLocalView(consoleplayer))
{
A_Log("You're dead! You set off the alarm.");
}
dropper.target.NoiseAlert(dropper.target);
}
Destroy ();
return true;
}
}
// Open door tag 224 --------------------------------------------------------
class OpenDoor224 : DummyStrifeItem native
class OpenDoor224 : DummyStrifeItem
{
override bool TryPickup (in out Actor toucher)
{
Door_Open(224, 16);
GoAwayAndDie ();
return true;
}
override bool SpecialDropAction (Actor dropper)
{
Door_Open(224, 16);
Destroy ();
return true;
}
}
// Ammo ---------------------------------------------------------------------
class AmmoFillup : DummyStrifeItem native
class AmmoFillup : DummyStrifeItem
{
Default
{
Tag "$TAG_AMMOFILLUP";
}
override bool TryPickup (in out Actor toucher)
{
Inventory item = toucher.FindInventory("ClipOfBullets");
if (item == NULL)
{
item = toucher.GiveInventoryType ("ClipOfBullets");
if (item != NULL)
{
item.Amount = 50;
}
}
else if (item.Amount < 50)
{
item.Amount = 50;
}
else
{
return false;
}
GoAwayAndDie ();
return true;
}
}
// Health -------------------------------------------------------------------
class HealthFillup : DummyStrifeItem native
class HealthFillup : DummyStrifeItem
{
Default
{
Tag "$TAG_HEALTHFILLUP";
}
override bool TryPickup (in out Actor toucher)
{
static const int skillhealths[] = { -100, -75, -50, -50, -100 };
int index = clamp(skill, 0,4);
if (!toucher.GiveBody (skillhealths[index]))
{
return false;
}
GoAwayAndDie ();
return true;
}
}
// Upgrade Stamina ----------------------------------------------------------
class UpgradeStamina : DummyStrifeItem native
class UpgradeStamina : DummyStrifeItem
{
Default
{
Inventory.Amount 10;
Inventory.MaxAmount 100;
}
override bool TryPickup (in out Actor toucher)
{
if (toucher.player == NULL)
return false;
toucher.player.mo.stamina += Amount;
if (toucher.player.mo.stamina >= MaxAmount)
toucher.player.mo.stamina = MaxAmount;
toucher.GiveBody (-100);
GoAwayAndDie ();
return true;
}
}
// Upgrade Accuracy ---------------------------------------------------------
class UpgradeAccuracy : DummyStrifeItem native
class UpgradeAccuracy : DummyStrifeItem
{
override bool TryPickup (in out Actor toucher)
{
if (toucher.player == NULL || toucher.player.mo.accuracy >= 100)
return false;
toucher.player.mo.accuracy += 10;
GoAwayAndDie ();
return true;
}
}
// Start a slideshow --------------------------------------------------------
class SlideshowStarter : DummyStrifeItem native
class SlideshowStarter : DummyStrifeItem
{
override bool TryPickup (in out Actor toucher)
{
gameaction = ga_slideshow;
if (level.levelnum == 10)
{
toucher.GiveInventoryType ("QuestItem17");
}
GoAwayAndDie ();
return true;
}
}