mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 14:51:51 +00:00
Merge branch 'zscript' of https://github.com/rheit/zdoom into gz-zscript
# Conflicts: # wadsrc/static/zscript.txt
This commit is contained in:
commit
fbc8d0e83c
93 changed files with 1312 additions and 994 deletions
|
@ -473,6 +473,11 @@ static AMColorset AMMod;
|
|||
static AMColorset AMModOverlay;
|
||||
|
||||
|
||||
void AM_ClearColorsets()
|
||||
{
|
||||
AMModOverlay.defined = false;
|
||||
AMMod.defined = false;
|
||||
}
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
@ -27,6 +27,7 @@ class FSerializer;
|
|||
|
||||
|
||||
void AM_StaticInit();
|
||||
void AM_ClearColorsets(); // reset data for a restart.
|
||||
|
||||
// Called by main loop.
|
||||
bool AM_Responder (event_t* ev, bool last);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "cmdlib.h"
|
||||
#include "i_system.h"
|
||||
#include "v_text.h"
|
||||
#include "sc_man.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -324,7 +325,7 @@ FString ExtractFileBase (const char *path, bool include_extension)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int ParseHex (const char *hex)
|
||||
int ParseHex (const char *hex, FScriptPosition *sc)
|
||||
{
|
||||
const char *str;
|
||||
int num;
|
||||
|
@ -342,7 +343,8 @@ int ParseHex (const char *hex)
|
|||
else if (*str >= 'A' && *str <= 'F')
|
||||
num += 10 + *str-'A';
|
||||
else {
|
||||
Printf ("Bad hex number: %s\n",hex);
|
||||
if (!sc) Printf ("Bad hex number: %s\n",hex);
|
||||
else sc->Message(MSG_WARNING, "Bad hex number: %s", hex);
|
||||
return 0;
|
||||
}
|
||||
str++;
|
||||
|
@ -351,21 +353,6 @@ int ParseHex (const char *hex)
|
|||
return num;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ParseNum
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int ParseNum (const char *str)
|
||||
{
|
||||
if (str[0] == '$')
|
||||
return ParseHex (str+1);
|
||||
if (str[0] == '0' && str[1] == 'x')
|
||||
return ParseHex (str+2);
|
||||
return atol (str);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// IsNum
|
||||
|
|
|
@ -33,8 +33,8 @@ void DefaultExtension (FString &path, const char *extension);
|
|||
FString ExtractFilePath (const char *path);
|
||||
FString ExtractFileBase (const char *path, bool keep_extension=false);
|
||||
|
||||
int ParseHex (const char *str);
|
||||
int ParseNum (const char *str);
|
||||
struct FScriptPosition;
|
||||
int ParseHex(const char *str, FScriptPosition *sc = nullptr);
|
||||
bool IsNum (const char *str); // [RH] added
|
||||
|
||||
char *copystring(const char *s);
|
||||
|
|
|
@ -3020,6 +3020,7 @@ void FinishDehPatch ()
|
|||
while (subclass == nullptr);
|
||||
|
||||
AActor *defaults2 = GetDefaultByType (subclass);
|
||||
memcpy ((void *)defaults2, (void *)defaults1, sizeof(AActor));
|
||||
|
||||
// Make a copy of the replaced class's state labels
|
||||
FStateDefinitions statedef;
|
||||
|
|
|
@ -193,10 +193,10 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize)
|
|||
{
|
||||
sc.MustGetStringName("=");
|
||||
sc.MustGetString();
|
||||
iwad->FgColor = V_GetColor(NULL, sc.String);
|
||||
iwad->FgColor = V_GetColor(NULL, sc);
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
iwad->BkColor = V_GetColor(NULL, sc.String);
|
||||
iwad->BkColor = V_GetColor(NULL, sc);
|
||||
}
|
||||
else if (sc.Compare("Load"))
|
||||
{
|
||||
|
|
|
@ -1027,6 +1027,12 @@ void D_DoomLoop ()
|
|||
}
|
||||
D_ErrorCleanup ();
|
||||
}
|
||||
catch (CVMAbortException &error)
|
||||
{
|
||||
error.MaybePrintMessage();
|
||||
Printf("%s", error.stacktrace);
|
||||
D_ErrorCleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1838,10 +1844,10 @@ static FString ParseGameInfo(TArray<FString> &pwads, const char *fn, const char
|
|||
else if (!nextKey.CompareNoCase("STARTUPCOLORS"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
DoomStartupInfo.FgColor = V_GetColor(NULL, sc.String);
|
||||
DoomStartupInfo.FgColor = V_GetColor(NULL, sc);
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
DoomStartupInfo.BkColor = V_GetColor(NULL, sc.String);
|
||||
DoomStartupInfo.BkColor = V_GetColor(NULL, sc);
|
||||
}
|
||||
else if (!nextKey.CompareNoCase("STARTUPTYPE"))
|
||||
{
|
||||
|
@ -2592,44 +2598,48 @@ void D_DoomMain (void)
|
|||
G_DeferedPlayDemo (v);
|
||||
D_DoomLoop (); // never returns
|
||||
}
|
||||
|
||||
v = Args->CheckValue ("-timedemo");
|
||||
if (v)
|
||||
else
|
||||
{
|
||||
G_TimeDemo (v);
|
||||
D_DoomLoop (); // never returns
|
||||
}
|
||||
|
||||
if (gameaction != ga_loadgame && gameaction != ga_loadgamehidecon)
|
||||
{
|
||||
if (autostart || netgame)
|
||||
v = Args->CheckValue("-timedemo");
|
||||
if (v)
|
||||
{
|
||||
// Do not do any screenwipes when autostarting a game.
|
||||
if (!Args->CheckParm("-warpwipe"))
|
||||
{
|
||||
NoWipe = TICRATE;
|
||||
}
|
||||
CheckWarpTransMap (startmap, true);
|
||||
if (demorecording)
|
||||
G_BeginRecording (startmap);
|
||||
G_InitNew (startmap, false);
|
||||
if (StoredWarp.IsNotEmpty())
|
||||
{
|
||||
AddCommandString(StoredWarp.LockBuffer());
|
||||
StoredWarp = NULL;
|
||||
}
|
||||
G_TimeDemo(v);
|
||||
D_DoomLoop(); // never returns
|
||||
}
|
||||
else
|
||||
{
|
||||
D_StartTitle (); // start up intro loop
|
||||
if (gameaction != ga_loadgame && gameaction != ga_loadgamehidecon)
|
||||
{
|
||||
if (autostart || netgame)
|
||||
{
|
||||
// Do not do any screenwipes when autostarting a game.
|
||||
if (!Args->CheckParm("-warpwipe"))
|
||||
{
|
||||
NoWipe = TICRATE;
|
||||
}
|
||||
CheckWarpTransMap(startmap, true);
|
||||
if (demorecording)
|
||||
G_BeginRecording(startmap);
|
||||
G_InitNew(startmap, false);
|
||||
if (StoredWarp.IsNotEmpty())
|
||||
{
|
||||
AddCommandString(StoredWarp.LockBuffer());
|
||||
StoredWarp = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
D_StartTitle(); // start up intro loop
|
||||
}
|
||||
}
|
||||
else if (demorecording)
|
||||
{
|
||||
G_BeginRecording(NULL);
|
||||
}
|
||||
|
||||
atterm(D_QuitNetGame); // killough
|
||||
}
|
||||
}
|
||||
else if (demorecording)
|
||||
{
|
||||
G_BeginRecording (NULL);
|
||||
}
|
||||
|
||||
atterm (D_QuitNetGame); // killough
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2643,7 +2653,7 @@ void D_DoomMain (void)
|
|||
}
|
||||
|
||||
D_DoomLoop (); // this only returns if a 'restart' CCMD is given.
|
||||
|
||||
maxberestart:
|
||||
//
|
||||
// Clean up after a restart
|
||||
//
|
||||
|
@ -2654,6 +2664,7 @@ void D_DoomMain (void)
|
|||
|
||||
M_ClearMenus(); // close menu if open
|
||||
F_EndFinale(); // If an intermission is active, end it now
|
||||
AM_ClearColorsets();
|
||||
|
||||
// clean up game state
|
||||
ST_Clear();
|
||||
|
|
|
@ -81,7 +81,6 @@ public:
|
|||
FPlayerColorSet *GetColorSet(int setnum) { return ColorSets.CheckKey(setnum); }
|
||||
void SetPainFlash(FName type, PalEntry color);
|
||||
bool GetPainFlash(FName type, PalEntry *color) const;
|
||||
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
|
||||
|
||||
FString DisplayName; // Display name (used in menus, etc.)
|
||||
FString SoundClass; // Sound class
|
||||
|
|
|
@ -532,7 +532,7 @@ void FDecalLib::ParseDecal (FScanner &sc)
|
|||
sc.MustGetString ();
|
||||
if (!sc.Compare("BloodDefault"))
|
||||
{
|
||||
newdecal.ShadeColor = V_GetColor (NULL, sc.String);
|
||||
newdecal.ShadeColor = V_GetColor (NULL, sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -547,8 +547,8 @@ void FDecalLib::ParseDecal (FScanner &sc)
|
|||
case DECAL_COLORS:
|
||||
DWORD startcolor, endcolor;
|
||||
|
||||
sc.MustGetString (); startcolor = V_GetColor (NULL, sc.String);
|
||||
sc.MustGetString (); endcolor = V_GetColor (NULL, sc.String);
|
||||
sc.MustGetString (); startcolor = V_GetColor (NULL, sc);
|
||||
sc.MustGetString (); endcolor = V_GetColor (NULL, sc);
|
||||
newdecal.Translation = GenerateTranslation (startcolor, endcolor)->Index;
|
||||
break;
|
||||
|
||||
|
@ -819,7 +819,7 @@ void FDecalLib::ParseColorchanger (FScanner &sc)
|
|||
else if (sc.Compare ("Color"))
|
||||
{
|
||||
sc.MustGetString ();
|
||||
goal = V_GetColor (NULL, sc.String);
|
||||
goal = V_GetColor (NULL, sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -423,7 +423,7 @@ size_t DObject::PointerSubstitution (DObject *old, DObject *notOld)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld)
|
||||
size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld, bool scandefaults)
|
||||
{
|
||||
DObject *probe;
|
||||
size_t changed = 0;
|
||||
|
@ -438,6 +438,20 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld)
|
|||
last = probe;
|
||||
}
|
||||
|
||||
if (scandefaults)
|
||||
{
|
||||
for (auto p : PClassActor::AllActorClasses)
|
||||
{
|
||||
auto def = GetDefaultByType(p);
|
||||
if (def != nullptr)
|
||||
{
|
||||
def->Class = p;
|
||||
def->DObject::PointerSubstitution(old, notOld);
|
||||
def->Class = nullptr; // reset pointer. Defaults should not have a valid class pointer.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Go through the bodyque.
|
||||
for (i = 0; i < BODYQUESIZE; ++i)
|
||||
{
|
||||
|
|
|
@ -482,7 +482,7 @@ public:
|
|||
// change any pointers from the old object to the new object,
|
||||
// use this method.
|
||||
virtual size_t PointerSubstitution (DObject *old, DObject *notOld);
|
||||
static size_t StaticPointerSubstitution (DObject *old, DObject *notOld);
|
||||
static size_t StaticPointerSubstitution (DObject *old, DObject *notOld, bool scandefaults = false);
|
||||
|
||||
PClass *GetClass() const
|
||||
{
|
||||
|
|
|
@ -3008,8 +3008,6 @@ PClass *ClassReg::RegisterClass()
|
|||
&PClassPlayerPawn::RegistrationInfo,
|
||||
&PClassType::RegistrationInfo,
|
||||
&PClassClass::RegistrationInfo,
|
||||
&PClassWeaponPiece::RegistrationInfo,
|
||||
&PClassPowerupGiver::RegistrationInfo,
|
||||
};
|
||||
|
||||
// Skip classes that have already been registered
|
||||
|
@ -3332,15 +3330,15 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
|
|||
}
|
||||
else
|
||||
{
|
||||
PClassActor::AllActorClasses.Pop(); // remove the newly added class from the list
|
||||
// todo: replace all affected fields
|
||||
for (unsigned i = 0; i < PClassActor::AllActorClasses.Size(); i++)
|
||||
{
|
||||
PClassActor::AllActorClasses[i]->ReplaceClassRef(existclass, type);
|
||||
if (PClassActor::AllActorClasses[i] == existclass)
|
||||
PClassActor::AllActorClasses[i] = static_cast<PClassActor*>(type);
|
||||
}
|
||||
TypeTable.ReplaceType(type, existclass, bucket);
|
||||
StaticPointerSubstitution(existclass, type, true); // replace the old one, also in the actor defaults.
|
||||
// Delete the old class from the class lists, both the full one and the actor list.
|
||||
auto index = PClassActor::AllActorClasses.Find(static_cast<PClassActor*>(existclass));
|
||||
if (index < PClassActor::AllActorClasses.Size()) PClassActor::AllActorClasses.Delete(index);
|
||||
index = PClass::AllClasses.Find(existclass);
|
||||
if (index < PClass::AllClasses.Size()) PClass::AllClasses.Delete(index);
|
||||
// Now we can destroy the old class as nothing should reference it anymore
|
||||
existclass->Destroy();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,12 @@ public:
|
|||
strncpy (m_Message, message, MAX_ERRORTEXT-1);
|
||||
m_Message[MAX_ERRORTEXT-1] = '\0';
|
||||
}
|
||||
void AppendMessage(const char *message)
|
||||
{
|
||||
size_t len = strlen(m_Message);
|
||||
strncpy(m_Message + len, message, MAX_ERRORTEXT - 1 - len);
|
||||
m_Message[MAX_ERRORTEXT - 1] = '\0';
|
||||
}
|
||||
const char *GetMessage (void) const
|
||||
{
|
||||
if (m_Message[0] != '\0')
|
||||
|
@ -64,7 +70,7 @@ public:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
protected:
|
||||
char m_Message[MAX_ERRORTEXT];
|
||||
};
|
||||
|
||||
|
|
|
@ -2014,13 +2014,13 @@ void FParser::SF_CeilingTexture(void)
|
|||
|
||||
void FParser::SF_ChangeHubLevel(void)
|
||||
{
|
||||
I_Error("FS hub system permanently disabled\n");
|
||||
script_error("FS hub system permanently disabled\n");
|
||||
}
|
||||
|
||||
// for start map: start new game on a particular skill
|
||||
void FParser::SF_StartSkill(void)
|
||||
{
|
||||
I_Error("startskill is not supported by this implementation!\n");
|
||||
script_error("startskill is not supported by this implementation!\n");
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -113,7 +113,7 @@ void FParser::NextToken()
|
|||
}
|
||||
if(!Section)
|
||||
{
|
||||
I_Error("section not found!\n");
|
||||
script_error("section not found!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -708,6 +708,18 @@ void FParser::EvaluateExpression(svalue_t &result, int start, int stop)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FS_Error(const char *error, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char errortext[MAX_ERRORTEXT];
|
||||
|
||||
va_start(argptr, error);
|
||||
myvsnprintf(errortext, MAX_ERRORTEXT, error, argptr);
|
||||
va_end(argptr);
|
||||
throw CFraggleScriptError(errortext);
|
||||
}
|
||||
|
||||
|
||||
void FParser::ErrorMessage(FString msg)
|
||||
{
|
||||
int linenum = 0;
|
||||
|
@ -721,7 +733,7 @@ void FParser::ErrorMessage(FString msg)
|
|||
}
|
||||
|
||||
//lineinfo.Format("Script %d, line %d: ", Script->scriptnum, linenum);
|
||||
I_Error("Script %d, line %d: %s", Script->scriptnum, linenum, msg.GetChars());
|
||||
FS_Error("Script %d, line %d: %s", Script->scriptnum, linenum, msg.GetChars());
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -251,7 +251,7 @@ void DFsScript::ParseScript(char *position)
|
|||
FParser parse(this);
|
||||
parse.Run(position, data, data + len);
|
||||
}
|
||||
catch (CRecoverableError &err)
|
||||
catch (CFraggleScriptError &err)
|
||||
{
|
||||
Printf ("%s\n", err.GetMessage());
|
||||
}
|
||||
|
|
|
@ -41,12 +41,22 @@
|
|||
#include "p_lnspec.h"
|
||||
#include "m_fixed.h"
|
||||
#include "actor.h"
|
||||
#include "doomerrors.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// This pragma saves 8kb of wasted code.
|
||||
#pragma pointers_to_members( full_generality, single_inheritance )
|
||||
#endif
|
||||
|
||||
|
||||
class CFraggleScriptError : public CDoomError
|
||||
{
|
||||
public:
|
||||
CFraggleScriptError() : CDoomError() {}
|
||||
CFraggleScriptError(const char *message) : CDoomError(message) {}
|
||||
};
|
||||
|
||||
|
||||
class DRunningScript;
|
||||
|
||||
|
||||
|
|
|
@ -45,19 +45,12 @@ IMPLEMENT_CLASS(APowerup, false, false)
|
|||
|
||||
// Powerup-Giver -------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CLASS(PClassPowerupGiver, false, false)
|
||||
|
||||
void PClassPowerupGiver::ReplaceClassRef(PClass *oldclass, PClass *newclass)
|
||||
{
|
||||
Super::ReplaceClassRef(oldclass, newclass);
|
||||
APowerupGiver *def = (APowerupGiver*)Defaults;
|
||||
if (def != NULL)
|
||||
{
|
||||
if (def->PowerupType == oldclass) def->PowerupType = static_cast<PClassWeapon *>(newclass);
|
||||
}
|
||||
}
|
||||
IMPLEMENT_CLASS(APowerupGiver, false, true)
|
||||
|
||||
IMPLEMENT_CLASS(APowerupGiver, false, false)
|
||||
IMPLEMENT_POINTERS_START(APowerupGiver)
|
||||
IMPLEMENT_POINTER(PowerupType)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
DEFINE_FIELD(APowerupGiver, PowerupType)
|
||||
DEFINE_FIELD(APowerupGiver, EffectTics)
|
||||
|
@ -1855,7 +1848,14 @@ void APowerDoubleFiringSpeed::EndEffect( )
|
|||
|
||||
// Morph powerup ------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CLASS(APowerMorph, false, false)
|
||||
IMPLEMENT_CLASS(APowerMorph, false, true)
|
||||
|
||||
IMPLEMENT_POINTERS_START(APowerMorph)
|
||||
IMPLEMENT_POINTER(PlayerClass)
|
||||
IMPLEMENT_POINTER(MorphFlash)
|
||||
IMPLEMENT_POINTER(UnMorphFlash)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
|
||||
DEFINE_FIELD(APowerMorph, PlayerClass)
|
||||
DEFINE_FIELD(APowerMorph, MorphFlash)
|
||||
|
@ -1916,19 +1916,12 @@ void APowerMorph::EndEffect( )
|
|||
{
|
||||
Super::EndEffect();
|
||||
|
||||
// Abort if owner already destroyed
|
||||
if (Owner == NULL)
|
||||
// Abort if owner already destroyed or unmorphed
|
||||
if (Owner == nullptr || MorphedPlayer == nullptr)
|
||||
{
|
||||
assert(MorphedPlayer == NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
// Abort if owner already unmorphed
|
||||
if (MorphedPlayer == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Abort if owner is dead; their Die() method will
|
||||
// take care of any required unmorphing on death.
|
||||
if (MorphedPlayer->health <= 0)
|
||||
|
|
|
@ -35,19 +35,11 @@ protected:
|
|||
friend void InitAllPowerupEffects(AInventory *item);
|
||||
};
|
||||
|
||||
class PClassPowerupGiver: public PClassInventory
|
||||
{
|
||||
DECLARE_CLASS(PClassPowerupGiver, PClassInventory)
|
||||
protected:
|
||||
public:
|
||||
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
|
||||
};
|
||||
|
||||
|
||||
// An artifact is an item that gives the player a powerup when activated.
|
||||
class APowerupGiver : public AInventory
|
||||
{
|
||||
DECLARE_CLASS_WITH_META (APowerupGiver, AInventory, PClassPowerupGiver)
|
||||
DECLARE_CLASS (APowerupGiver, AInventory)
|
||||
HAS_OBJECT_POINTERS
|
||||
public:
|
||||
virtual bool Use (bool pickup) override;
|
||||
virtual void Serialize(FSerializer &arc) override;
|
||||
|
@ -272,6 +264,7 @@ protected:
|
|||
class APowerMorph : public APowerup
|
||||
{
|
||||
DECLARE_CLASS( APowerMorph, APowerup )
|
||||
HAS_OBJECT_POINTERS
|
||||
public:
|
||||
|
||||
virtual void Serialize(FSerializer &arc) override;
|
||||
|
|
|
@ -45,9 +45,9 @@ void PClassInventory::DeriveData(PClass *newclass)
|
|||
newc->RestrictedToPlayerClass = RestrictedToPlayerClass;
|
||||
}
|
||||
|
||||
void PClassInventory::ReplaceClassRef(PClass *oldclass, PClass *newclass)
|
||||
size_t PClassInventory::PointerSubstitution(DObject *oldclass, DObject *newclass)
|
||||
{
|
||||
Super::ReplaceClassRef(oldclass, newclass);
|
||||
size_t changed = Super::PointerSubstitution(oldclass, newclass);
|
||||
AInventory *def = (AInventory*)Defaults;
|
||||
if (def != NULL)
|
||||
{
|
||||
|
@ -55,14 +55,21 @@ void PClassInventory::ReplaceClassRef(PClass *oldclass, PClass *newclass)
|
|||
for (unsigned i = 0; i < ForbiddenToPlayerClass.Size(); i++)
|
||||
{
|
||||
if (ForbiddenToPlayerClass[i] == oldclass)
|
||||
{
|
||||
ForbiddenToPlayerClass[i] = static_cast<PClassPlayerPawn*>(newclass);
|
||||
changed++;
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < RestrictedToPlayerClass.Size(); i++)
|
||||
{
|
||||
if (RestrictedToPlayerClass[i] == oldclass)
|
||||
{
|
||||
RestrictedToPlayerClass[i] = static_cast<PClassPlayerPawn*>(newclass);
|
||||
changed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
void PClassInventory::Finalize(FStateDefinitions &statedef)
|
||||
|
@ -254,7 +261,7 @@ bool AInventory::SpecialDropAction (AActor *dropper)
|
|||
DEFINE_ACTION_FUNCTION(AInventory, SpecialDropAction)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
PARAM_OBJECT(dropper, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(dropper, AActor);
|
||||
ACTION_RETURN_BOOL(self->SpecialDropAction(dropper));
|
||||
}
|
||||
|
||||
|
@ -422,7 +429,7 @@ bool AInventory::HandlePickup (AInventory *item)
|
|||
DEFINE_ACTION_FUNCTION(AInventory, HandlePickup)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
PARAM_OBJECT(item, AInventory);
|
||||
PARAM_OBJECT_NOT_NULL(item, AInventory);
|
||||
ACTION_RETURN_BOOL(self->HandlePickup(item));
|
||||
}
|
||||
|
||||
|
@ -1409,7 +1416,7 @@ bool AInventory::TryPickup (AActor *&toucher)
|
|||
DEFINE_ACTION_FUNCTION(AInventory, TryPickup)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
PARAM_POINTER(toucher, AActor*);
|
||||
PARAM_POINTER_NOT_NULL(toucher, AActor*);
|
||||
ACTION_RETURN_BOOL(self->TryPickup(*toucher));
|
||||
}
|
||||
|
||||
|
@ -1427,7 +1434,7 @@ bool AInventory::TryPickupRestricted (AActor *&toucher)
|
|||
DEFINE_ACTION_FUNCTION(AInventory, TryPickupRestricted)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
PARAM_POINTER(toucher, AActor*);
|
||||
PARAM_POINTER_NOT_NULL(toucher, AActor*);
|
||||
ACTION_RETURN_BOOL(self->TryPickupRestricted(*toucher));
|
||||
}
|
||||
|
||||
|
@ -1606,7 +1613,7 @@ void AInventory::AttachToOwner (AActor *other)
|
|||
DEFINE_ACTION_FUNCTION(AInventory, AttachToOwner)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
PARAM_OBJECT(other, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(other, AActor);
|
||||
self->AttachToOwner(other);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ class PClassInventory : public PClassActor
|
|||
public:
|
||||
PClassInventory();
|
||||
virtual void DeriveData(PClass *newclass);
|
||||
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
|
||||
virtual size_t PointerSubstitution(DObject *oldclass, DObject *newclass);
|
||||
void Finalize(FStateDefinitions &statedef);
|
||||
|
||||
FString PickupMessage;
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include "doomstat.h"
|
||||
#include "serializer.h"
|
||||
|
||||
IMPLEMENT_CLASS(PClassWeaponPiece, false, false)
|
||||
IMPLEMENT_CLASS(AWeaponHolder, false, false)
|
||||
|
||||
DEFINE_FIELD(AWeaponHolder, PieceMask);
|
||||
|
@ -50,22 +49,6 @@ DEFINE_FIELD(AWeaponHolder, PieceWeapon);
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
void PClassWeaponPiece::ReplaceClassRef(PClass *oldclass, PClass *newclass)
|
||||
{
|
||||
Super::ReplaceClassRef(oldclass, newclass);
|
||||
AWeaponPiece *def = (AWeaponPiece*)Defaults;
|
||||
if (def != NULL)
|
||||
{
|
||||
if (def->WeaponClass == oldclass) def->WeaponClass = static_cast<PClassWeapon *>(newclass);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void AWeaponHolder::Serialize(FSerializer &arc)
|
||||
{
|
||||
Super::Serialize(arc);
|
||||
|
@ -77,6 +60,7 @@ IMPLEMENT_CLASS(AWeaponPiece, false, true)
|
|||
|
||||
IMPLEMENT_POINTERS_START(AWeaponPiece)
|
||||
IMPLEMENT_POINTER(FullWeapon)
|
||||
IMPLEMENT_POINTER(WeaponClass)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -2,18 +2,9 @@
|
|||
#include "a_pickups.h"
|
||||
#include "a_weapons.h"
|
||||
|
||||
//
|
||||
class PClassWeaponPiece : public PClassInventory
|
||||
{
|
||||
DECLARE_CLASS(PClassWeaponPiece, PClassInventory)
|
||||
protected:
|
||||
public:
|
||||
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
|
||||
};
|
||||
|
||||
class AWeaponPiece : public AInventory
|
||||
{
|
||||
DECLARE_CLASS_WITH_META(AWeaponPiece, AInventory, PClassWeaponPiece)
|
||||
DECLARE_CLASS(AWeaponPiece, AInventory)
|
||||
HAS_OBJECT_POINTERS
|
||||
protected:
|
||||
bool PrivateShouldStay ();
|
||||
|
|
|
@ -66,6 +66,9 @@ IMPLEMENT_POINTERS_START(AWeapon)
|
|||
IMPLEMENT_POINTER(Ammo1)
|
||||
IMPLEMENT_POINTER(Ammo2)
|
||||
IMPLEMENT_POINTER(SisterWeapon)
|
||||
IMPLEMENT_POINTER(AmmoType1)
|
||||
IMPLEMENT_POINTER(AmmoType2)
|
||||
IMPLEMENT_POINTER(SisterWeaponType)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
DEFINE_FIELD(AWeapon, WeaponFlags)
|
||||
|
@ -148,24 +151,6 @@ void PClassWeapon::DeriveData(PClass *newclass)
|
|||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void PClassWeapon::ReplaceClassRef(PClass *oldclass, PClass *newclass)
|
||||
{
|
||||
Super::ReplaceClassRef(oldclass, newclass);
|
||||
AWeapon *def = (AWeapon*)Defaults;
|
||||
if (def != NULL)
|
||||
{
|
||||
if (def->AmmoType1 == oldclass) def->AmmoType1 = static_cast<PClassAmmo *>(newclass);
|
||||
if (def->AmmoType2 == oldclass) def->AmmoType2 = static_cast<PClassAmmo *>(newclass);
|
||||
if (def->SisterWeaponType == oldclass) def->SisterWeaponType = static_cast<PClassWeapon *>(newclass);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
@ -95,7 +95,6 @@ protected:
|
|||
virtual void DeriveData(PClass *newclass);
|
||||
public:
|
||||
PClassWeapon();
|
||||
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
|
||||
void Finalize(FStateDefinitions &statedef);
|
||||
|
||||
int SlotNumber;
|
||||
|
|
|
@ -860,14 +860,14 @@ DEFINE_MAP_OPTION(fade, true)
|
|||
{
|
||||
parse.ParseAssign();
|
||||
parse.sc.MustGetString();
|
||||
info->fadeto = V_GetColor(NULL, parse.sc.String);
|
||||
info->fadeto = V_GetColor(NULL, parse.sc);
|
||||
}
|
||||
|
||||
DEFINE_MAP_OPTION(outsidefog, true)
|
||||
{
|
||||
parse.ParseAssign();
|
||||
parse.sc.MustGetString();
|
||||
info->outsidefog = V_GetColor(NULL, parse.sc.String);
|
||||
info->outsidefog = V_GetColor(NULL, parse.sc);
|
||||
}
|
||||
|
||||
DEFINE_MAP_OPTION(titlepatch, true)
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "r_data/r_translate.h"
|
||||
|
||||
static FRandom pr_freezedeath ("FreezeDeath");
|
||||
static FRandom pr_icesettics ("IceSetTics");
|
||||
static FRandom pr_freeze ("FreezeDeathChunks");
|
||||
|
||||
|
||||
|
@ -121,36 +120,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeath)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_IceSetTics
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void IceSetTics(AActor *self)
|
||||
{
|
||||
|
||||
int floor;
|
||||
|
||||
self->tics = 70 + (pr_icesettics() & 63);
|
||||
floor = P_GetThingFloorType(self);
|
||||
if (Terrains[floor].DamageMOD == NAME_Fire)
|
||||
{
|
||||
self->tics >>= 2;
|
||||
}
|
||||
else if (Terrains[floor].DamageMOD == NAME_Ice)
|
||||
{
|
||||
self->tics <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_IceSetTics)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
IceSetTics(self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_FreezeDeathChunks
|
||||
|
@ -193,7 +162,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeathChunks)
|
|||
mo->Vel.X = pr_freeze.Random2() / 128.;
|
||||
mo->Vel.Y = pr_freeze.Random2() / 128.;
|
||||
mo->Vel.Z = (mo->Z() - self->Z()) / self->Height * 4;
|
||||
IceSetTics(mo); // set a random tic wait
|
||||
mo->RenderStyle = self->RenderStyle;
|
||||
mo->Alpha = self->Alpha;
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ static void BridgeOrbit(AActor *self)
|
|||
self->ceilingz = self->target->ceilingz;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BridgeOrbit)
|
||||
DEFINE_ACTION_FUNCTION(ABridgeBall, A_BridgeOrbit)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
BridgeOrbit(self);
|
||||
|
@ -122,7 +122,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BridgeOrbit)
|
|||
}
|
||||
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BridgeInit)
|
||||
DEFINE_ACTION_FUNCTION(ACustomBridge, A_BridgeInit)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_CLASS_DEF(balltype, AActor);
|
||||
|
|
|
@ -363,7 +363,7 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag,
|
|||
DEFINE_ACTION_FUNCTION(_PlayerInfo, UndoPlayerMorph)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(player_t);
|
||||
PARAM_POINTER(player, player_t);
|
||||
PARAM_POINTER_NOT_NULL(player, player_t);
|
||||
PARAM_INT_DEF(unmorphflag);
|
||||
PARAM_BOOL_DEF(force);
|
||||
ACTION_RETURN_BOOL(P_UndoPlayerMorph(self, player, unmorphflag, force));
|
||||
|
@ -613,7 +613,14 @@ void InitAllPowerupEffects(AInventory *item)
|
|||
|
||||
// Base class for morphing projectiles --------------------------------------
|
||||
|
||||
IMPLEMENT_CLASS(AMorphProjectile, false, false)
|
||||
IMPLEMENT_CLASS(AMorphProjectile, false, true)
|
||||
|
||||
IMPLEMENT_POINTERS_START(AMorphProjectile)
|
||||
IMPLEMENT_POINTER(PlayerClass)
|
||||
IMPLEMENT_POINTER(MonsterClass)
|
||||
IMPLEMENT_POINTER(MorphFlash)
|
||||
IMPLEMENT_POINTER(UnMorphFlash)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
DEFINE_FIELD(AMorphProjectile, PlayerClass)
|
||||
DEFINE_FIELD(AMorphProjectile, MonsterClass)
|
||||
|
|
|
@ -187,6 +187,7 @@ private:
|
|||
class AMorphProjectile : public AActor
|
||||
{
|
||||
DECLARE_CLASS (AMorphProjectile, AActor)
|
||||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
int DoSpecialDamage (AActor *target, int damage, FName damagetype);
|
||||
|
||||
|
|
|
@ -265,6 +265,7 @@ DEFINE_ACTION_FUNCTION(DSpotState, GetSpotState)
|
|||
|
||||
FSpotList *DSpotState::FindSpotList(PClassActor *type)
|
||||
{
|
||||
if (type == nullptr) return nullptr;
|
||||
for(unsigned i = 0; i < SpotLists.Size(); i++)
|
||||
{
|
||||
if (SpotLists[i].Type == type) return &SpotLists[i];
|
||||
|
@ -401,10 +402,10 @@ void ASpecialSpot::Destroy()
|
|||
// will build a list of all mace spots in the level and spawn a
|
||||
// mace. The rest of the spots will do nothing.
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SpawnSingleItem)
|
||||
DEFINE_ACTION_FUNCTION(ASpecialSpot, A_SpawnSingleItem)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_CLASS (cls, AActor);
|
||||
PARAM_SELF_PROLOGUE(ASpecialSpot);
|
||||
PARAM_CLASS_NOT_NULL(cls, AActor);
|
||||
PARAM_INT_DEF (fail_sp)
|
||||
PARAM_INT_DEF (fail_co)
|
||||
PARAM_INT_DEF (fail_dm)
|
||||
|
|
44
src/info.cpp
44
src/info.cpp
|
@ -89,16 +89,35 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info,
|
|||
stateret = NULL;
|
||||
}
|
||||
}
|
||||
if (stateret == NULL)
|
||||
try
|
||||
{
|
||||
GlobalVMStack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, NULL, 0, NULL);
|
||||
if (stateret == NULL)
|
||||
{
|
||||
GlobalVMStack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, NULL, 0, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
VMReturn ret;
|
||||
ret.PointerAt((void **)stateret);
|
||||
GlobalVMStack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, 1, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (CVMAbortException &err)
|
||||
{
|
||||
VMReturn ret;
|
||||
ret.PointerAt((void **)stateret);
|
||||
GlobalVMStack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, 1, NULL);
|
||||
err.MaybePrintMessage();
|
||||
auto owner = FState::StaticFindStateOwner(this);
|
||||
int offs = int(this - owner->OwnedStates);
|
||||
const char *callinfo = "";
|
||||
if (info != nullptr && info->mStateType == STATE_Psprite)
|
||||
{
|
||||
if (stateowner->IsKindOf(RUNTIME_CLASS(AWeapon)) && stateowner != self) callinfo = "weapon ";
|
||||
else callinfo = "overlay ";
|
||||
}
|
||||
err.stacktrace.AppendFormat("Called from %sstate %s.%d in %s\n", callinfo, owner->TypeName.GetChars(), offs, stateowner->GetClass()->TypeName.GetChars());
|
||||
throw;
|
||||
throw;
|
||||
}
|
||||
|
||||
ActionCycles.Unclock();
|
||||
return true;
|
||||
}
|
||||
|
@ -619,19 +638,18 @@ void PClassActor::SetPainChance(FName type, int chance)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void PClassActor::ReplaceClassRef(PClass *oldclass, PClass *newclass)
|
||||
size_t PClassActor::PointerSubstitution(DObject *oldclass, DObject *newclass)
|
||||
{
|
||||
auto changed = Super::PointerSubstitution(oldclass, newclass);
|
||||
for (unsigned i = 0; i < VisibleToPlayerClass.Size(); i++)
|
||||
{
|
||||
if (VisibleToPlayerClass[i] == oldclass)
|
||||
{
|
||||
VisibleToPlayerClass[i] = static_cast<PClassPlayerPawn*>(newclass);
|
||||
changed++;
|
||||
}
|
||||
}
|
||||
AActor *def = (AActor*)Defaults;
|
||||
if (def != NULL)
|
||||
{
|
||||
if (def->TeleFogSourceType == oldclass) def->TeleFogSourceType = static_cast<PClassActor *>(newclass);
|
||||
if (def->TeleFogDestType == oldclass) def->TeleFogDestType = static_cast<PClassActor *>(newclass);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -248,7 +248,7 @@ public:
|
|||
PClassActor();
|
||||
~PClassActor();
|
||||
|
||||
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
|
||||
virtual size_t PointerSubstitution(DObject *oldclass, DObject *newclass);
|
||||
void BuildDefaults();
|
||||
void ApplyDefaults(BYTE *defaults);
|
||||
void RegisterIDs();
|
||||
|
|
|
@ -400,10 +400,10 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
|
|||
int y = sc.Number;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
PalEntry c1 = V_GetColor(NULL, sc.String);
|
||||
PalEntry c1 = V_GetColor(NULL, sc);
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetString();
|
||||
PalEntry c2 = V_GetColor(NULL, sc.String);
|
||||
PalEntry c2 = V_GetColor(NULL, sc);
|
||||
if (sc.CheckString(","))
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
|
|
|
@ -715,6 +715,7 @@ xx(String)
|
|||
xx(Vector)
|
||||
xx(Map)
|
||||
xx(Array)
|
||||
xx(Include)
|
||||
xx(Sound)
|
||||
xx(State)
|
||||
xx(Fixed)
|
||||
|
|
|
@ -183,7 +183,19 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState *state)
|
|||
numret = 2;
|
||||
}
|
||||
}
|
||||
GlobalVMStack.Call(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret);
|
||||
try
|
||||
{
|
||||
GlobalVMStack.Call(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret);
|
||||
}
|
||||
catch (CVMAbortException &err)
|
||||
{
|
||||
err.MaybePrintMessage();
|
||||
auto owner = FState::StaticFindStateOwner(state);
|
||||
int offs = int(state - owner->OwnedStates);
|
||||
err.stacktrace.AppendFormat("Called from state %s.%d in inventory state chain in %s\n", owner->TypeName.GetChars(), offs, GetClass()->TypeName.GetChars());
|
||||
throw;
|
||||
}
|
||||
|
||||
// As long as even one state succeeds, the whole chain succeeds unless aborted below.
|
||||
// A state that wants to jump does not count as "succeeded".
|
||||
if (nextstate == NULL)
|
||||
|
@ -247,7 +259,7 @@ DEFINE_ACTION_FUNCTION(AActor, CheckClass)
|
|||
PARAM_BOOL_DEF (match_superclass);
|
||||
|
||||
self = COPY_AAPTR(self, pick_pointer);
|
||||
if (self == NULL)
|
||||
if (self == nullptr || checktype == nullptr)
|
||||
{
|
||||
ret->SetInt(false);
|
||||
}
|
||||
|
@ -1773,9 +1785,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomComboAttack)
|
|||
// State jump function
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_JumpIfNoAmmo)
|
||||
DEFINE_ACTION_FUNCTION(AStateProvider, A_JumpIfNoAmmo)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_ACTION_PROLOGUE(AStateProvider);
|
||||
PARAM_STATE_ACTION(jump);
|
||||
|
||||
if (!ACTION_CALL_FROM_PSPRITE() || self->player->ReadyWeapon == nullptr)
|
||||
|
@ -1844,9 +1856,9 @@ static void AimBulletMissile(AActor *proj, AActor *puff, int flags, bool temp, b
|
|||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FireBullets)
|
||||
DEFINE_ACTION_FUNCTION(AStateProvider, A_FireBullets)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_ACTION_PROLOGUE(AStateProvider);
|
||||
PARAM_ANGLE (spread_xy);
|
||||
PARAM_ANGLE (spread_z);
|
||||
PARAM_INT (numbullets);
|
||||
|
@ -1974,9 +1986,9 @@ enum FP_Flags
|
|||
FPF_TRANSFERTRANSLATION = 2,
|
||||
FPF_NOAUTOAIM = 4,
|
||||
};
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FireCustomMissile)
|
||||
DEFINE_ACTION_FUNCTION(AStateProvider, A_FireCustomMissile)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_ACTION_PROLOGUE(AStateProvider);
|
||||
PARAM_CLASS (ti, AActor);
|
||||
PARAM_ANGLE_DEF (angle);
|
||||
PARAM_BOOL_DEF (useammo);
|
||||
|
@ -2051,9 +2063,9 @@ enum
|
|||
CPF_STEALARMOR = 32,
|
||||
};
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_CustomPunch)
|
||||
DEFINE_ACTION_FUNCTION(AStateProvider, A_CustomPunch)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_ACTION_PROLOGUE(AStateProvider);
|
||||
PARAM_INT (damage);
|
||||
PARAM_BOOL_DEF (norandom);
|
||||
PARAM_INT_DEF (flags);
|
||||
|
@ -2155,9 +2167,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomPunch)
|
|||
// customizable railgun attack function
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_RailAttack)
|
||||
DEFINE_ACTION_FUNCTION(AStateProvider, A_RailAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_ACTION_PROLOGUE(AStateProvider);
|
||||
PARAM_INT (damage);
|
||||
PARAM_INT_DEF (spawnofs_xy);
|
||||
PARAM_BOOL_DEF (useammo);
|
||||
|
@ -4443,9 +4455,9 @@ DEFINE_ACTION_FUNCTION(AActor, CheckIfInTargetLOS)
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_CheckForReload)
|
||||
DEFINE_ACTION_FUNCTION(AStateProvider, A_CheckForReload)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_ACTION_PROLOGUE(AStateProvider);
|
||||
|
||||
if ( self->player == NULL || self->player->ReadyWeapon == NULL )
|
||||
{
|
||||
|
@ -4496,9 +4508,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_CheckForReload)
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_ResetReloadCounter)
|
||||
DEFINE_ACTION_FUNCTION(AStateProvider, A_ResetReloadCounter)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_ACTION_PROLOGUE(AStateProvider);
|
||||
|
||||
if (self->player == NULL || self->player->ReadyWeapon == NULL)
|
||||
return 0;
|
||||
|
|
|
@ -461,7 +461,7 @@ bool P_CreateCeiling(sector_t *sec, DCeiling::ECeiling type, line_t *line, int t
|
|||
DEFINE_ACTION_FUNCTION(DCeiling, CreateCeiling)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTER(sec, sector_t);
|
||||
PARAM_POINTER_NOT_NULL(sec, sector_t);
|
||||
PARAM_INT(type);
|
||||
PARAM_POINTER(ln, line_t);
|
||||
PARAM_FLOAT(speed);
|
||||
|
|
|
@ -1307,6 +1307,11 @@ bool P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams
|
|||
double mindist;
|
||||
DAngle fov;
|
||||
|
||||
if (other == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (params != NULL)
|
||||
{
|
||||
maxdist = params->maxDist;
|
||||
|
@ -3323,15 +3328,6 @@ AInventory *P_DropItem (AActor *source, PClassActor *type, int dropamount, int c
|
|||
return NULL;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, DoDropItem)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_CLASS(cls, AActor);
|
||||
PARAM_INT(amt);
|
||||
PARAM_INT(chance);
|
||||
ACTION_RETURN_OBJECT(P_DropItem(self, cls, amt, chance));
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// P_TossItem
|
||||
|
|
|
@ -495,7 +495,7 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line,
|
|||
DEFINE_ACTION_FUNCTION(DFloor, CreateFloor)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTER(sec, sector_t);
|
||||
PARAM_POINTER_NOT_NULL(sec, sector_t);
|
||||
PARAM_INT(floortype);
|
||||
PARAM_POINTER(ln, line_t);
|
||||
PARAM_FLOAT(speed);
|
||||
|
|
|
@ -1639,7 +1639,7 @@ void P_PoisonMobj (AActor *target, AActor *inflictor, AActor *source, int damage
|
|||
DEFINE_ACTION_FUNCTION(AActor, PoisonMobj)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(inflictor, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(inflictor, AActor);
|
||||
PARAM_OBJECT(source, AActor);
|
||||
PARAM_INT(damage);
|
||||
PARAM_INT(duration);
|
||||
|
|
|
@ -4513,6 +4513,7 @@ DEFINE_ACTION_FUNCTION(AActor, LineAttack)
|
|||
PARAM_POINTER_DEF(victim, FTranslatedLineTarget);
|
||||
|
||||
int acdmg;
|
||||
if (puffType == nullptr) puffType = PClass::FindActor("BulletPuff"); // P_LineAttack does not work without a puff to take info from.
|
||||
auto puff = P_LineAttack(self, angle, distance, pitch, damage, damageType, puffType, flags, victim, &acdmg);
|
||||
if (numret > 0) ret[0].SetPointer(puff, ATAG_OBJECT);
|
||||
if (numret > 1) ret[1].SetInt(acdmg), numret = 2;
|
||||
|
@ -4716,7 +4717,7 @@ DEFINE_ACTION_FUNCTION(_FTranslatedLineTarget, TraceBleed)
|
|||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FTranslatedLineTarget);
|
||||
PARAM_INT(damage);
|
||||
PARAM_OBJECT(missile, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(missile, AActor);
|
||||
|
||||
P_TraceBleed(damage, self, missile);
|
||||
return 0;
|
||||
|
|
|
@ -1193,7 +1193,7 @@ IMPLEMENT_CLASS(DBlockThingsIterator, false, false);
|
|||
DEFINE_ACTION_FUNCTION(DBlockThingsIterator, Create)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_OBJECT(origin, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(origin, AActor);
|
||||
PARAM_FLOAT_DEF(radius);
|
||||
PARAM_BOOL_DEF(ignore);
|
||||
ACTION_RETURN_OBJECT(new DBlockThingsIterator(origin, radius, ignore));
|
||||
|
|
165
src/p_mobj.cpp
165
src/p_mobj.cpp
|
@ -145,6 +145,8 @@ IMPLEMENT_POINTERS_START(AActor)
|
|||
IMPLEMENT_POINTER(Poisoner)
|
||||
IMPLEMENT_POINTER(DamageFunc)
|
||||
IMPLEMENT_POINTER(alternative)
|
||||
IMPLEMENT_POINTER(TeleFogSourceType)
|
||||
IMPLEMENT_POINTER(TeleFogDestType)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
AActor::~AActor ()
|
||||
|
@ -749,7 +751,7 @@ void AActor::AddInventory (AInventory *item)
|
|||
DEFINE_ACTION_FUNCTION(AActor, AddInventory)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(item, AInventory);
|
||||
PARAM_OBJECT_NOT_NULL(item, AInventory);
|
||||
self->AddInventory(item);
|
||||
return 0;
|
||||
}
|
||||
|
@ -817,7 +819,7 @@ bool AActor::GiveInventory(PClassInventory *type, int amount, bool givecheat)
|
|||
DEFINE_ACTION_FUNCTION(AActor, Inventory)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(item, AInventory);
|
||||
PARAM_OBJECT_NOT_NULL(item, AInventory);
|
||||
ACTION_RETURN_BOOL(self->UseInventory(item));
|
||||
}
|
||||
|
||||
|
@ -852,7 +854,7 @@ void AActor::RemoveInventory(AInventory *item)
|
|||
DEFINE_ACTION_FUNCTION(AActor, RemoveInventory)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(item, AInventory);
|
||||
PARAM_OBJECT_NOT_NULL(item, AInventory);
|
||||
self->RemoveInventory(item);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1007,7 +1009,7 @@ bool AActor::UseInventory (AInventory *item)
|
|||
DEFINE_ACTION_FUNCTION(AActor, UseInventory)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(item, AInventory);
|
||||
PARAM_OBJECT_NOT_NULL(item, AInventory);
|
||||
ACTION_RETURN_BOOL(self->UseInventory(item));
|
||||
}
|
||||
|
||||
|
@ -1040,7 +1042,7 @@ AInventory *AActor::DropInventory (AInventory *item)
|
|||
DEFINE_ACTION_FUNCTION(AActor, DropInventory)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(item, AInventory);
|
||||
PARAM_OBJECT_NOT_NULL(item, AInventory);
|
||||
ACTION_RETURN_OBJECT(self->DropInventory(item));
|
||||
}
|
||||
|
||||
|
@ -1261,7 +1263,7 @@ void AActor::CopyFriendliness (AActor *other, bool changeTarget, bool resetHealt
|
|||
DEFINE_ACTION_FUNCTION(AActor, CopyFriendliness)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(other, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(other, AActor);
|
||||
PARAM_BOOL_DEF(changetarget);
|
||||
PARAM_BOOL_DEF(resethealth);
|
||||
self->CopyFriendliness(other, changetarget, resethealth);
|
||||
|
@ -1484,7 +1486,7 @@ void AActor::Touch (AActor *toucher)
|
|||
DEFINE_ACTION_FUNCTION(AActor, Touch)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(toucher, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(toucher, AActor);
|
||||
self->Touch(toucher);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1998,7 +2000,7 @@ bool AActor::CanSeek(AActor *target) const
|
|||
DEFINE_ACTION_FUNCTION(AActor, CanSeek)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(target, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(target, AActor);
|
||||
ACTION_RETURN_BOOL(self->CanSeek(target));
|
||||
}
|
||||
|
||||
|
@ -4667,7 +4669,7 @@ AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t a
|
|||
DEFINE_ACTION_FUNCTION(AActor, Spawn)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_CLASS(type, AActor);
|
||||
PARAM_CLASS_NOT_NULL(type, AActor);
|
||||
PARAM_FLOAT_DEF(x);
|
||||
PARAM_FLOAT_DEF(y);
|
||||
PARAM_FLOAT_DEF(z);
|
||||
|
@ -5654,6 +5656,8 @@ AActor *P_SpawnPuff (AActor *source, PClassActor *pufftype, const DVector3 &pos1
|
|||
AActor *puff;
|
||||
DVector3 pos = pos1;
|
||||
|
||||
if (pufftype == nullptr) return nullptr;
|
||||
|
||||
if (!(flags & PF_NORANDOMZ)) pos.Z += pr_spawnpuff.Random2() / 64.;
|
||||
puff = Spawn(pufftype, pos, ALLOW_REPLACE);
|
||||
if (puff == NULL) return NULL;
|
||||
|
@ -6161,7 +6165,7 @@ foundone:
|
|||
DEFINE_ACTION_FUNCTION(AActor, HitWater)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_POINTER(sec, sector_t);
|
||||
PARAM_POINTER_NOT_NULL(sec, sector_t);
|
||||
PARAM_FLOAT(x);
|
||||
PARAM_FLOAT(y);
|
||||
PARAM_FLOAT(z);
|
||||
|
@ -6381,7 +6385,7 @@ void P_PlaySpawnSound(AActor *missile, AActor *spawner)
|
|||
DEFINE_ACTION_FUNCTION(AActor, PlaySpawnSound)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(missile, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(missile, AActor);
|
||||
P_PlaySpawnSound(missile, self);
|
||||
return 0;
|
||||
}
|
||||
|
@ -6413,47 +6417,11 @@ DEFINE_ACTION_FUNCTION(AActor, GetDefaultSpeed)
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
AActor *P_SpawnMissile (AActor *source, AActor *dest, PClassActor *type, AActor *owner)
|
||||
{
|
||||
if (source == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return P_SpawnMissileXYZ (source->PosPlusZ(32 + source->GetBobOffset()), source, dest, type, true, owner);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, SpawnMissile)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(dest, AActor);
|
||||
PARAM_CLASS(type, AActor);
|
||||
PARAM_OBJECT_DEF(owner, AActor);
|
||||
ACTION_RETURN_OBJECT(P_SpawnMissile(self, dest, type, owner));
|
||||
}
|
||||
|
||||
AActor *P_SpawnMissileZ (AActor *source, double z, AActor *dest, PClassActor *type)
|
||||
{
|
||||
if (source == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return P_SpawnMissileXYZ (source->PosAtZ(z), source, dest, type);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, SpawnMissileZ)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_FLOAT(z);
|
||||
PARAM_OBJECT(dest, AActor);
|
||||
PARAM_CLASS(type, AActor);
|
||||
ACTION_RETURN_OBJECT(P_SpawnMissileZ(self, z, dest, type));
|
||||
}
|
||||
|
||||
AActor *P_SpawnMissileXYZ (DVector3 pos, AActor *source, AActor *dest, PClassActor *type, bool checkspawn, AActor *owner)
|
||||
{
|
||||
if (source == NULL)
|
||||
if (source == nullptr || type == nullptr)
|
||||
{
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (dest == NULL)
|
||||
|
@ -6528,19 +6496,56 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnMissileXYZ)
|
|||
PARAM_FLOAT(x);
|
||||
PARAM_FLOAT(y);
|
||||
PARAM_FLOAT(z);
|
||||
PARAM_OBJECT(dest, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(dest, AActor);
|
||||
PARAM_CLASS(type, AActor);
|
||||
PARAM_BOOL_DEF(check);
|
||||
PARAM_OBJECT_DEF(owner, AActor);
|
||||
ACTION_RETURN_OBJECT(P_SpawnMissileXYZ(DVector3(x,y,z), self, dest, type, check, owner));
|
||||
}
|
||||
|
||||
AActor *P_SpawnMissile(AActor *source, AActor *dest, PClassActor *type, AActor *owner)
|
||||
{
|
||||
if (source == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return P_SpawnMissileXYZ(source->PosPlusZ(32 + source->GetBobOffset()), source, dest, type, true, owner);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, SpawnMissile)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT_NOT_NULL(dest, AActor);
|
||||
PARAM_CLASS(type, AActor);
|
||||
PARAM_OBJECT_DEF(owner, AActor);
|
||||
ACTION_RETURN_OBJECT(P_SpawnMissile(self, dest, type, owner));
|
||||
}
|
||||
|
||||
AActor *P_SpawnMissileZ(AActor *source, double z, AActor *dest, PClassActor *type)
|
||||
{
|
||||
if (source == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return P_SpawnMissileXYZ(source->PosAtZ(z), source, dest, type);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, SpawnMissileZ)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_FLOAT(z);
|
||||
PARAM_OBJECT_NOT_NULL(dest, AActor);
|
||||
PARAM_CLASS(type, AActor);
|
||||
ACTION_RETURN_OBJECT(P_SpawnMissileZ(self, z, dest, type));
|
||||
}
|
||||
|
||||
|
||||
|
||||
AActor *P_OldSpawnMissile(AActor *source, AActor *owner, AActor *dest, PClassActor *type)
|
||||
{
|
||||
if (source == NULL)
|
||||
if (source == nullptr || type == nullptr)
|
||||
{
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
AActor *th = Spawn (type, source->PosPlusZ(32.), ALLOW_REPLACE);
|
||||
|
||||
|
@ -6566,7 +6571,7 @@ AActor *P_OldSpawnMissile(AActor *source, AActor *owner, AActor *dest, PClassAct
|
|||
DEFINE_ACTION_FUNCTION(AActor, OldSpawnMissile)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(dest, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(dest, AActor);
|
||||
PARAM_CLASS(type, AActor);
|
||||
PARAM_OBJECT_DEF(owner, AActor);
|
||||
ACTION_RETURN_OBJECT(P_OldSpawnMissile(self, owner, dest, type));
|
||||
|
@ -6584,7 +6589,7 @@ DEFINE_ACTION_FUNCTION(AActor, OldSpawnMissile)
|
|||
|
||||
AActor *P_SpawnMissileAngle (AActor *source, PClassActor *type, DAngle angle, double vz)
|
||||
{
|
||||
if (source == NULL)
|
||||
if (source == nullptr || type == nullptr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -6593,14 +6598,18 @@ AActor *P_SpawnMissileAngle (AActor *source, PClassActor *type, DAngle angle, do
|
|||
|
||||
AActor *P_SpawnMissileAngleZ (AActor *source, double z, PClassActor *type, DAngle angle, double vz)
|
||||
{
|
||||
if (type == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return P_SpawnMissileAngleZSpeed (source, z, type, angle, vz, GetDefaultSpeed (type));
|
||||
}
|
||||
|
||||
AActor *P_SpawnMissileZAimed (AActor *source, double z, AActor *dest, PClassActor *type)
|
||||
{
|
||||
if (source == NULL)
|
||||
if (source == nullptr || type == nullptr)
|
||||
{
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
DAngle an;
|
||||
double dist;
|
||||
|
@ -6624,7 +6633,7 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnMissileZAimed)
|
|||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_FLOAT(z);
|
||||
PARAM_OBJECT(dest, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(dest, AActor);
|
||||
PARAM_CLASS(type, AActor);
|
||||
ACTION_RETURN_OBJECT(P_SpawnMissileZAimed(self, z, dest, type));
|
||||
}
|
||||
|
@ -6641,9 +6650,9 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnMissileZAimed)
|
|||
AActor *P_SpawnMissileAngleZSpeed (AActor *source, double z,
|
||||
PClassActor *type, DAngle angle, double vz, double speed, AActor *owner, bool checkspawn)
|
||||
{
|
||||
if (source == NULL)
|
||||
if (source == nullptr || type == nullptr)
|
||||
{
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
AActor *mo;
|
||||
|
||||
|
@ -6687,9 +6696,9 @@ AActor *P_SpawnSubMissile(AActor *source, PClassActor *type, AActor *target)
|
|||
{
|
||||
AActor *other = Spawn(type, source->Pos(), ALLOW_REPLACE);
|
||||
|
||||
if (other == NULL)
|
||||
if (source == nullptr || type == nullptr)
|
||||
{
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
other->target = target;
|
||||
|
@ -6721,7 +6730,7 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnSubMissile)
|
|||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_CLASS(cls, AActor);
|
||||
PARAM_OBJECT(target, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(target, AActor);
|
||||
ACTION_RETURN_OBJECT(P_SpawnSubMissile(self, cls, target));
|
||||
}
|
||||
/*
|
||||
|
@ -6751,6 +6760,11 @@ AActor *P_SpawnPlayerMissile (AActor *source, double x, double y, double z,
|
|||
PClassActor *type, DAngle angle, FTranslatedLineTarget *pLineTarget, AActor **pMissileActor,
|
||||
bool nofreeaim, bool noautoaim, int aimflags)
|
||||
{
|
||||
if (source == nullptr || type == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const double angdiff[3] = { -5.625, 5.625, 0 };
|
||||
DAngle an = angle;
|
||||
DAngle pitch;
|
||||
|
@ -6758,10 +6772,6 @@ AActor *P_SpawnPlayerMissile (AActor *source, double x, double y, double z,
|
|||
AActor *defaultobject = GetDefaultByType(type);
|
||||
DAngle vrange = nofreeaim ? 35. : 0.;
|
||||
|
||||
if (source == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (!pLineTarget) pLineTarget = &scratch;
|
||||
if (source->player && source->player->ReadyWeapon && ((source->player->ReadyWeapon->WeaponFlags & WIF_NOAUTOAIM) || noautoaim))
|
||||
{
|
||||
|
@ -6908,7 +6918,7 @@ bool AActor::IsTeammate (AActor *other)
|
|||
DEFINE_ACTION_FUNCTION(AActor, isTeammate)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(other, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(other, AActor);
|
||||
ACTION_RETURN_BOOL(self->IsTeammate(other));
|
||||
}
|
||||
|
||||
|
@ -6980,7 +6990,7 @@ bool AActor::IsFriend (AActor *other)
|
|||
DEFINE_ACTION_FUNCTION(AActor, isFriend)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(other, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(other, AActor);
|
||||
ACTION_RETURN_BOOL(self->IsFriend(other));
|
||||
}
|
||||
|
||||
|
@ -7017,7 +7027,7 @@ bool AActor::IsHostile (AActor *other)
|
|||
DEFINE_ACTION_FUNCTION(AActor, isHostile)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(other, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(other, AActor);
|
||||
ACTION_RETURN_BOOL(self->IsHostile(other));
|
||||
}
|
||||
|
||||
|
@ -7056,7 +7066,7 @@ int AActor::DoSpecialDamage (AActor *target, int damage, FName damagetype)
|
|||
DEFINE_ACTION_FUNCTION(AActor, DoSpecialDamage)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(target, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(target, AActor);
|
||||
PARAM_INT(damage);
|
||||
PARAM_NAME(damagetype);
|
||||
ACTION_RETURN_INT(self->DoSpecialDamage(target, damage, damagetype));
|
||||
|
@ -7578,14 +7588,14 @@ DEFINE_ACTION_FUNCTION(AActor, absangle) // should this be global?
|
|||
DEFINE_ACTION_FUNCTION(AActor, Distance2D)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(other, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(other, AActor);
|
||||
ACTION_RETURN_FLOAT(self->Distance2D(other));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, Distance3D)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(other, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(other, AActor);
|
||||
ACTION_RETURN_FLOAT(self->Distance3D(other));
|
||||
}
|
||||
|
||||
|
@ -7618,7 +7628,7 @@ DEFINE_ACTION_FUNCTION(AActor, GetDefaultByType)
|
|||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_CLASS(cls, AActor);
|
||||
ACTION_RETURN_OBJECT(GetDefaultByType(cls));
|
||||
ACTION_RETURN_OBJECT(cls == nullptr? nullptr : GetDefaultByType(cls));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, GetBobOffset)
|
||||
|
@ -7690,7 +7700,7 @@ DEFINE_ACTION_FUNCTION(AActor, Thrust)
|
|||
DEFINE_ACTION_FUNCTION(AActor, AngleTo)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(targ, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(targ, AActor);
|
||||
PARAM_BOOL_DEF(absolute);
|
||||
ACTION_RETURN_FLOAT(self->AngleTo(targ, absolute).Degrees);
|
||||
}
|
||||
|
@ -7715,7 +7725,7 @@ DEFINE_ACTION_FUNCTION(AActor, RotateVector)
|
|||
DEFINE_ACTION_FUNCTION(AActor, DistanceBySpeed)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(targ, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(targ, AActor);
|
||||
PARAM_FLOAT(speed);
|
||||
ACTION_RETURN_FLOAT(self->DistanceBySpeed(targ, speed));
|
||||
}
|
||||
|
@ -7743,14 +7753,14 @@ DEFINE_ACTION_FUNCTION(AActor, Vec2Angle)
|
|||
DEFINE_ACTION_FUNCTION(AActor, Vec3To)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(t, AActor)
|
||||
PARAM_OBJECT_NOT_NULL(t, AActor)
|
||||
ACTION_RETURN_VEC3(self->Vec3To(t));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, Vec2To)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(t, AActor)
|
||||
PARAM_OBJECT_NOT_NULL(t, AActor)
|
||||
ACTION_RETURN_VEC2(self->Vec2To(t));
|
||||
}
|
||||
|
||||
|
@ -7911,5 +7921,6 @@ void PrintMiscActorInfo(AActor *query)
|
|||
query->floorz, query->ceilingz);
|
||||
Printf("\nSpeed= %f, velocity= x:%f, y:%f, z:%f, combined:%f.\n",
|
||||
query->Speed, query->Vel.X, query->Vel.Y, query->Vel.Z, query->Vel.Length());
|
||||
Printf("Scale: x:%f, y:%f\n", query->Scale.X, query->Scale.Y);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -828,7 +828,7 @@ void DoReadyWeapon(AActor *self)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(AStateProvider, A_WeaponReady)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_ACTION_PROLOGUE(AStateProvider);
|
||||
PARAM_INT_DEF(flags);
|
||||
|
||||
DoReadyWeaponToSwitch(self, !(flags & WRF_NoSwitch));
|
||||
|
@ -960,7 +960,7 @@ static void P_CheckWeaponButtons (player_t *player)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(AStateProvider, A_ReFire)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_ACTION_PROLOGUE(AStateProvider);
|
||||
PARAM_STATE_ACTION_DEF(state);
|
||||
A_ReFire(self, state);
|
||||
return 0;
|
||||
|
@ -998,7 +998,7 @@ void A_ReFire(AActor *self, FState *state)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(AStateProvider, A_ClearReFire)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_ACTION_PROLOGUE(AStateProvider);
|
||||
player_t *player = self->player;
|
||||
|
||||
if (NULL != player)
|
||||
|
@ -1020,7 +1020,7 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_ClearReFire)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(AStateProvider, A_CheckReload)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_ACTION_PROLOGUE(AStateProvider);
|
||||
|
||||
if (self->player != NULL)
|
||||
{
|
||||
|
@ -1208,7 +1208,7 @@ DEFINE_ACTION_FUNCTION(AActor, OverlayID)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(AStateProvider, A_Lower)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_ACTION_PROLOGUE(AStateProvider);
|
||||
|
||||
player_t *player = self->player;
|
||||
DPSprite *psp;
|
||||
|
@ -1254,9 +1254,9 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_Lower)
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Raise)
|
||||
DEFINE_ACTION_FUNCTION(AStateProvider, A_Raise)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_ACTION_PROLOGUE(AStateProvider);
|
||||
|
||||
if (self == nullptr)
|
||||
{
|
||||
|
@ -1368,7 +1368,7 @@ enum GF_Flags
|
|||
|
||||
DEFINE_ACTION_FUNCTION(AStateProvider, A_GunFlash)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_ACTION_PROLOGUE(AStateProvider);
|
||||
PARAM_STATE_ACTION_DEF(flash);
|
||||
PARAM_INT_DEF(flags);
|
||||
|
||||
|
@ -1605,38 +1605,40 @@ void player_t::DestroyPSprites()
|
|||
|
||||
void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int index)
|
||||
{
|
||||
|
||||
PClassActor *cls = weapon->GetClass();
|
||||
while (cls != RUNTIME_CLASS(AWeapon))
|
||||
if (flashstate != nullptr)
|
||||
{
|
||||
if (flashstate >= cls->OwnedStates && flashstate < cls->OwnedStates + cls->NumOwnedStates)
|
||||
PClassActor *cls = weapon->GetClass();
|
||||
while (cls != RUNTIME_CLASS(AWeapon))
|
||||
{
|
||||
// The flash state belongs to this class.
|
||||
// Now let's check if the actually wanted state does also
|
||||
if (flashstate + index < cls->OwnedStates + cls->NumOwnedStates)
|
||||
if (flashstate >= cls->OwnedStates && flashstate < cls->OwnedStates + cls->NumOwnedStates)
|
||||
{
|
||||
// we're ok so set the state
|
||||
P_SetPsprite(player, PSP_FLASH, flashstate + index, true);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// oh, no! The state is beyond the end of the state table so use the original flash state.
|
||||
P_SetPsprite(player, PSP_FLASH, flashstate, true);
|
||||
return;
|
||||
// The flash state belongs to this class.
|
||||
// Now let's check if the actually wanted state does also
|
||||
if (flashstate + index < cls->OwnedStates + cls->NumOwnedStates)
|
||||
{
|
||||
// we're ok so set the state
|
||||
P_SetPsprite(player, PSP_FLASH, flashstate + index, true);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// oh, no! The state is beyond the end of the state table so use the original flash state.
|
||||
P_SetPsprite(player, PSP_FLASH, flashstate, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// try again with parent class
|
||||
cls = static_cast<PClassActor *>(cls->ParentClass);
|
||||
}
|
||||
// if we get here the state doesn't seem to belong to any class in the inheritance chain
|
||||
// This can happen with Dehacked if the flash states are remapped.
|
||||
// The only way to check this would be to go through all Dehacked modifiable actors, convert
|
||||
// their states into a single flat array and find the correct one.
|
||||
// Rather than that, just check to make sure it belongs to something.
|
||||
if (FState::StaticFindStateOwner(flashstate + index) == NULL)
|
||||
{ // Invalid state. With no index offset, it should at least be valid.
|
||||
index = 0;
|
||||
}
|
||||
// try again with parent class
|
||||
cls = static_cast<PClassActor *>(cls->ParentClass);
|
||||
}
|
||||
// if we get here the state doesn't seem to belong to any class in the inheritance chain
|
||||
// This can happen with Dehacked if the flash states are remapped.
|
||||
// The only way to check this would be to go through all Dehacked modifiable actors, convert
|
||||
// their states into a single flat array and find the correct one.
|
||||
// Rather than that, just check to make sure it belongs to something.
|
||||
if (FState::StaticFindStateOwner(flashstate + index) == NULL)
|
||||
{ // Invalid state. With no index offset, it should at least be valid.
|
||||
index = 0;
|
||||
}
|
||||
P_SetPsprite(player, PSP_FLASH, flashstate + index, true);
|
||||
}
|
||||
|
@ -1644,7 +1646,7 @@ void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int i
|
|||
DEFINE_ACTION_FUNCTION(_PlayerInfo, SetSafeFlash)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(player_t);
|
||||
PARAM_OBJECT(weapon, AWeapon);
|
||||
PARAM_OBJECT_NOT_NULL(weapon, AWeapon);
|
||||
PARAM_POINTER(state, FState);
|
||||
PARAM_INT(index);
|
||||
P_SetSafeFlash(weapon, self, state, index);
|
||||
|
|
|
@ -908,7 +908,7 @@ done:
|
|||
DEFINE_ACTION_FUNCTION(AActor, CheckSight)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(target, AActor);
|
||||
PARAM_OBJECT_NOT_NULL(target, AActor);
|
||||
PARAM_INT_DEF(flags);
|
||||
ACTION_RETURN_BOOL(P_CheckSight(self, target, flags));
|
||||
}
|
||||
|
|
|
@ -178,8 +178,8 @@ void P_SetSlope (secplane_t *plane, bool setCeil, int xyangi, int zangi, const D
|
|||
if (ib_compatflags & BCOMPATF_SETSLOPEOVERFLOW)
|
||||
{
|
||||
// We have to consider an integer multiplication overflow here.
|
||||
norm[0] = FixedToFloat(FloatToFixed(zang.Cos()) * FloatToFixed(xyang.Cos()));
|
||||
norm[1] = FixedToFloat(FloatToFixed(zang.Cos()) * FloatToFixed(xyang.Sin()));
|
||||
norm[0] = FixedToFloat(FloatToFixed(zang.Cos()) * FloatToFixed(xyang.Cos())) / 65536.;
|
||||
norm[1] = FixedToFloat(FloatToFixed(zang.Cos()) * FloatToFixed(xyang.Sin())) / 65536.;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1083,11 +1083,12 @@ DEFINE_ACTION_FUNCTION(FState, DistanceTo)
|
|||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FState);
|
||||
PARAM_POINTER(other, FState);
|
||||
|
||||
// Safely calculate the distance between two states.
|
||||
auto o1 = FState::StaticFindStateOwner(self);
|
||||
int retv;
|
||||
if (other < o1->OwnedStates || other >= o1->OwnedStates + o1->NumOwnedStates) retv = INT_MIN;
|
||||
else retv = int(other - self);
|
||||
int retv = INT_MIN;
|
||||
if (other != nullptr)
|
||||
{
|
||||
// Safely calculate the distance between two states.
|
||||
auto o1 = FState::StaticFindStateOwner(self);
|
||||
if (other >= o1->OwnedStates && other < o1->OwnedStates + o1->NumOwnedStates) retv = int(other - self);
|
||||
}
|
||||
ACTION_RETURN_INT(retv);
|
||||
}
|
||||
|
|
|
@ -608,6 +608,7 @@ static void ParseSpawnMap(FScanner &sc, SpawnMap & themap, const char *descript)
|
|||
}
|
||||
defined[ednum] = true;
|
||||
editem.classname = sc.String;
|
||||
editem.linenum = sc.Line;
|
||||
|
||||
themap.Insert(ednum, editem);
|
||||
}
|
||||
|
|
|
@ -607,16 +607,6 @@ bool PClassPlayerPawn::GetPainFlash(FName type, PalEntry *color) const
|
|||
return false;
|
||||
}
|
||||
|
||||
void PClassPlayerPawn::ReplaceClassRef(PClass *oldclass, PClass *newclass)
|
||||
{
|
||||
Super::ReplaceClassRef(oldclass, newclass);
|
||||
APlayerPawn *def = (APlayerPawn*)Defaults;
|
||||
if (def != NULL)
|
||||
{
|
||||
if (def->FlechetteType == oldclass) def->FlechetteType = static_cast<PClassInventory *>(newclass);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// player_t :: SendPitchLimits
|
||||
|
@ -648,6 +638,7 @@ IMPLEMENT_CLASS(APlayerPawn, false, true)
|
|||
IMPLEMENT_POINTERS_START(APlayerPawn)
|
||||
IMPLEMENT_POINTER(InvFirst)
|
||||
IMPLEMENT_POINTER(InvSel)
|
||||
IMPLEMENT_POINTER(FlechetteType)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
IMPLEMENT_CLASS(APlayerChunk, false, false)
|
||||
|
|
|
@ -1775,7 +1775,14 @@ void PO_Init (void)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clear all polyobj specials so that they do not obstruct using other lines.
|
||||
for (int i = 0; i < numlines; i++)
|
||||
{
|
||||
if (lines[i].special == Polyobj_ExplicitLine || lines[i].special == Polyobj_StartLine)
|
||||
{
|
||||
lines[i].special = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -1007,7 +1007,7 @@ void FScanner::CheckOpen()
|
|||
//==========================================================================
|
||||
int FScriptPosition::ErrorCounter;
|
||||
int FScriptPosition::WarnCounter;
|
||||
bool FScriptPosition::StrictErrors; // makes all OPTERRPR messages real errors.
|
||||
bool FScriptPosition::StrictErrors; // makes all OPTERROR messages real errors.
|
||||
|
||||
FScriptPosition::FScriptPosition(const FScriptPosition &other)
|
||||
{
|
||||
|
|
|
@ -288,6 +288,60 @@ ExpEmit FxExpression::Emit (VMFunctionBuilder *build)
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Emits a statement and records its position in the source.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FxExpression::EmitStatement(VMFunctionBuilder *build)
|
||||
{
|
||||
build->BeginStatement(this);
|
||||
ExpEmit exp = Emit(build);
|
||||
exp.Free(build);
|
||||
build->EndStatement();
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FxExpression::EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no)
|
||||
{
|
||||
ExpEmit op = Emit(build);
|
||||
ExpEmit i;
|
||||
assert(op.RegType != REGT_NIL && op.RegCount == 1 && !op.Konst);
|
||||
switch (op.RegType)
|
||||
{
|
||||
case REGT_INT:
|
||||
build->Emit(OP_EQ_K, !invert, op.RegNum, build->GetConstantInt(0));
|
||||
break;
|
||||
|
||||
case REGT_FLOAT:
|
||||
build->Emit(OP_EQF_K, !invert, op.RegNum, build->GetConstantFloat(0));
|
||||
break;
|
||||
|
||||
case REGT_POINTER:
|
||||
build->Emit(OP_EQA_K, !invert, op.RegNum, build->GetConstantAddress(0, ATAG_GENERIC));
|
||||
break;
|
||||
|
||||
case REGT_STRING:
|
||||
i = ExpEmit(build, REGT_INT);
|
||||
build->Emit(OP_LENS, i.RegNum, op.RegNum);
|
||||
build->Emit(OP_EQ_K, !invert, i.RegNum, build->GetConstantInt(0));
|
||||
i.Free(build);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
patchspots_no.Push(build->Emit(OP_JMP, 0));
|
||||
op.Free(build);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -584,7 +638,7 @@ static ExpEmit EmitKonst(VMFunctionBuilder *build, ExpEmit &emit)
|
|||
|
||||
ExpEmit FxVectorValue::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
// no const handling here. Ultimstely it's too rarely used (i.e. the only fully constant vector ever allocated in ZDoom is the 0-vector in a very few places)
|
||||
// no const handling here. Ultimately it's too rarely used (i.e. the only fully constant vector ever allocated in ZDoom is the 0-vector in a very few places)
|
||||
// and the negatives (excessive allocation of float constants) outweigh the positives (saved a few instructions)
|
||||
assert(xyz[0] != nullptr);
|
||||
assert(xyz[1] != nullptr);
|
||||
|
@ -757,26 +811,7 @@ ExpEmit FxBoolCast::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
ExpEmit to(build, REGT_INT);
|
||||
from.Free(build);
|
||||
// Preload result with 0.
|
||||
build->Emit(OP_LI, to.RegNum, 0);
|
||||
|
||||
// Check source against 0.
|
||||
if (from.RegType == REGT_INT)
|
||||
{
|
||||
build->Emit(OP_EQ_R, 1, from.RegNum, to.RegNum);
|
||||
}
|
||||
else if (from.RegType == REGT_FLOAT)
|
||||
{
|
||||
build->Emit(OP_EQF_K, 1, from.RegNum, build->GetConstantFloat(0.));
|
||||
}
|
||||
else if (from.RegType == REGT_POINTER)
|
||||
{
|
||||
build->Emit(OP_EQA_K, 1, from.RegNum, build->GetConstantAddress(nullptr, ATAG_GENERIC));
|
||||
}
|
||||
build->Emit(OP_JMP, 1);
|
||||
|
||||
// Reload result with 1 if the comparison fell through.
|
||||
build->Emit(OP_LI, to.RegNum, 1);
|
||||
build->Emit(OP_CASTB, to.RegNum, from.RegNum, from.RegType == REGT_INT ? CASTB_I : from.RegType == REGT_FLOAT ? CASTB_F : CASTB_A);
|
||||
return to;
|
||||
}
|
||||
else
|
||||
|
@ -791,6 +826,17 @@ ExpEmit FxBoolCast::Emit(VMFunctionBuilder *build)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FxBoolCast::EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no)
|
||||
{
|
||||
basex->EmitCompare(build, invert, patchspots_yes, patchspots_no);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxIntCast::FxIntCast(FxExpression *x, bool nowarn, bool explicitly)
|
||||
: FxExpression(EFX_IntCast, x->ScriptPosition)
|
||||
{
|
||||
|
@ -1210,7 +1256,7 @@ FxExpression *FxColorCast::Resolve(FCompileContext &ctx)
|
|||
}
|
||||
else
|
||||
{
|
||||
FxExpression *x = new FxConstant(V_GetColor(nullptr, constval.GetString()), ScriptPosition);
|
||||
FxExpression *x = new FxConstant(V_GetColor(nullptr, constval.GetString(), &ScriptPosition), ScriptPosition);
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
|
@ -1788,10 +1834,11 @@ FxExpression *FxUnaryNotBitwise::Resolve(FCompileContext& ctx)
|
|||
{
|
||||
int result = ~static_cast<FxConstant *>(Operand)->GetValue().GetInt();
|
||||
FxExpression *e = new FxConstant(result, ScriptPosition);
|
||||
e->ValueType = Operand->ValueType == TypeUInt32 ? TypeUInt32 : TypeSInt32;
|
||||
delete this;
|
||||
return e;
|
||||
}
|
||||
ValueType = TypeSInt32;
|
||||
ValueType = Operand->ValueType == TypeUInt32? TypeUInt32 : TypeSInt32;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -1889,6 +1936,17 @@ ExpEmit FxUnaryNotBoolean::Emit(VMFunctionBuilder *build)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FxUnaryNotBoolean::EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no)
|
||||
{
|
||||
Operand->EmitCompare(build, !invert, patchspots_yes, patchspots_no);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxSizeAlign::FxSizeAlign(FxExpression *operand, int which)
|
||||
: FxExpression(EFX_SizeAlign, operand->ScriptPosition)
|
||||
{
|
||||
|
@ -2261,14 +2319,29 @@ ExpEmit FxAssign::Emit(VMFunctionBuilder *build)
|
|||
ExpEmit pointer = Base->Emit(build);
|
||||
Address = pointer;
|
||||
|
||||
ExpEmit result = Right->Emit(build);
|
||||
ExpEmit result;
|
||||
bool intconst = false;
|
||||
int intconstval;
|
||||
|
||||
if (Right->isConstant() && Right->ValueType->GetRegType() == REGT_INT)
|
||||
{
|
||||
intconst = true;
|
||||
intconstval = static_cast<FxConstant*>(Right)->GetValue().GetInt();
|
||||
result.Konst = true;
|
||||
result.RegType = REGT_INT;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = Right->Emit(build);
|
||||
}
|
||||
assert(result.RegType <= REGT_TYPE);
|
||||
|
||||
if (pointer.Target)
|
||||
{
|
||||
if (result.Konst)
|
||||
{
|
||||
build->Emit(loadops[result.RegType], pointer.RegNum, result.RegNum);
|
||||
if (intconst) build->EmitLoadInt(pointer.RegNum, intconstval);
|
||||
else build->Emit(loadops[result.RegType], pointer.RegNum, result.RegNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2280,7 +2353,8 @@ ExpEmit FxAssign::Emit(VMFunctionBuilder *build)
|
|||
if (result.Konst)
|
||||
{
|
||||
ExpEmit temp(build, result.RegType);
|
||||
build->Emit(loadops[result.RegType], temp.RegNum, result.RegNum);
|
||||
if (intconst) build->EmitLoadInt(temp.RegNum, intconstval);
|
||||
else build->Emit(loadops[result.RegType], temp.RegNum, result.RegNum);
|
||||
result.Free(build);
|
||||
result = temp;
|
||||
}
|
||||
|
@ -3141,7 +3215,7 @@ FxExpression *FxCompareRel::Resolve(FCompileContext& ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build)
|
||||
ExpEmit FxCompareRel::EmitCommon(VMFunctionBuilder *build, bool forcompare, bool invert)
|
||||
{
|
||||
ExpEmit op1 = left->Emit(build);
|
||||
ExpEmit op2 = right->Emit(build);
|
||||
|
@ -3171,11 +3245,15 @@ ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
op2.Free(build);
|
||||
}
|
||||
if (invert) a ^= CMP_CHECK;
|
||||
|
||||
build->Emit(OP_LI, to.RegNum, 0, 0);
|
||||
if (!forcompare) build->Emit(OP_LI, to.RegNum, 0, 0);
|
||||
build->Emit(OP_CMPS, a, op1.RegNum, op2.RegNum);
|
||||
build->Emit(OP_JMP, 1);
|
||||
build->Emit(OP_LI, to.RegNum, 1);
|
||||
if (!forcompare)
|
||||
{
|
||||
build->Emit(OP_JMP, 1);
|
||||
build->Emit(OP_LI, to.RegNum, 1);
|
||||
}
|
||||
return to;
|
||||
}
|
||||
else
|
||||
|
@ -3214,16 +3292,32 @@ ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
op1.Free(build);
|
||||
}
|
||||
if (invert) check ^= 1;
|
||||
|
||||
// See FxBoolCast for comments, since it's the same thing.
|
||||
build->Emit(OP_LI, to.RegNum, 0, 0);
|
||||
if (!forcompare) build->Emit(OP_LI, to.RegNum, 0, 0);
|
||||
build->Emit(instr, check, op1.RegNum, op2.RegNum);
|
||||
build->Emit(OP_JMP, 1);
|
||||
build->Emit(OP_LI, to.RegNum, 1);
|
||||
if (!forcompare)
|
||||
{
|
||||
build->Emit(OP_JMP, 1);
|
||||
build->Emit(OP_LI, to.RegNum, 1);
|
||||
}
|
||||
return to;
|
||||
}
|
||||
}
|
||||
|
||||
ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
return EmitCommon(build, false, false);
|
||||
}
|
||||
|
||||
void FxCompareRel::EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no)
|
||||
{
|
||||
ExpEmit emit = EmitCommon(build, true, invert);
|
||||
emit.Free(build);
|
||||
patchspots_no.Push(build->Emit(OP_JMP, 0));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -3421,7 +3515,7 @@ error:
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build)
|
||||
ExpEmit FxCompareEq::EmitCommon(VMFunctionBuilder *build, bool forcompare, bool invert)
|
||||
{
|
||||
ExpEmit op1 = left->Emit(build);
|
||||
ExpEmit op2 = right->Emit(build);
|
||||
|
@ -3435,13 +3529,17 @@ ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build)
|
|||
int a = Operator == TK_Eq ? CMP_EQ :
|
||||
Operator == TK_Neq ? CMP_EQ | CMP_CHECK : CMP_EQ | CMP_APPROX;
|
||||
|
||||
if (op1.Konst) a|= CMP_BK;
|
||||
if (op1.Konst) a |= CMP_BK;
|
||||
if (op2.Konst) a |= CMP_CK;
|
||||
if (invert) a ^= CMP_CHECK;
|
||||
|
||||
build->Emit(OP_LI, to.RegNum, 0, 0);
|
||||
if (!forcompare) build->Emit(OP_LI, to.RegNum, 0, 0);
|
||||
build->Emit(OP_CMPS, a, op1.RegNum, op2.RegNum);
|
||||
build->Emit(OP_JMP, 1);
|
||||
build->Emit(OP_LI, to.RegNum, 1);
|
||||
if (!forcompare)
|
||||
{
|
||||
build->Emit(OP_JMP, 1);
|
||||
build->Emit(OP_LI, to.RegNum, 1);
|
||||
}
|
||||
op1.Free(build);
|
||||
op2.Free(build);
|
||||
return to;
|
||||
|
@ -3474,14 +3572,29 @@ ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build)
|
|||
}
|
||||
|
||||
// See FxUnaryNotBoolean for comments, since it's the same thing.
|
||||
build->Emit(OP_LI, to.RegNum, 0, 0);
|
||||
build->Emit(instr, Operator == TK_ApproxEq ? CMP_APPROX : ((Operator != TK_Eq) ? CMP_CHECK : 0), op1.RegNum, op2.RegNum);
|
||||
build->Emit(OP_JMP, 1);
|
||||
build->Emit(OP_LI, to.RegNum, 1);
|
||||
if (!forcompare) build->Emit(OP_LI, to.RegNum, 0, 0);
|
||||
build->Emit(instr, int(invert) ^ (Operator == TK_ApproxEq ? CMP_APPROX : ((Operator != TK_Eq) ? CMP_CHECK : 0)), op1.RegNum, op2.RegNum);
|
||||
if (!forcompare)
|
||||
{
|
||||
build->Emit(OP_JMP, 1);
|
||||
build->Emit(OP_LI, to.RegNum, 1);
|
||||
}
|
||||
return to;
|
||||
}
|
||||
}
|
||||
|
||||
ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
return EmitCommon(build, false, false);
|
||||
}
|
||||
|
||||
void FxCompareEq::EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no)
|
||||
{
|
||||
ExpEmit emit = EmitCommon(build, true, invert);
|
||||
emit.Free(build);
|
||||
patchspots_no.Push(build->Emit(OP_JMP, 0));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -4078,23 +4191,19 @@ void FxBinaryLogical::Flatten()
|
|||
|
||||
ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
TArray<size_t> patchspots;
|
||||
TArray<size_t> yes, no;
|
||||
bool invert = Operator == TK_OrOr;
|
||||
|
||||
int zero = build->GetConstantInt(0);
|
||||
for (unsigned i = 0; i < list.Size(); i++)
|
||||
{
|
||||
assert(list[i]->ValueType->GetRegType() == REGT_INT);
|
||||
ExpEmit op1 = list[i]->Emit(build);
|
||||
assert(!op1.Konst);
|
||||
op1.Free(build);
|
||||
build->Emit(OP_EQ_K, (Operator == TK_AndAnd) ? 1 : 0, op1.RegNum, zero);
|
||||
patchspots.Push(build->Emit(OP_JMP, 0, 0, 0));
|
||||
list[i]->EmitCompare(build, invert, yes, no);
|
||||
}
|
||||
build->BackpatchListToHere(yes);
|
||||
ExpEmit to(build, REGT_INT);
|
||||
build->Emit(OP_LI, to.RegNum, (Operator == TK_AndAnd) ? 1 : 0);
|
||||
build->Emit(OP_JMP, 1);
|
||||
build->BackpatchListToHere(no);
|
||||
auto ctarget = build->Emit(OP_LI, to.RegNum, (Operator == TK_AndAnd) ? 0 : 1);
|
||||
for (auto addr : patchspots) build->Backpatch(addr, ctarget);
|
||||
list.DeleteAndClear();
|
||||
list.ShrinkToFit();
|
||||
return to;
|
||||
|
@ -4464,21 +4573,17 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx)
|
|||
|
||||
ExpEmit FxConditional::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
size_t truejump, falsejump;
|
||||
ExpEmit out;
|
||||
size_t truejump;
|
||||
ExpEmit out, falseout;
|
||||
|
||||
// The true and false expressions ought to be assigned to the
|
||||
// same temporary instead of being copied to it. Oh well; good enough
|
||||
// for now.
|
||||
ExpEmit cond = condition->Emit(build);
|
||||
assert(cond.RegType == REGT_INT && !cond.Konst);
|
||||
TArray<size_t> yes, no;
|
||||
condition->EmitCompare(build, false, yes, no);
|
||||
|
||||
// Test condition.
|
||||
build->Emit(OP_EQ_K, 1, cond.RegNum, build->GetConstantInt(0));
|
||||
falsejump = build->Emit(OP_JMP, 0);
|
||||
cond.Free(build);
|
||||
build->BackpatchListToHere(yes);
|
||||
|
||||
// Evaluate true expression.
|
||||
if (truex->isConstant() && truex->ValueType->GetRegType() == REGT_INT)
|
||||
{
|
||||
out = ExpEmit(build, REGT_INT);
|
||||
|
@ -4518,7 +4623,7 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build)
|
|||
truejump = build->Emit(OP_JMP, 0);
|
||||
|
||||
// Evaluate false expression.
|
||||
build->BackpatchToHere(falsejump);
|
||||
build->BackpatchListToHere(no);
|
||||
if (falsex->isConstant() && falsex->ValueType->GetRegType() == REGT_INT)
|
||||
{
|
||||
build->EmitLoadInt(out.RegNum, static_cast<FxConstant *>(falsex)->GetValue().GetInt());
|
||||
|
@ -4591,7 +4696,13 @@ FxExpression *FxAbs::Resolve(FCompileContext &ctx)
|
|||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(val, ctx);
|
||||
|
||||
|
||||
if (val->ValueType == TypeBool) // abs of a boolean is always the same as the operand
|
||||
{
|
||||
auto v = val;
|
||||
val = nullptr;
|
||||
delete this;
|
||||
return v;
|
||||
}
|
||||
if (!val->IsNumeric())
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||
|
@ -5590,8 +5701,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
|||
goto foundit;
|
||||
}
|
||||
|
||||
auto cvar = FindCVar(Identifier.GetChars(), nullptr);
|
||||
if (cvar != nullptr)
|
||||
if (auto *cvar = FindCVar(Identifier.GetChars(), nullptr))
|
||||
{
|
||||
if (cvar->GetFlags() & CVAR_USERINFO)
|
||||
{
|
||||
|
@ -8424,9 +8534,7 @@ ExpEmit FxSequence::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
for (unsigned i = 0; i < Expressions.Size(); ++i)
|
||||
{
|
||||
ExpEmit v = Expressions[i]->Emit(build);
|
||||
// Throw away any result. We don't care about it.
|
||||
v.Free(build);
|
||||
Expressions[i]->EmitStatement(build);
|
||||
}
|
||||
return ExpEmit();
|
||||
}
|
||||
|
@ -8722,7 +8830,7 @@ ExpEmit FxSwitchStatement::Emit(VMFunctionBuilder *build)
|
|||
break;
|
||||
|
||||
default:
|
||||
line->Emit(build);
|
||||
line->EmitStatement(build);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -8876,68 +8984,28 @@ FxExpression *FxIfStatement::Resolve(FCompileContext &ctx)
|
|||
ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
ExpEmit v;
|
||||
size_t jumpspot;
|
||||
FxExpression *path1, *path2;
|
||||
int condcheck;
|
||||
size_t jumpspot = ~0u;
|
||||
|
||||
// This is pretty much copied from FxConditional, except we don't
|
||||
// keep any results.
|
||||
ExpEmit cond = Condition->Emit(build);
|
||||
assert(cond.RegType != REGT_STRING && !cond.Konst);
|
||||
TArray<size_t> yes, no;
|
||||
Condition->EmitCompare(build, false, yes, no);
|
||||
|
||||
if (WhenTrue != nullptr)
|
||||
{
|
||||
path1 = WhenTrue;
|
||||
path2 = WhenFalse;
|
||||
condcheck = 1;
|
||||
build->BackpatchListToHere(yes);
|
||||
WhenTrue->EmitStatement(build);
|
||||
}
|
||||
if (WhenFalse != nullptr)
|
||||
{
|
||||
if (!WhenTrue->CheckReturn()) jumpspot = build->Emit(OP_JMP, 0); // no need to emit a jump if the block returns.
|
||||
build->BackpatchListToHere(no);
|
||||
WhenFalse->EmitStatement(build);
|
||||
if (jumpspot != ~0u) build->BackpatchToHere(jumpspot);
|
||||
if (WhenTrue == nullptr) build->BackpatchListToHere(yes);
|
||||
}
|
||||
else
|
||||
{
|
||||
// When there is only a false path, reverse the condition so we can
|
||||
// treat it as a true path.
|
||||
assert(WhenFalse != nullptr);
|
||||
path1 = WhenFalse;
|
||||
path2 = nullptr;
|
||||
condcheck = 0;
|
||||
build->BackpatchListToHere(no);
|
||||
}
|
||||
|
||||
// Test condition.
|
||||
|
||||
switch (cond.RegType)
|
||||
{
|
||||
default:
|
||||
case REGT_INT:
|
||||
build->Emit(OP_EQ_K, condcheck, cond.RegNum, build->GetConstantInt(0));
|
||||
break;
|
||||
|
||||
case REGT_FLOAT:
|
||||
build->Emit(OP_EQF_K, condcheck, cond.RegNum, build->GetConstantFloat(0));
|
||||
break;
|
||||
|
||||
case REGT_POINTER:
|
||||
build->Emit(OP_EQA_K, condcheck, cond.RegNum, build->GetConstantAddress(nullptr, ATAG_GENERIC));
|
||||
break;
|
||||
}
|
||||
jumpspot = build->Emit(OP_JMP, 0);
|
||||
cond.Free(build);
|
||||
|
||||
// Evaluate first path
|
||||
v = path1->Emit(build);
|
||||
v.Free(build);
|
||||
if (path2 != nullptr)
|
||||
{
|
||||
size_t path1jump;
|
||||
|
||||
// if the branch ends with a return we do not need a terminating jmp.
|
||||
if (!path1->CheckReturn()) path1jump = build->Emit(OP_JMP, 0);
|
||||
else path1jump = 0xffffffff;
|
||||
// Evaluate second path
|
||||
build->BackpatchToHere(jumpspot);
|
||||
v = path2->Emit(build);
|
||||
v.Free(build);
|
||||
jumpspot = path1jump;
|
||||
}
|
||||
if (jumpspot != 0xffffffff) build->BackpatchToHere(jumpspot);
|
||||
return ExpEmit();
|
||||
}
|
||||
|
||||
|
@ -9045,35 +9113,27 @@ ExpEmit FxWhileLoop::Emit(VMFunctionBuilder *build)
|
|||
assert(Condition->ValueType == TypeBool);
|
||||
|
||||
size_t loopstart, loopend;
|
||||
size_t jumpspot;
|
||||
TArray<size_t> yes, no;
|
||||
|
||||
// Evaluate the condition and execute/break out of the loop.
|
||||
loopstart = build->GetAddress();
|
||||
if (!Condition->isConstant())
|
||||
{
|
||||
ExpEmit cond = Condition->Emit(build);
|
||||
build->Emit(OP_TEST, cond.RegNum, 0);
|
||||
jumpspot = build->Emit(OP_JMP, 0);
|
||||
cond.Free(build);
|
||||
Condition->EmitCompare(build, false, yes, no);
|
||||
}
|
||||
else assert(static_cast<FxConstant *>(Condition)->GetValue().GetBool() == true);
|
||||
|
||||
build->BackpatchListToHere(yes);
|
||||
// Execute the loop's content.
|
||||
if (Code != nullptr)
|
||||
{
|
||||
ExpEmit code = Code->Emit(build);
|
||||
code.Free(build);
|
||||
Code->EmitStatement(build);
|
||||
}
|
||||
|
||||
// Loop back.
|
||||
build->Backpatch(build->Emit(OP_JMP, 0), loopstart);
|
||||
build->BackpatchListToHere(no);
|
||||
loopend = build->GetAddress();
|
||||
|
||||
if (!Condition->isConstant())
|
||||
{
|
||||
build->Backpatch(jumpspot, loopend);
|
||||
}
|
||||
|
||||
Backpatch(build, loopstart, loopend);
|
||||
return ExpEmit();
|
||||
}
|
||||
|
@ -9142,25 +9202,23 @@ ExpEmit FxDoWhileLoop::Emit(VMFunctionBuilder *build)
|
|||
codestart = build->GetAddress();
|
||||
if (Code != nullptr)
|
||||
{
|
||||
ExpEmit code = Code->Emit(build);
|
||||
code.Free(build);
|
||||
Code->EmitStatement(build);
|
||||
}
|
||||
|
||||
// Evaluate the condition and execute/break out of the loop.
|
||||
loopstart = build->GetAddress();
|
||||
if (!Condition->isConstant())
|
||||
{
|
||||
ExpEmit cond = Condition->Emit(build);
|
||||
build->Emit(OP_TEST, cond.RegNum, 1);
|
||||
cond.Free(build);
|
||||
build->Backpatch(build->Emit(OP_JMP, 0), codestart);
|
||||
TArray<size_t> yes, no;
|
||||
Condition->EmitCompare(build, true, yes, no);
|
||||
build->BackpatchList(no, codestart);
|
||||
build->BackpatchListToHere(yes);
|
||||
}
|
||||
else if (static_cast<FxConstant *>(Condition)->GetValue().GetBool() == true)
|
||||
{ // Always looping
|
||||
build->Backpatch(build->Emit(OP_JMP, 0), codestart);
|
||||
}
|
||||
loopend = build->GetAddress();
|
||||
|
||||
Backpatch(build, loopstart, loopend);
|
||||
|
||||
return ExpEmit();
|
||||
|
@ -9234,7 +9292,7 @@ ExpEmit FxForLoop::Emit(VMFunctionBuilder *build)
|
|||
|
||||
size_t loopstart, loopend;
|
||||
size_t codestart;
|
||||
size_t jumpspot;
|
||||
TArray<size_t> yes, no;
|
||||
|
||||
// Init statement (only used by DECORATE. ZScript is pulling it before the loop statement and enclosing the entire loop in a compound statement so that Init can have local variables.)
|
||||
if (Init != nullptr)
|
||||
|
@ -9247,17 +9305,14 @@ ExpEmit FxForLoop::Emit(VMFunctionBuilder *build)
|
|||
codestart = build->GetAddress();
|
||||
if (Condition != nullptr)
|
||||
{
|
||||
ExpEmit cond = Condition->Emit(build);
|
||||
build->Emit(OP_TEST, cond.RegNum, 0);
|
||||
cond.Free(build);
|
||||
jumpspot = build->Emit(OP_JMP, 0);
|
||||
Condition->EmitCompare(build, false, yes, no);
|
||||
}
|
||||
|
||||
build->BackpatchListToHere(yes);
|
||||
// Execute the loop's content.
|
||||
if (Code != nullptr)
|
||||
{
|
||||
ExpEmit code = Code->Emit(build);
|
||||
code.Free(build);
|
||||
Code->EmitStatement(build);
|
||||
}
|
||||
|
||||
// Iteration statement.
|
||||
|
@ -9271,10 +9326,7 @@ ExpEmit FxForLoop::Emit(VMFunctionBuilder *build)
|
|||
|
||||
// End of loop.
|
||||
loopend = build->GetAddress();
|
||||
if (Condition != nullptr)
|
||||
{
|
||||
build->Backpatch(jumpspot, loopend);
|
||||
}
|
||||
build->BackpatchListToHere(no);
|
||||
|
||||
Backpatch(build, loopstart, loopend);
|
||||
return ExpEmit();
|
||||
|
@ -9655,7 +9707,7 @@ int BuiltinClassCast(VMValue *param, TArray<VMValue> &defaultparam, int numparam
|
|||
PARAM_PROLOGUE;
|
||||
PARAM_CLASS(from, DObject);
|
||||
PARAM_CLASS(to, DObject);
|
||||
ACTION_RETURN_OBJECT(from->IsDescendantOf(to) ? from : nullptr);
|
||||
ACTION_RETURN_OBJECT(from && to && from->IsDescendantOf(to) ? from : nullptr);
|
||||
}
|
||||
|
||||
ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
|
||||
|
@ -9923,6 +9975,19 @@ FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx)
|
|||
if (Init) Init = new FxTypeCast(Init, ValueType, false);
|
||||
SAFE_RESOLVE_OPT(Init, ctx);
|
||||
}
|
||||
if (Name != NAME_None)
|
||||
{
|
||||
for (auto l : ctx.Block->LocalVars)
|
||||
{
|
||||
if (l->Name == Name)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Local variable %s already defined", Name.GetChars());
|
||||
l->ScriptPosition.Message(MSG_ERROR, "Original definition is here ");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.Block->LocalVars.Push(this);
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -328,6 +328,8 @@ public:
|
|||
bool IsObject() const { return ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) && ValueType != TypeNullPtr && static_cast<PPointer*>(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PClass)); }
|
||||
|
||||
virtual ExpEmit Emit(VMFunctionBuilder *build);
|
||||
void EmitStatement(VMFunctionBuilder *build);
|
||||
virtual void EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no);
|
||||
|
||||
FScriptPosition ScriptPosition;
|
||||
PType *ValueType = nullptr;
|
||||
|
@ -565,6 +567,7 @@ public:
|
|||
FxExpression *Resolve(FCompileContext&);
|
||||
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
void EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no);
|
||||
};
|
||||
|
||||
class FxIntCast : public FxExpression
|
||||
|
@ -734,6 +737,7 @@ public:
|
|||
~FxUnaryNotBoolean();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
void EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -934,7 +938,9 @@ public:
|
|||
|
||||
FxCompareRel(int, FxExpression*, FxExpression*);
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpEmit EmitCommon(VMFunctionBuilder *build, bool forcompare, bool invert);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
void EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -949,7 +955,9 @@ public:
|
|||
|
||||
FxCompareEq(int, FxExpression*, FxExpression*);
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpEmit EmitCommon(VMFunctionBuilder *build, bool forcompare, bool invert);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
void EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -165,7 +165,7 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool c
|
|||
}
|
||||
else
|
||||
{
|
||||
int c = V_GetColor (NULL, sc.String);
|
||||
int c = V_GetColor (NULL, sc);
|
||||
// 0 needs to be the default so we have to mark the color.
|
||||
v = MAKEARGB(1, RPART(c), GPART(c), BPART(c));
|
||||
}
|
||||
|
|
|
@ -343,7 +343,7 @@ endofstate:
|
|||
if (ScriptCode != nullptr)
|
||||
{
|
||||
auto funcsym = CreateAnonymousFunction(actor, nullptr, state.UseFlags);
|
||||
state.ActionFunc = FunctionBuildList.AddFunction(funcsym, ScriptCode, FStringf("%s.StateFunction.%d", actor->TypeName.GetChars(), bag.statedef.GetStateCount()), true);
|
||||
state.ActionFunc = FunctionBuildList.AddFunction(funcsym, ScriptCode, FStringf("%s.StateFunction.%d", actor->TypeName.GetChars(), bag.statedef.GetStateCount()), true, bag.statedef.GetStateCount(), int(statestring.Len()), sc.LumpNum);
|
||||
}
|
||||
int count = bag.statedef.AddStates(&state, statestring, scp);
|
||||
if (count < 0)
|
||||
|
|
|
@ -68,7 +68,6 @@
|
|||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
void InitThingdef();
|
||||
TArray<PClassActor **> OptionalClassPtrs;
|
||||
|
||||
// STATIC FUNCTION PROTOTYPES --------------------------------------------
|
||||
PClassActor *QuestItemClasses[31];
|
||||
|
@ -220,7 +219,7 @@ PFunction *FindClassMemberFunction(PStruct *selfcls, PStruct *funccls, FName nam
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate)
|
||||
void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate, int lumpnum)
|
||||
{
|
||||
if (id == nullptr)
|
||||
{
|
||||
|
@ -230,7 +229,7 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id,
|
|||
{
|
||||
auto dmg = new FxReturnStatement(new FxIntCast(id, true), id->ScriptPosition);
|
||||
auto funcsym = CreateAnonymousFunction(info, TypeSInt32, 0);
|
||||
defaults->DamageFunc = FunctionBuildList.AddFunction(funcsym, dmg, FStringf("%s.DamageFunction", info->TypeName.GetChars()), fromDecorate);
|
||||
defaults->DamageFunc = FunctionBuildList.AddFunction(funcsym, dmg, FStringf("%s.DamageFunction", info->TypeName.GetChars()), fromDecorate, -1, 0, lumpnum);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -365,7 +364,7 @@ static void CheckStates(PClassActor *obj)
|
|||
void ParseScripts();
|
||||
void ParseAllDecorate();
|
||||
|
||||
void LoadActors ()
|
||||
void LoadActors()
|
||||
{
|
||||
cycle_t timer;
|
||||
|
||||
|
@ -387,8 +386,9 @@ void LoadActors ()
|
|||
}
|
||||
FScriptPosition::ResetErrorCounter();
|
||||
|
||||
for (auto ti : PClassActor::AllActorClasses)
|
||||
for (int i = PClassActor::AllActorClasses.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
auto ti = PClassActor::AllActorClasses[i];
|
||||
if (ti->Size == TentativeClass)
|
||||
{
|
||||
if (ti->ObjectFlags & OF_Transient)
|
||||
|
@ -396,10 +396,7 @@ void LoadActors ()
|
|||
Printf(TEXTCOLOR_ORANGE "Class %s referenced but not defined\n", ti->TypeName.GetChars());
|
||||
FScriptPosition::WarnCounter++;
|
||||
DObject::StaticPointerSubstitution(ti, nullptr);
|
||||
for (auto op : OptionalClassPtrs)
|
||||
{
|
||||
if (*op == ti) *op = nullptr;
|
||||
}
|
||||
PClassActor::AllActorClasses.Delete(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -418,7 +415,7 @@ void LoadActors ()
|
|||
|
||||
|
||||
CheckStates(ti);
|
||||
|
||||
|
||||
if (ti->bDecorateClass && ti->IsDescendantOf(RUNTIME_CLASS(AStateProvider)))
|
||||
{
|
||||
// either a DECORATE based weapon or CustomInventory.
|
||||
|
@ -427,7 +424,7 @@ void LoadActors ()
|
|||
// hits an unsafe state. If we can find something here it can be handled wuth a compile error rather than a runtime error.
|
||||
CheckForUnsafeStates(ti);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
if (FScriptPosition::ErrorCounter > 0)
|
||||
{
|
||||
|
@ -445,6 +442,4 @@ void LoadActors ()
|
|||
QuestItemClasses[i] = PClass::FindActor(fmt);
|
||||
}
|
||||
StateSourceLines.Clear();
|
||||
OptionalClassPtrs.Clear();
|
||||
OptionalClassPtrs.ShrinkToFit();
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ FName CheckCastKludges(FName in);
|
|||
void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, TArray<FName> *argnames, PStruct *cls, DWORD funcflags, int useflags);
|
||||
PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags);
|
||||
PFunction *FindClassMemberFunction(PStruct *cls, PStruct *funccls, FName name, FScriptPosition &sc, bool *error);
|
||||
void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate);
|
||||
void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate, int lumpnum);
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -583,35 +583,24 @@ FPropertyInfo *FindProperty(const char * string)
|
|||
|
||||
AFuncDesc *FindFunction(PStruct *cls, const char * string)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
int min = 0, max = AFTable.Size() - 1;
|
||||
|
||||
while (min <= max)
|
||||
{
|
||||
// Since many functions have been declared with Actor as owning class, despite being members of something else, let's hack around this until they have been fixed or exported.
|
||||
// Since most of these are expected to be scriptified anyway, there's no point fixing them all before they get exported.
|
||||
if (i == 1)
|
||||
int mid = (min + max) / 2;
|
||||
int lexval = stricmp(cls->TypeName.GetChars(), AFTable[mid].ClassName + 1);
|
||||
if (lexval == 0) lexval = stricmp(string, AFTable[mid].FuncName);
|
||||
if (lexval == 0)
|
||||
{
|
||||
if (!cls->IsKindOf(RUNTIME_CLASS(PClassActor))) break;
|
||||
cls = RUNTIME_CLASS(AActor);
|
||||
return &AFTable[mid];
|
||||
}
|
||||
|
||||
int min = 0, max = AFTable.Size() - 1;
|
||||
|
||||
while (min <= max)
|
||||
else if (lexval > 0)
|
||||
{
|
||||
int mid = (min + max) / 2;
|
||||
int lexval = stricmp(cls->TypeName.GetChars(), AFTable[mid].ClassName + 1);
|
||||
if (lexval == 0) lexval = stricmp(string, AFTable[mid].FuncName);
|
||||
if (lexval == 0)
|
||||
{
|
||||
return &AFTable[mid];
|
||||
}
|
||||
else if (lexval > 0)
|
||||
{
|
||||
min = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
max = mid - 1;
|
||||
}
|
||||
min = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
max = mid - 1;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
|
|
@ -74,8 +74,6 @@
|
|||
#include "a_health.h"
|
||||
#include "a_keys.h"
|
||||
|
||||
extern TArray<PClassActor **> OptionalClassPtrs;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Gets a class pointer and performs an error check for correct type
|
||||
|
@ -666,7 +664,7 @@ DEFINE_PROPERTY(damage, X, Actor)
|
|||
|
||||
defaults->DamageVal = dmgval;
|
||||
// Only DECORATE can get here with a valid expression.
|
||||
CreateDamageFunction(bag.Info, defaults, id, true);
|
||||
CreateDamageFunction(bag.Info, defaults, id, true, bag.Lumpnum);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -2307,8 +2305,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, color, C_f, Inventory)
|
|||
*pBlendColor = MakeSpecialColormap(65535);
|
||||
return;
|
||||
}
|
||||
|
||||
color = V_GetColor(NULL, name);
|
||||
color = V_GetColor(NULL, name, &bag.ScriptPosition);
|
||||
}
|
||||
if (PROP_PARM_COUNT > 2)
|
||||
{
|
||||
|
@ -2998,7 +2995,6 @@ DEFINE_CLASS_PROPERTY(playerclass, S, MorphProjectile)
|
|||
{
|
||||
PROP_STRING_PARM(str, 0);
|
||||
defaults->PlayerClass = FindClassTentativePlayerPawn(str, bag.fromDecorate);
|
||||
if (bag.fromDecorate) OptionalClassPtrs.Push((PClassActor**)&defaults->PlayerClass);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -3008,7 +3004,6 @@ DEFINE_CLASS_PROPERTY(monsterclass, S, MorphProjectile)
|
|||
{
|
||||
PROP_STRING_PARM(str, 0);
|
||||
defaults->MonsterClass = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate);
|
||||
if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->MonsterClass);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -3036,7 +3031,6 @@ DEFINE_CLASS_PROPERTY(morphflash, S, MorphProjectile)
|
|||
{
|
||||
PROP_STRING_PARM(str, 0);
|
||||
defaults->MorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate);
|
||||
if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->MorphFlash);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -3046,7 +3040,6 @@ DEFINE_CLASS_PROPERTY(unmorphflash, S, MorphProjectile)
|
|||
{
|
||||
PROP_STRING_PARM(str, 0);
|
||||
defaults->UnMorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate);
|
||||
if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->UnMorphFlash);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -3056,7 +3049,6 @@ DEFINE_CLASS_PROPERTY(playerclass, S, PowerMorph)
|
|||
{
|
||||
PROP_STRING_PARM(str, 0);
|
||||
defaults->PlayerClass = FindClassTentativePlayerPawn(str, bag.fromDecorate);
|
||||
if (bag.fromDecorate) OptionalClassPtrs.Push((PClassActor**)&defaults->PlayerClass);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -3075,7 +3067,6 @@ DEFINE_CLASS_PROPERTY(morphflash, S, PowerMorph)
|
|||
{
|
||||
PROP_STRING_PARM(str, 0);
|
||||
defaults->MorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate);
|
||||
if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->MorphFlash);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -3085,7 +3076,6 @@ DEFINE_CLASS_PROPERTY(unmorphflash, S, PowerMorph)
|
|||
{
|
||||
PROP_STRING_PARM(str, 0);
|
||||
defaults->UnMorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate);
|
||||
if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->UnMorphFlash);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "autosegs.h"
|
||||
#include "vectors.h"
|
||||
#include "cmdlib.h"
|
||||
#include "doomerrors.h"
|
||||
|
||||
#define MAX_RETURNS 8 // Maximum number of results a function called by script code can return
|
||||
#define MAX_TRY_DEPTH 8 // Maximum number of nested TRYs in a single function
|
||||
|
@ -130,6 +131,11 @@ enum
|
|||
CAST_V32S,
|
||||
CAST_SID2S,
|
||||
CAST_TID2S,
|
||||
|
||||
CASTB_I,
|
||||
CASTB_F,
|
||||
CASTB_A,
|
||||
CASTB_S
|
||||
};
|
||||
|
||||
// Register types for VMParam
|
||||
|
@ -184,6 +190,14 @@ enum EVMAbortException
|
|||
X_BAD_SELF,
|
||||
};
|
||||
|
||||
class CVMAbortException : public CDoomError
|
||||
{
|
||||
public:
|
||||
static FString stacktrace;
|
||||
CVMAbortException(EVMAbortException reason, const char *moreinfo, va_list ap);
|
||||
void MaybePrintMessage();
|
||||
};
|
||||
|
||||
enum EVMOpMode
|
||||
{
|
||||
MODE_ASHIFT = 0,
|
||||
|
@ -795,6 +809,12 @@ union FVoidObj
|
|||
void *v;
|
||||
};
|
||||
|
||||
struct FStatementInfo
|
||||
{
|
||||
uint16_t InstructionIndex;
|
||||
uint16_t LineNumber;
|
||||
};
|
||||
|
||||
class VMScriptFunction : public VMFunction
|
||||
{
|
||||
DECLARE_CLASS(VMScriptFunction, VMFunction);
|
||||
|
@ -802,18 +822,21 @@ public:
|
|||
VMScriptFunction(FName name=NAME_None);
|
||||
~VMScriptFunction();
|
||||
size_t PropagateMark();
|
||||
void Alloc(int numops, int numkonstd, int numkonstf, int numkonsts, int numkonsta);
|
||||
void Alloc(int numops, int numkonstd, int numkonstf, int numkonsts, int numkonsta, int numlinenumbers);
|
||||
|
||||
VM_ATAG *KonstATags() { return (VM_UBYTE *)(KonstA + NumKonstA); }
|
||||
const VM_ATAG *KonstATags() const { return (VM_UBYTE *)(KonstA + NumKonstA); }
|
||||
|
||||
VMOP *Code;
|
||||
FStatementInfo *LineInfo;
|
||||
FString SourceFileName;
|
||||
int *KonstD;
|
||||
double *KonstF;
|
||||
FString *KonstS;
|
||||
FVoidObj *KonstA;
|
||||
int ExtraSpace;
|
||||
int CodeSize; // Size of code in instructions (not bytes)
|
||||
unsigned LineInfoCount;
|
||||
VM_UBYTE NumRegD;
|
||||
VM_UBYTE NumRegF;
|
||||
VM_UBYTE NumRegS;
|
||||
|
@ -829,6 +852,7 @@ public:
|
|||
void InitExtra(void *addr);
|
||||
void DestroyExtra(void *addr);
|
||||
int AllocExtraStack(PType *type);
|
||||
int PCToLine(const VMOP *pc);
|
||||
};
|
||||
|
||||
class VMFrameStack
|
||||
|
@ -946,6 +970,9 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
|
||||
// Use these to collect the parameters in a native function.
|
||||
// variable name <x> at position <p>
|
||||
void NullParam(const char *varname);
|
||||
|
||||
#define PARAM_NULLCHECK(ptr, var) (ptr == nullptr? NullParam(#var), ptr : ptr)
|
||||
|
||||
// For required parameters.
|
||||
#define PARAM_INT_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); int x = param[p].i;
|
||||
|
@ -961,6 +988,9 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
#define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)param[p].a;
|
||||
#define PARAM_OBJECT_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); type *x = (type *)param[p].a; assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type)));
|
||||
#define PARAM_CLASS_AT(p,x,base) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); base::MetaClass *x = (base::MetaClass *)param[p].a; assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base)));
|
||||
#define PARAM_POINTER_NOT_NULL_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)PARAM_NULLCHECK(param[p].a, #x);
|
||||
#define PARAM_OBJECT_NOT_NULL_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); type *x = (type *)PARAM_NULLCHECK(param[p].a, #x); assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type)));
|
||||
#define PARAM_CLASS_NOT_NULL_AT(p,x,base) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); base::MetaClass *x = (base::MetaClass *)PARAM_NULLCHECK(param[p].a, #x); assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base)));
|
||||
|
||||
#define PARAM_EXISTS(p) ((p) < numparam)
|
||||
#define ASSERTINT(p) assert((p).Type == REGT_INT)
|
||||
|
@ -983,6 +1013,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
#define PARAM_POINTER_DEF_AT(p,x,t) t *x; if (PARAM_EXISTS(p)) { ASSERTPOINTER(param[p]); x = (t*)param[p].a; } else { ASSERTPOINTER(defaultparam[p]); x = (t*)defaultparam[p].a; }
|
||||
#define PARAM_OBJECT_DEF_AT(p,x,t) t *x; if (PARAM_EXISTS(p)) { ASSERTOBJECT(param[p]); x = (t*)param[p].a; } else { ASSERTOBJECT(defaultparam[p]); x = (t*)defaultparam[p].a; }
|
||||
#define PARAM_CLASS_DEF_AT(p,x,t) t::MetaClass *x; if (PARAM_EXISTS(p)) { ASSERTOBJECT(param[p]); x = (t::MetaClass*)param[p].a; } else { ASSERTOBJECT(defaultparam[p]); x = (t::MetaClass*)defaultparam[p].a; }
|
||||
#define PARAM_CLASS_DEF_NOT_NULL_AT(p,x,t) t::MetaClass *x; if (PARAM_EXISTS(p)) { ASSERTOBJECT(param[p]); x = (t::MetaClass*)PARAM_NULLCHECK(param[p].a, #x); } else { ASSERTOBJECT(defaultparam[p]); x = (t::MetaClass*)PARAM_NULLCHECK(defaultparam[p].a, #x); }
|
||||
|
||||
// The above, but with an automatically increasing position index.
|
||||
#define PARAM_PROLOGUE int paramnum = -1;
|
||||
|
@ -1000,6 +1031,9 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
#define PARAM_POINTER(x,type) ++paramnum; PARAM_POINTER_AT(paramnum,x,type)
|
||||
#define PARAM_OBJECT(x,type) ++paramnum; PARAM_OBJECT_AT(paramnum,x,type)
|
||||
#define PARAM_CLASS(x,base) ++paramnum; PARAM_CLASS_AT(paramnum,x,base)
|
||||
#define PARAM_POINTER_NOT_NULL(x,type) ++paramnum; PARAM_POINTER_NOT_NULL_AT(paramnum,x,type)
|
||||
#define PARAM_OBJECT_NOT_NULL(x,type) ++paramnum; PARAM_OBJECT_NOT_NULL_AT(paramnum,x,type)
|
||||
#define PARAM_CLASS_NOT_NULL(x,base) ++paramnum; PARAM_CLASS_NOT_NULL_AT(paramnum,x,base)
|
||||
|
||||
#define PARAM_INT_DEF(x) ++paramnum; PARAM_INT_DEF_AT(paramnum,x)
|
||||
#define PARAM_BOOL_DEF(x) ++paramnum; PARAM_BOOL_DEF_AT(paramnum,x)
|
||||
|
@ -1014,6 +1048,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
#define PARAM_POINTER_DEF(x,type) ++paramnum; PARAM_POINTER_DEF_AT(paramnum,x,type)
|
||||
#define PARAM_OBJECT_DEF(x,type) ++paramnum; PARAM_OBJECT_DEF_AT(paramnum,x,type)
|
||||
#define PARAM_CLASS_DEF(x,base) ++paramnum; PARAM_CLASS_DEF_AT(paramnum,x,base)
|
||||
#define PARAM_CLASS_DEF_NOT_NULL(x,base) ++paramnum; PARAM_CLASS_DEF_NOT_NULL_AT(paramnum,x,base)
|
||||
|
||||
typedef int(*actionf_p)(VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/
|
||||
|
||||
|
@ -1115,8 +1150,8 @@ class AActor;
|
|||
// callingstate - State this action was called from
|
||||
#define PARAM_ACTION_PROLOGUE(type) \
|
||||
PARAM_PROLOGUE; \
|
||||
PARAM_OBJECT (self, type); \
|
||||
PARAM_OBJECT (stateowner, AActor) \
|
||||
PARAM_OBJECT (self, AActor); \
|
||||
PARAM_OBJECT (stateowner, type) \
|
||||
PARAM_POINTER (stateinfo, FStateParamInfo) \
|
||||
|
||||
// Number of action paramaters
|
||||
|
|
|
@ -75,18 +75,45 @@ VMFunctionBuilder::~VMFunctionBuilder()
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// VMFunctionBuilder :: MakeFunction
|
||||
// VMFunctionBuilder :: BeginStatement
|
||||
//
|
||||
// Creates a new VMScriptFunction out of the data passed to this class.
|
||||
// Records the start of a new statement.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void VMFunctionBuilder::BeginStatement(FxExpression *stmt)
|
||||
{
|
||||
// pop empty statement records.
|
||||
while (LineNumbers.Size() > 0 && LineNumbers.Last().InstructionIndex == Code.Size()) LineNumbers.Pop();
|
||||
// only add a new entry if the line number differs.
|
||||
if (LineNumbers.Size() == 0 || stmt->ScriptPosition.ScriptLine != LineNumbers.Last().LineNumber)
|
||||
{
|
||||
FStatementInfo si = { (uint16_t)Code.Size(), (uint16_t)stmt->ScriptPosition.ScriptLine };
|
||||
LineNumbers.Push(si);
|
||||
}
|
||||
StatementStack.Push(stmt);
|
||||
}
|
||||
|
||||
void VMFunctionBuilder::EndStatement()
|
||||
{
|
||||
// pop empty statement records.
|
||||
while (LineNumbers.Size() > 0 && LineNumbers.Last().InstructionIndex == Code.Size()) LineNumbers.Pop();
|
||||
StatementStack.Pop();
|
||||
// Re-enter the previous statement.
|
||||
if (StatementStack.Size() > 0)
|
||||
{
|
||||
FStatementInfo si = { (uint16_t)Code.Size(), (uint16_t)StatementStack.Last()->ScriptPosition.ScriptLine };
|
||||
LineNumbers.Push(si);
|
||||
}
|
||||
}
|
||||
|
||||
void VMFunctionBuilder::MakeFunction(VMScriptFunction *func)
|
||||
{
|
||||
func->Alloc(Code.Size(), IntConstantList.Size(), FloatConstantList.Size(), StringConstantList.Size(), AddressConstantList.Size());
|
||||
func->Alloc(Code.Size(), IntConstantList.Size(), FloatConstantList.Size(), StringConstantList.Size(), AddressConstantList.Size(), LineNumbers.Size());
|
||||
|
||||
// Copy code block.
|
||||
memcpy(func->Code, &Code[0], Code.Size() * sizeof(VMOP));
|
||||
memcpy(func->LineInfo, &LineNumbers[0], LineNumbers.Size() * sizeof(LineNumbers[0]));
|
||||
|
||||
// Create constant tables.
|
||||
if (IntConstantList.Size() > 0)
|
||||
|
@ -734,6 +761,13 @@ void VMFunctionBuilder::Backpatch(size_t loc, size_t target)
|
|||
Code[loc].i24 = offset;
|
||||
}
|
||||
|
||||
void VMFunctionBuilder::BackpatchList(TArray<size_t> &locs, size_t target)
|
||||
{
|
||||
for (auto loc : locs)
|
||||
Backpatch(loc, target);
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// VMFunctionBuilder :: BackpatchToHere
|
||||
|
@ -748,6 +782,12 @@ void VMFunctionBuilder::BackpatchToHere(size_t loc)
|
|||
Backpatch(loc, Code.Size());
|
||||
}
|
||||
|
||||
void VMFunctionBuilder::BackpatchListToHere(TArray<size_t> &locs)
|
||||
{
|
||||
for (auto loc : locs)
|
||||
Backpatch(loc, Code.Size());
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FFunctionBuildList
|
||||
|
@ -867,7 +907,10 @@ void FFunctionBuildList::Build()
|
|||
// Emit code
|
||||
try
|
||||
{
|
||||
sfunc->SourceFileName = item.Code->ScriptPosition.FileName; // remember the file name for printing error messages if something goes wrong in the VM.
|
||||
buildit.BeginStatement(item.Code);
|
||||
item.Code->Emit(&buildit);
|
||||
buildit.EndStatement();
|
||||
buildit.MakeFunction(sfunc);
|
||||
sfunc->NumArgs = 0;
|
||||
// NumArgs for the VMFunction must be the amount of stack elements, which can differ from the amount of logical function arguments if vectors are in the list.
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "dobject.h"
|
||||
|
||||
class VMFunctionBuilder;
|
||||
class FxExpression;
|
||||
|
||||
struct ExpEmit
|
||||
{
|
||||
|
@ -42,6 +43,8 @@ public:
|
|||
VMFunctionBuilder(int numimplicits);
|
||||
~VMFunctionBuilder();
|
||||
|
||||
void BeginStatement(FxExpression *stmt);
|
||||
void EndStatement();
|
||||
void MakeFunction(VMScriptFunction *func);
|
||||
|
||||
// Returns the constant register holding the value.
|
||||
|
@ -69,6 +72,8 @@ public:
|
|||
|
||||
void Backpatch(size_t addr, size_t target);
|
||||
void BackpatchToHere(size_t addr);
|
||||
void BackpatchList(TArray<size_t> &addrs, size_t target);
|
||||
void BackpatchListToHere(TArray<size_t> &addrs);
|
||||
|
||||
// Write out complete constant tables.
|
||||
void FillIntConstants(int *konst);
|
||||
|
@ -95,6 +100,9 @@ private:
|
|||
VM_ATAG Tag;
|
||||
};
|
||||
|
||||
TArray<FStatementInfo> LineNumbers;
|
||||
TArray<FxExpression *> StatementStack;
|
||||
|
||||
TArray<int> IntConstantList;
|
||||
TArray<double> FloatConstantList;
|
||||
TArray<void *> AddressConstantList;
|
||||
|
@ -141,7 +149,7 @@ class FFunctionBuildList
|
|||
TArray<Item> mItems;
|
||||
|
||||
public:
|
||||
VMFunction *AddFunction(PFunction *func, FxExpression *code, const FString &name, bool fromdecorate, int currentstate = -1, int statecnt = 0, int lumpnum = -1);
|
||||
VMFunction *AddFunction(PFunction *func, FxExpression *code, const FString &name, bool fromdecorate, int currentstate, int statecnt, int lumpnum);
|
||||
void Build();
|
||||
};
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@
|
|||
#define THROW MODE_AIMMZ | MODE_BCTHROW
|
||||
#define CATCH MODE_AIMMZ | MODE_BCCATCH
|
||||
#define CAST MODE_AX | MODE_BX | MODE_CIMMZ | MODE_BCCAST
|
||||
#define CASTB MODE_AI | MODE_BX | MODE_CIMMZ | MODE_BCCAST
|
||||
|
||||
#define RSRSRS MODE_AS | MODE_BS | MODE_CS
|
||||
#define RIRS MODE_AI | MODE_BS | MODE_CUNUSED
|
||||
|
@ -381,10 +382,18 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
break;
|
||||
|
||||
default:
|
||||
|
||||
|
||||
if ((mode & MODE_BCTYPE) == MODE_BCCAST)
|
||||
{
|
||||
switch (code[i].c)
|
||||
{
|
||||
case CASTB_I:
|
||||
mode = MODE_AI | MODE_BI | MODE_CUNUSED;
|
||||
break;
|
||||
case CASTB_A:
|
||||
mode = MODE_AI | MODE_BP | MODE_CUNUSED;
|
||||
break;
|
||||
case CAST_I2F:
|
||||
case CAST_U2F:
|
||||
mode = MODE_AF | MODE_BI | MODE_CUNUSED;
|
||||
|
@ -398,6 +407,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
break;
|
||||
case CAST_F2I:
|
||||
case CAST_F2U:
|
||||
case CASTB_F:
|
||||
mode = MODE_AI | MODE_BF | MODE_CUNUSED;
|
||||
break;
|
||||
case CAST_F2S:
|
||||
|
@ -412,6 +422,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
case CAST_S2So:
|
||||
case CAST_S2N:
|
||||
case CAST_S2I:
|
||||
case CASTB_S:
|
||||
mode = MODE_AI | MODE_BS | MODE_CUNUSED;
|
||||
break;
|
||||
case CAST_S2F:
|
||||
|
|
|
@ -40,6 +40,11 @@
|
|||
#include "textures/textures.h"
|
||||
#include "math/cmath.h"
|
||||
|
||||
// This must be a separate function because the VC compiler would otherwise allocate memory on the stack for every separate instance of the exception object that may get thrown.
|
||||
void ThrowAbortException(EVMAbortException reason, const char *moreinfo, ...);
|
||||
// intentionally implemented in a different source file tp prevent inlining.
|
||||
void ThrowVMException(VMException *x);
|
||||
|
||||
#define IMPLEMENT_VMEXEC
|
||||
|
||||
#if !defined(COMPGOTO) && defined(__GNUC__)
|
||||
|
@ -82,8 +87,6 @@
|
|||
#define ASSERTKA(x) assert(sfunc != NULL && (unsigned)(x) < sfunc->NumKonstA)
|
||||
#define ASSERTKS(x) assert(sfunc != NULL && (unsigned)(x) < sfunc->NumKonstS)
|
||||
|
||||
#define THROW(x) throw(EVMAbortException(x))
|
||||
|
||||
#define CMPJMP(test) \
|
||||
if ((test) == (a & CMP_CHECK)) { \
|
||||
assert(pc[1].op == OP_JMP); \
|
||||
|
@ -93,7 +96,7 @@
|
|||
}
|
||||
|
||||
#define GETADDR(a,o,x) \
|
||||
if (a == NULL) { THROW(x); } \
|
||||
if (a == NULL) { ThrowAbortException(x, nullptr); } \
|
||||
ptr = (VM_SBYTE *)a + o
|
||||
|
||||
static const VM_UWORD ZapTable[16] =
|
||||
|
@ -228,3 +231,5 @@ void VMFillParams(VMValue *params, VMFrame *callee, int numparam)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#error vmexec.h must not be #included outside vmexec.cpp. Use vm.h instead.
|
||||
#endif
|
||||
|
||||
|
||||
static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret)
|
||||
{
|
||||
#if COMPGOTO
|
||||
|
@ -419,12 +418,12 @@ begin:
|
|||
if (C == CAST_I2F)
|
||||
{
|
||||
ASSERTF(a); ASSERTD(B);
|
||||
reg.f[A] = reg.d[B];
|
||||
reg.f[a] = reg.d[B];
|
||||
}
|
||||
else if (C == CAST_F2I)
|
||||
{
|
||||
ASSERTD(a); ASSERTF(B);
|
||||
reg.d[A] = (int)reg.f[B];
|
||||
reg.d[a] = (int)reg.f[B];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -432,6 +431,29 @@ begin:
|
|||
}
|
||||
NEXTOP;
|
||||
|
||||
OP(CASTB):
|
||||
if (C == CASTB_I)
|
||||
{
|
||||
ASSERTD(a); ASSERTD(B);
|
||||
reg.d[a] = !!reg.d[B];
|
||||
}
|
||||
else if (C == CASTB_F)
|
||||
{
|
||||
ASSERTD(a); ASSERTF(B);
|
||||
reg.d[a] = reg.f[B] != 0;
|
||||
}
|
||||
else if (C == CASTB_A)
|
||||
{
|
||||
ASSERTD(a); ASSERTA(B);
|
||||
reg.d[a] = reg.a[B] != nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERTD(a); ASSERTS(B);
|
||||
reg.d[a] = reg.s[B].Len() > 0;
|
||||
}
|
||||
NEXTOP;
|
||||
|
||||
OP(TEST):
|
||||
ASSERTD(a);
|
||||
if (reg.d[a] != BC)
|
||||
|
@ -573,7 +595,17 @@ begin:
|
|||
FillReturns(reg, f, returns, pc+1, C);
|
||||
if (call->Native)
|
||||
{
|
||||
numret = static_cast<VMNativeFunction *>(call)->NativeCall(reg.param + f->NumParam - B, call->DefaultArgs, B, returns, C);
|
||||
try
|
||||
{
|
||||
numret = static_cast<VMNativeFunction *>(call)->NativeCall(reg.param + f->NumParam - B, call->DefaultArgs, B, returns, C);
|
||||
}
|
||||
catch (CVMAbortException &err)
|
||||
{
|
||||
err.MaybePrintMessage();
|
||||
err.stacktrace.AppendFormat("Called from %s\n", call->PrintableName.GetChars());
|
||||
// PrintParameters(reg.param + f->NumParam - B, B);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -617,7 +649,17 @@ begin:
|
|||
|
||||
if (call->Native)
|
||||
{
|
||||
return static_cast<VMNativeFunction *>(call)->NativeCall(reg.param + f->NumParam - B, call->DefaultArgs, B, ret, numret);
|
||||
try
|
||||
{
|
||||
return static_cast<VMNativeFunction *>(call)->NativeCall(reg.param + f->NumParam - B, call->DefaultArgs, B, ret, numret);
|
||||
}
|
||||
catch (CVMAbortException &err)
|
||||
{
|
||||
err.MaybePrintMessage();
|
||||
err.stacktrace.AppendFormat("Called from %s\n", call->PrintableName.GetChars());
|
||||
// PrintParameters(reg.param + f->NumParam - B, B);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // FIXME: Not a true tail call
|
||||
|
@ -681,7 +723,7 @@ begin:
|
|||
assert(try_depth < MAX_TRY_DEPTH);
|
||||
if (try_depth >= MAX_TRY_DEPTH)
|
||||
{
|
||||
THROW(X_TOO_MANY_TRIES);
|
||||
ThrowAbortException(X_TOO_MANY_TRIES, nullptr);
|
||||
}
|
||||
assert((pc + JMPOFS(pc) + 1)->op == OP_CATCH);
|
||||
exception_frames[try_depth++] = pc + JMPOFS(pc) + 1;
|
||||
|
@ -694,17 +736,17 @@ begin:
|
|||
if (a == 0)
|
||||
{
|
||||
ASSERTA(B);
|
||||
throw((VMException *)reg.a[B]);
|
||||
ThrowVMException((VMException *)reg.a[B]);
|
||||
}
|
||||
else if (a == 1)
|
||||
{
|
||||
ASSERTKA(B);
|
||||
assert(konstatag[B] == ATAG_OBJECT);
|
||||
throw((VMException *)konsta[B].o);
|
||||
ThrowVMException((VMException *)konsta[B].o);
|
||||
}
|
||||
else
|
||||
{
|
||||
THROW(BC);
|
||||
ThrowAbortException(EVMAbortException(BC), nullptr);
|
||||
}
|
||||
NEXTOP;
|
||||
OP(CATCH):
|
||||
|
@ -713,13 +755,10 @@ begin:
|
|||
assert(0);
|
||||
NEXTOP;
|
||||
|
||||
// Fixme: This really needs to throw something more informative than a number. Printing the message here instead of passing it to the exception is not sufficient.
|
||||
OP(BOUND):
|
||||
if (reg.d[a] >= BC)
|
||||
{
|
||||
assert(false);
|
||||
Printf("Array access out of bounds: Max. index = %u, current index = %u\n", BC, reg.d[a]);
|
||||
THROW(X_ARRAY_OUT_OF_BOUNDS);
|
||||
ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", BC, reg.d[a]);
|
||||
}
|
||||
NEXTOP;
|
||||
|
||||
|
@ -727,9 +766,7 @@ begin:
|
|||
ASSERTKD(BC);
|
||||
if (reg.d[a] >= konstd[BC])
|
||||
{
|
||||
assert(false);
|
||||
Printf("Array access out of bounds: Max. index = %u, current index = %u\n", konstd[BC], reg.d[a]);
|
||||
THROW(X_ARRAY_OUT_OF_BOUNDS);
|
||||
ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", konstd[BC], reg.d[a]);
|
||||
}
|
||||
NEXTOP;
|
||||
|
||||
|
@ -737,9 +774,7 @@ begin:
|
|||
ASSERTD(B);
|
||||
if (reg.d[a] >= reg.d[B])
|
||||
{
|
||||
assert(false);
|
||||
Printf("Array access out of bounds: Max. index = %u, current index = %u\n", reg.d[B], reg.d[a]);
|
||||
THROW(X_ARRAY_OUT_OF_BOUNDS);
|
||||
ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", reg.d[B], reg.d[a]);
|
||||
}
|
||||
NEXTOP;
|
||||
|
||||
|
@ -886,7 +921,7 @@ begin:
|
|||
ASSERTD(a); ASSERTD(B); ASSERTD(C);
|
||||
if (reg.d[C] == 0)
|
||||
{
|
||||
THROW(X_DIVISION_BY_ZERO);
|
||||
ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
|
||||
}
|
||||
reg.d[a] = reg.d[B] / reg.d[C];
|
||||
NEXTOP;
|
||||
|
@ -894,7 +929,7 @@ begin:
|
|||
ASSERTD(a); ASSERTD(B); ASSERTKD(C);
|
||||
if (konstd[C] == 0)
|
||||
{
|
||||
THROW(X_DIVISION_BY_ZERO);
|
||||
ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
|
||||
}
|
||||
reg.d[a] = reg.d[B] / konstd[C];
|
||||
NEXTOP;
|
||||
|
@ -902,7 +937,7 @@ begin:
|
|||
ASSERTD(a); ASSERTKD(B); ASSERTD(C);
|
||||
if (reg.d[C] == 0)
|
||||
{
|
||||
THROW(X_DIVISION_BY_ZERO);
|
||||
ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
|
||||
}
|
||||
reg.d[a] = konstd[B] / reg.d[C];
|
||||
NEXTOP;
|
||||
|
@ -911,7 +946,7 @@ begin:
|
|||
ASSERTD(a); ASSERTD(B); ASSERTD(C);
|
||||
if (reg.d[C] == 0)
|
||||
{
|
||||
THROW(X_DIVISION_BY_ZERO);
|
||||
ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
|
||||
}
|
||||
reg.d[a] = int((unsigned)reg.d[B] / (unsigned)reg.d[C]);
|
||||
NEXTOP;
|
||||
|
@ -919,7 +954,7 @@ begin:
|
|||
ASSERTD(a); ASSERTD(B); ASSERTKD(C);
|
||||
if (konstd[C] == 0)
|
||||
{
|
||||
THROW(X_DIVISION_BY_ZERO);
|
||||
ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
|
||||
}
|
||||
reg.d[a] = int((unsigned)reg.d[B] / (unsigned)konstd[C]);
|
||||
NEXTOP;
|
||||
|
@ -927,7 +962,7 @@ begin:
|
|||
ASSERTD(a); ASSERTKD(B); ASSERTD(C);
|
||||
if (reg.d[C] == 0)
|
||||
{
|
||||
THROW(X_DIVISION_BY_ZERO);
|
||||
ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
|
||||
}
|
||||
reg.d[a] = int((unsigned)konstd[B] / (unsigned)reg.d[C]);
|
||||
NEXTOP;
|
||||
|
@ -936,7 +971,7 @@ begin:
|
|||
ASSERTD(a); ASSERTD(B); ASSERTD(C);
|
||||
if (reg.d[C] == 0)
|
||||
{
|
||||
THROW(X_DIVISION_BY_ZERO);
|
||||
ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
|
||||
}
|
||||
reg.d[a] = reg.d[B] % reg.d[C];
|
||||
NEXTOP;
|
||||
|
@ -944,7 +979,7 @@ begin:
|
|||
ASSERTD(a); ASSERTD(B); ASSERTKD(C);
|
||||
if (konstd[C] == 0)
|
||||
{
|
||||
THROW(X_DIVISION_BY_ZERO);
|
||||
ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
|
||||
}
|
||||
reg.d[a] = reg.d[B] % konstd[C];
|
||||
NEXTOP;
|
||||
|
@ -952,7 +987,7 @@ begin:
|
|||
ASSERTD(a); ASSERTKD(B); ASSERTD(C);
|
||||
if (reg.d[C] == 0)
|
||||
{
|
||||
THROW(X_DIVISION_BY_ZERO);
|
||||
ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
|
||||
}
|
||||
reg.d[a] = konstd[B] % reg.d[C];
|
||||
NEXTOP;
|
||||
|
@ -961,7 +996,7 @@ begin:
|
|||
ASSERTD(a); ASSERTD(B); ASSERTD(C);
|
||||
if (reg.d[C] == 0)
|
||||
{
|
||||
THROW(X_DIVISION_BY_ZERO);
|
||||
ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
|
||||
}
|
||||
reg.d[a] = int((unsigned)reg.d[B] % (unsigned)reg.d[C]);
|
||||
NEXTOP;
|
||||
|
@ -969,7 +1004,7 @@ begin:
|
|||
ASSERTD(a); ASSERTD(B); ASSERTKD(C);
|
||||
if (konstd[C] == 0)
|
||||
{
|
||||
THROW(X_DIVISION_BY_ZERO);
|
||||
ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
|
||||
}
|
||||
reg.d[a] = int((unsigned)reg.d[B] % (unsigned)konstd[C]);
|
||||
NEXTOP;
|
||||
|
@ -977,7 +1012,7 @@ begin:
|
|||
ASSERTD(a); ASSERTKD(B); ASSERTD(C);
|
||||
if (reg.d[C] == 0)
|
||||
{
|
||||
THROW(X_DIVISION_BY_ZERO);
|
||||
ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
|
||||
}
|
||||
reg.d[a] = int((unsigned)konstd[B] % (unsigned)reg.d[C]);
|
||||
NEXTOP;
|
||||
|
@ -1155,7 +1190,7 @@ begin:
|
|||
ASSERTF(a); ASSERTF(B); ASSERTF(C);
|
||||
if (reg.f[C] == 0.)
|
||||
{
|
||||
THROW(X_DIVISION_BY_ZERO);
|
||||
ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
|
||||
}
|
||||
reg.f[a] = reg.f[B] / reg.f[C];
|
||||
NEXTOP;
|
||||
|
@ -1163,7 +1198,7 @@ begin:
|
|||
ASSERTF(a); ASSERTF(B); ASSERTKF(C);
|
||||
if (konstf[C] == 0.)
|
||||
{
|
||||
THROW(X_DIVISION_BY_ZERO);
|
||||
ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
|
||||
}
|
||||
reg.f[a] = reg.f[B] / konstf[C];
|
||||
NEXTOP;
|
||||
|
@ -1171,7 +1206,7 @@ begin:
|
|||
ASSERTF(a); ASSERTKF(B); ASSERTF(C);
|
||||
if (reg.f[C] == 0.)
|
||||
{
|
||||
THROW(X_DIVISION_BY_ZERO);
|
||||
ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
|
||||
}
|
||||
reg.f[a] = konstf[B] / reg.f[C];
|
||||
NEXTOP;
|
||||
|
@ -1182,7 +1217,7 @@ begin:
|
|||
Do_MODF:
|
||||
if (fc == 0.)
|
||||
{
|
||||
THROW(X_DIVISION_BY_ZERO);
|
||||
ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
|
||||
}
|
||||
reg.f[a] = luai_nummod(fb, fc);
|
||||
NEXTOP;
|
||||
|
@ -1595,6 +1630,13 @@ begin:
|
|||
// Nothing caught it. Rethrow and let somebody else deal with it.
|
||||
throw;
|
||||
}
|
||||
catch (CVMAbortException &err)
|
||||
{
|
||||
err.MaybePrintMessage();
|
||||
err.stacktrace.AppendFormat("Called from %s at %s, line %d\n", sfunc->PrintableName.GetChars(), sfunc->SourceFileName.GetChars(), sfunc->PCToLine(pc));
|
||||
// PrintParameters(reg.param + f->NumParam - B, B);
|
||||
throw;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1827,12 +1869,12 @@ static void SetReturn(const VMRegisters ®, VMFrame *frame, VMReturn *ret, VM_
|
|||
case REGT_FLOAT:
|
||||
if (regtype & REGT_KONST)
|
||||
{
|
||||
assert(regnum + ((regtype & REGT_KONST) ? 2u : 0u) < func->NumKonstF);
|
||||
assert(regnum < func->NumKonstF);
|
||||
src = &func->KonstF[regnum];
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(regnum + ((regtype & REGT_KONST) ? 2u : 0u) < frame->NumRegF);
|
||||
assert(regnum < frame->NumRegF);
|
||||
src = ®.f[regnum];
|
||||
}
|
||||
if (regtype & REGT_MULTIREG3)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright -2016 Randy Heit
|
||||
** Copyright 2016 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
|
@ -33,6 +34,7 @@
|
|||
|
||||
#include <new>
|
||||
#include "dobject.h"
|
||||
#include "v_text.h"
|
||||
|
||||
IMPLEMENT_CLASS(VMException, false, false)
|
||||
IMPLEMENT_CLASS(VMFunction, true, true)
|
||||
|
@ -48,11 +50,13 @@ VMScriptFunction::VMScriptFunction(FName name)
|
|||
{
|
||||
Native = false;
|
||||
Name = name;
|
||||
LineInfo = nullptr;
|
||||
Code = NULL;
|
||||
KonstD = NULL;
|
||||
KonstF = NULL;
|
||||
KonstS = NULL;
|
||||
KonstA = NULL;
|
||||
LineInfoCount = 0;
|
||||
ExtraSpace = 0;
|
||||
CodeSize = 0;
|
||||
NumRegD = 0;
|
||||
|
@ -82,7 +86,7 @@ VMScriptFunction::~VMScriptFunction()
|
|||
}
|
||||
}
|
||||
|
||||
void VMScriptFunction::Alloc(int numops, int numkonstd, int numkonstf, int numkonsts, int numkonsta)
|
||||
void VMScriptFunction::Alloc(int numops, int numkonstd, int numkonstf, int numkonsts, int numkonsta, int numlinenumbers)
|
||||
{
|
||||
assert(Code == NULL);
|
||||
assert(numops > 0);
|
||||
|
@ -90,14 +94,27 @@ void VMScriptFunction::Alloc(int numops, int numkonstd, int numkonstf, int numko
|
|||
assert(numkonstf >= 0 && numkonstf <= 65535);
|
||||
assert(numkonsts >= 0 && numkonsts <= 65535);
|
||||
assert(numkonsta >= 0 && numkonsta <= 65535);
|
||||
assert(numlinenumbers >= 0 && numlinenumbers <= 65535);
|
||||
void *mem = M_Malloc(numops * sizeof(VMOP) +
|
||||
numkonstd * sizeof(int) +
|
||||
numkonstf * sizeof(double) +
|
||||
numkonsts * sizeof(FString) +
|
||||
numkonsta * (sizeof(FVoidObj) + 1));
|
||||
numkonsta * (sizeof(FVoidObj) + 1) +
|
||||
numlinenumbers * sizeof(FStatementInfo));
|
||||
Code = (VMOP *)mem;
|
||||
mem = (void *)((VMOP *)mem + numops);
|
||||
|
||||
if (numlinenumbers > 0)
|
||||
{
|
||||
LineInfo = (FStatementInfo*)mem;
|
||||
LineInfoCount = numlinenumbers;
|
||||
mem = LineInfo + numlinenumbers;
|
||||
}
|
||||
else
|
||||
{
|
||||
LineInfo = nullptr;
|
||||
LineInfoCount = 0;
|
||||
}
|
||||
if (numkonstd > 0)
|
||||
{
|
||||
KonstD = (int *)mem;
|
||||
|
@ -190,6 +207,20 @@ int VMScriptFunction::AllocExtraStack(PType *type)
|
|||
return address;
|
||||
}
|
||||
|
||||
int VMScriptFunction::PCToLine(const VMOP *pc)
|
||||
{
|
||||
int PCIndex = int(pc - Code);
|
||||
if (LineInfoCount == 1) return LineInfo[0].LineNumber;
|
||||
for (unsigned i = 1; i < LineInfoCount; i++)
|
||||
{
|
||||
if (LineInfo[i].InstructionIndex > PCIndex)
|
||||
{
|
||||
return LineInfo[i - 1].LineNumber;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// VMFrame :: InitRegS
|
||||
|
@ -422,7 +453,7 @@ VMFrame *VMFrameStack::PopFrame()
|
|||
|
||||
int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMReturn *results, int numresults, VMException **trap)
|
||||
{
|
||||
assert(this == VMGlobalStack); // why would anyone even want to create a local stack?
|
||||
assert(this == &GlobalVMStack); // why would anyone even want to create a local stack?
|
||||
bool allocated = false;
|
||||
try
|
||||
{
|
||||
|
@ -453,48 +484,6 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur
|
|||
}
|
||||
throw;
|
||||
}
|
||||
catch (EVMAbortException exception)
|
||||
{
|
||||
if (allocated)
|
||||
{
|
||||
PopFrame();
|
||||
}
|
||||
if (trap != nullptr)
|
||||
{
|
||||
*trap = nullptr;
|
||||
}
|
||||
|
||||
Printf("VM execution aborted: ");
|
||||
switch (exception)
|
||||
{
|
||||
case X_READ_NIL:
|
||||
Printf("tried to read from address zero.");
|
||||
break;
|
||||
|
||||
case X_WRITE_NIL:
|
||||
Printf("tried to write to address zero.");
|
||||
break;
|
||||
|
||||
case X_TOO_MANY_TRIES:
|
||||
Printf("too many try-catch blocks.");
|
||||
break;
|
||||
|
||||
case X_ARRAY_OUT_OF_BOUNDS:
|
||||
Printf("array access out of bounds.");
|
||||
break;
|
||||
|
||||
case X_DIVISION_BY_ZERO:
|
||||
Printf("division by zero.");
|
||||
break;
|
||||
|
||||
case X_BAD_SELF:
|
||||
Printf("invalid self pointer.");
|
||||
break;
|
||||
}
|
||||
Printf("\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (allocated)
|
||||
|
@ -504,3 +493,83 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur
|
|||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// Exception stuff for the VM is intentionally placed there, because having this in vmexec.cpp would subject it to inlining
|
||||
// which we do not want because it increases the local stack requirements of Exec which are already too high.
|
||||
FString CVMAbortException::stacktrace;
|
||||
|
||||
CVMAbortException::CVMAbortException(EVMAbortException reason, const char *moreinfo, va_list ap)
|
||||
{
|
||||
SetMessage("VM execution aborted: ");
|
||||
switch (reason)
|
||||
{
|
||||
case X_READ_NIL:
|
||||
AppendMessage("tried to read from address zero.");
|
||||
break;
|
||||
|
||||
case X_WRITE_NIL:
|
||||
AppendMessage("tried to write to address zero.");
|
||||
break;
|
||||
|
||||
case X_TOO_MANY_TRIES:
|
||||
AppendMessage("too many try-catch blocks.");
|
||||
break;
|
||||
|
||||
case X_ARRAY_OUT_OF_BOUNDS:
|
||||
AppendMessage("array access out of bounds.");
|
||||
break;
|
||||
|
||||
case X_DIVISION_BY_ZERO:
|
||||
AppendMessage("division by zero.");
|
||||
break;
|
||||
|
||||
case X_BAD_SELF:
|
||||
AppendMessage("invalid self pointer.");
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
size_t len = strlen(m_Message);
|
||||
mysnprintf(m_Message + len, MAX_ERRORTEXT - len, "Unknown reason %d", reason);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (moreinfo != nullptr)
|
||||
{
|
||||
AppendMessage(" ");
|
||||
size_t len = strlen(m_Message);
|
||||
myvsnprintf(m_Message + len, MAX_ERRORTEXT - len, moreinfo, ap);
|
||||
}
|
||||
stacktrace = "";
|
||||
}
|
||||
|
||||
// Print this only once on the first catch block.
|
||||
void CVMAbortException::MaybePrintMessage()
|
||||
{
|
||||
auto m = GetMessage();
|
||||
if (m != nullptr)
|
||||
{
|
||||
Printf(TEXTCOLOR_RED);
|
||||
Printf("%s\n", m);
|
||||
SetMessage("");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ThrowAbortException(EVMAbortException reason, const char *moreinfo, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, moreinfo);
|
||||
throw CVMAbortException(reason, moreinfo, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void NullParam(const char *varname)
|
||||
{
|
||||
ThrowAbortException(X_READ_NIL, "In function parameter %s", varname);
|
||||
}
|
||||
|
||||
void ThrowVMException(VMException *x)
|
||||
{
|
||||
throw x;
|
||||
}
|
||||
|
|
|
@ -83,6 +83,7 @@ xx(MOVEA, mov, RPRP, NOP, 0, 0), // aA = aB
|
|||
xx(MOVEV2, mov2, RFRF, NOP, 0, 0), // fA = fB (2 elements)
|
||||
xx(MOVEV3, mov3, RFRF, NOP, 0, 0), // fA = fB (3 elements)
|
||||
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
|
||||
|
||||
// Control flow.
|
||||
xx(TEST, test, RII16, NOP, 0, 0), // if (dA != BC) then pc++
|
||||
|
|
|
@ -140,6 +140,7 @@ external_declaration(X) ::= class_definition(A). { X = A; /*X-overwrites-A*
|
|||
external_declaration(X) ::= struct_def(A). { X = A; /*X-overwrites-A*/ }
|
||||
external_declaration(X) ::= enum_def(A). { X = A; /*X-overwrites-A*/ }
|
||||
external_declaration(X) ::= const_def(A). { X = A; /*X-overwrites-A*/ }
|
||||
external_declaration(X) ::= include_def. { X = nullptr; }
|
||||
|
||||
/* Optional bits. */
|
||||
opt_semicolon ::= .
|
||||
|
@ -156,6 +157,11 @@ opt_expr(X) ::= .
|
|||
opt_expr(X) ::= expr(X).
|
||||
|
||||
|
||||
include_def ::= INCLUDE string_constant(A).
|
||||
{
|
||||
AddInclude(A);
|
||||
}
|
||||
|
||||
/************ Class Definition ************/
|
||||
/* Can only occur at global scope. */
|
||||
|
||||
|
|
|
@ -1842,7 +1842,7 @@ void ZCCCompiler::ProcessDefaultProperty(PClassActor *cls, ZCC_PropertyStmt *pro
|
|||
if (namenode->Id == NAME_DamageFunction)
|
||||
{
|
||||
auto x = ConvertNode(prop->Values);
|
||||
CreateDamageFunction(cls, (AActor *)bag.Info->Defaults, x, false);
|
||||
CreateDamageFunction(cls, (AActor *)bag.Info->Defaults, x, false, Lump);
|
||||
((AActor *)bag.Info->Defaults)->DamageVal = -1;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,19 @@
|
|||
#include "zcc_parser.h"
|
||||
#include "zcc_compile.h"
|
||||
|
||||
TArray<FString> Includes;
|
||||
TArray<FScriptPosition> IncludeLocs;
|
||||
|
||||
static FString ZCCTokenName(int terminal);
|
||||
void AddInclude(ZCC_ExprConstant *node)
|
||||
{
|
||||
assert(node->Type == TypeString);
|
||||
if (Includes.Find(*node->StringVal) >= Includes.Size())
|
||||
{
|
||||
Includes.Push(*node->StringVal);
|
||||
IncludeLocs.Push(*node);
|
||||
}
|
||||
}
|
||||
|
||||
#include "zcc-parse.h"
|
||||
#include "zcc-parse.c"
|
||||
|
@ -152,6 +164,7 @@ static void InitTokenMap()
|
|||
TOKENDEF2(TK_Name, ZCC_NAME, NAME_Name);
|
||||
TOKENDEF2(TK_Map, ZCC_MAP, NAME_Map);
|
||||
TOKENDEF2(TK_Array, ZCC_ARRAY, NAME_Array);
|
||||
TOKENDEF2(TK_Include, ZCC_INCLUDE, NAME_Include);
|
||||
TOKENDEF (TK_Void, ZCC_VOID);
|
||||
TOKENDEF (TK_True, ZCC_TRUE);
|
||||
TOKENDEF (TK_False, ZCC_FALSE);
|
||||
|
@ -316,42 +329,24 @@ static void DoParse(int lumpnum)
|
|||
|
||||
sc.OpenLumpNum(lumpnum);
|
||||
auto saved = sc.SavePos();
|
||||
bool parsed = false;
|
||||
if (sc.GetToken())
|
||||
{
|
||||
if (sc.TokenType == TK_Class || sc.TokenType == TK_Enum || sc.TokenType == TK_Struct || sc.TokenType == TK_Const || sc.TokenType == TK_Native)
|
||||
{
|
||||
if (sc.CheckToken(TK_Identifier))
|
||||
{
|
||||
// This looks like an actual definition file and not a file list.
|
||||
ParseSingleFile(nullptr, lumpnum, parser, state);
|
||||
parsed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!parsed)
|
||||
{
|
||||
sc.RestorePos(saved);
|
||||
// parse all files from this list in one go.
|
||||
while (sc.GetString())
|
||||
{
|
||||
FixPathSeperator(sc.String);
|
||||
if (Wads.GetLumpFile(sc.LumpNum) == 0)
|
||||
{
|
||||
int includefile = Wads.GetLumpFile(Wads.CheckNumForFullName(sc.String, true));
|
||||
if (includefile != 0)
|
||||
{
|
||||
I_FatalError("File %s is overriding core lump %s.",
|
||||
Wads.GetWadFullName(includefile), sc.String);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (f) fprintf(f, "Starting parsing %s\n", sc.String);
|
||||
#endif
|
||||
ParseSingleFile(sc.String, 0, parser, state);
|
||||
ParseSingleFile(nullptr, lumpnum, parser, state);
|
||||
for (unsigned i = 0; i < Includes.Size(); i++)
|
||||
{
|
||||
lumpnum = Wads.CheckNumForFullName(Includes[i], true);
|
||||
if (lumpnum == -1)
|
||||
{
|
||||
IncludeLocs[i].Message(MSG_ERROR, "Include script lump %s not found", Includes[i].GetChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
ParseSingleFile(nullptr, lumpnum, parser, state);
|
||||
}
|
||||
}
|
||||
Includes.Clear();
|
||||
Includes.ShrinkToFit();
|
||||
IncludeLocs.Clear();
|
||||
IncludeLocs.ShrinkToFit();
|
||||
|
||||
value.Int = -1;
|
||||
value.SourceLoc = sc.GetMessageLine();
|
||||
|
|
|
@ -182,7 +182,7 @@ void FTeam::ParseTeamDefinition (FScanner &Scan)
|
|||
|
||||
case TEAMINFO_PlayerColor:
|
||||
Scan.MustGetString ();
|
||||
Team.m_iPlayerColor = V_GetColor (NULL, Scan.String);
|
||||
Team.m_iPlayerColor = V_GetColor (NULL, Scan);
|
||||
break;
|
||||
|
||||
case TEAMINFO_TextColor:
|
||||
|
|
|
@ -1098,7 +1098,7 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, TexInit &init)
|
|||
if (!sc.CheckNumber())
|
||||
{
|
||||
sc.MustGetString();
|
||||
part.Blend = V_GetColor(NULL, sc.String);
|
||||
part.Blend = V_GetColor(NULL, sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -211,6 +211,7 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename
|
|||
int i;
|
||||
|
||||
if (lumpnum == -1) fr = &lump;
|
||||
else fr = nullptr;
|
||||
|
||||
UseType = TEX_MiscPatch;
|
||||
LeftOffset = 0;
|
||||
|
|
|
@ -2300,19 +2300,19 @@ void V_InitFontColors ()
|
|||
else if (sc.Compare ("Flat:"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
logcolor = V_GetColor (NULL, sc.String);
|
||||
logcolor = V_GetColor (NULL, sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get first color
|
||||
c = V_GetColor (NULL, sc.String);
|
||||
c = V_GetColor (NULL, sc);
|
||||
tparm.Start[0] = RPART(c);
|
||||
tparm.Start[1] = GPART(c);
|
||||
tparm.Start[2] = BPART(c);
|
||||
|
||||
// Get second color
|
||||
sc.MustGetString();
|
||||
c = V_GetColor (NULL, sc.String);
|
||||
c = V_GetColor (NULL, sc);
|
||||
tparm.End[0] = RPART(c);
|
||||
tparm.End[1] = GPART(c);
|
||||
tparm.End[2] = BPART(c);
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "i_video.h"
|
||||
#include "v_video.h"
|
||||
#include "v_text.h"
|
||||
#include "sc_man.h"
|
||||
|
||||
#include "w_wad.h"
|
||||
|
||||
|
@ -437,7 +438,7 @@ void DCanvas::ReleaseScreenshotBuffer()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int V_GetColorFromString (const DWORD *palette, const char *cstr)
|
||||
int V_GetColorFromString (const DWORD *palette, const char *cstr, FScriptPosition *sc)
|
||||
{
|
||||
int c[3], i, p;
|
||||
char val[3];
|
||||
|
@ -456,7 +457,7 @@ int V_GetColorFromString (const DWORD *palette, const char *cstr)
|
|||
{
|
||||
val[0] = cstr[1 + i*2];
|
||||
val[1] = cstr[2 + i*2];
|
||||
c[i] = ParseHex (val);
|
||||
c[i] = ParseHex (val, sc);
|
||||
}
|
||||
}
|
||||
else if (len == 4)
|
||||
|
@ -465,7 +466,7 @@ int V_GetColorFromString (const DWORD *palette, const char *cstr)
|
|||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
val[1] = val[0] = cstr[1 + i];
|
||||
c[i] = ParseHex (val);
|
||||
c[i] = ParseHex (val, sc);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -518,7 +519,7 @@ normal:
|
|||
{
|
||||
val[1] = val[0];
|
||||
}
|
||||
c[i] = ParseHex (val);
|
||||
c[i] = ParseHex (val, sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -538,7 +539,7 @@ normal:
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FString V_GetColorStringByName (const char *name)
|
||||
FString V_GetColorStringByName (const char *name, FScriptPosition *sc)
|
||||
{
|
||||
FMemLump rgbNames;
|
||||
char *rgbEnd;
|
||||
|
@ -552,7 +553,8 @@ FString V_GetColorStringByName (const char *name)
|
|||
rgblump = Wads.CheckNumForName ("X11R6RGB");
|
||||
if (rgblump == -1)
|
||||
{
|
||||
Printf ("X11R6RGB lump not found\n");
|
||||
if (!sc) Printf ("X11R6RGB lump not found\n");
|
||||
else sc->Message(MSG_WARNING, "X11R6RGB lump not found");
|
||||
return FString();
|
||||
}
|
||||
|
||||
|
@ -614,7 +616,8 @@ FString V_GetColorStringByName (const char *name)
|
|||
}
|
||||
if (rgb < rgbEnd)
|
||||
{
|
||||
Printf ("X11R6RGB lump is corrupt\n");
|
||||
if (!sc) Printf ("X11R6RGB lump is corrupt\n");
|
||||
else sc->Message(MSG_WARNING, "X11R6RGB lump is corrupt");
|
||||
}
|
||||
return FString();
|
||||
}
|
||||
|
@ -627,22 +630,28 @@ FString V_GetColorStringByName (const char *name)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int V_GetColor (const DWORD *palette, const char *str)
|
||||
int V_GetColor (const DWORD *palette, const char *str, FScriptPosition *sc)
|
||||
{
|
||||
FString string = V_GetColorStringByName (str);
|
||||
FString string = V_GetColorStringByName (str, sc);
|
||||
int res;
|
||||
|
||||
if (!string.IsEmpty())
|
||||
{
|
||||
res = V_GetColorFromString (palette, string);
|
||||
res = V_GetColorFromString (palette, string, sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = V_GetColorFromString (palette, str);
|
||||
res = V_GetColorFromString (palette, str, sc);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int V_GetColor(const DWORD *palette, FScanner &sc)
|
||||
{
|
||||
FScriptPosition scc = sc;
|
||||
return V_GetColor(palette, sc.String, &scc);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// BuildTransTable
|
||||
|
|
|
@ -497,15 +497,17 @@ void V_Shutdown ();
|
|||
|
||||
void V_MarkRect (int x, int y, int width, int height);
|
||||
|
||||
class FScanner;
|
||||
// Returns the closest color to the one desired. String
|
||||
// should be of the form "rr gg bb".
|
||||
int V_GetColorFromString (const DWORD *palette, const char *colorstring);
|
||||
int V_GetColorFromString (const DWORD *palette, const char *colorstring, FScriptPosition *sc = nullptr);
|
||||
// Scans through the X11R6RGB lump for a matching color
|
||||
// and returns a color string suitable for V_GetColorFromString.
|
||||
FString V_GetColorStringByName (const char *name);
|
||||
FString V_GetColorStringByName (const char *name, FScriptPosition *sc = nullptr);
|
||||
|
||||
// Tries to get color by name, then by string
|
||||
int V_GetColor (const DWORD *palette, const char *str);
|
||||
int V_GetColor (const DWORD *palette, const char *str, FScriptPosition *sc = nullptr);
|
||||
int V_GetColor(const DWORD *palette, FScanner &sc);
|
||||
void V_DrawFrame (int left, int top, int width, int height);
|
||||
|
||||
// If the view size is not full screen, draws a border around it.
|
||||
|
|
|
@ -298,17 +298,68 @@ protected:
|
|||
|
||||
friend struct FStringData;
|
||||
|
||||
public:
|
||||
bool operator == (const FString &other) const
|
||||
{
|
||||
return Compare(other) == 0;
|
||||
}
|
||||
|
||||
bool operator != (const FString &other) const
|
||||
{
|
||||
return Compare(other) != 0;
|
||||
}
|
||||
|
||||
bool operator < (const FString &other) const
|
||||
{
|
||||
return Compare(other) < 0;
|
||||
}
|
||||
|
||||
bool operator > (const FString &other) const
|
||||
{
|
||||
return Compare(other) > 0;
|
||||
}
|
||||
|
||||
bool operator <= (const FString &other) const
|
||||
{
|
||||
return Compare(other) <= 0;
|
||||
}
|
||||
|
||||
bool operator >= (const FString &other) const
|
||||
{
|
||||
return Compare(other) >= 0;
|
||||
}
|
||||
|
||||
bool operator == (const char *) const = delete;
|
||||
bool operator != (const char *) const = delete;
|
||||
bool operator < (const char *) const = delete;
|
||||
bool operator > (const char *) const = delete;
|
||||
bool operator <= (const char *) const = delete;
|
||||
bool operator >= (const char *) const = delete;
|
||||
|
||||
bool operator == (FName) const = delete;
|
||||
bool operator != (FName) const = delete;
|
||||
bool operator < (FName) const = delete;
|
||||
bool operator > (FName) const = delete;
|
||||
bool operator <= (FName) const = delete;
|
||||
bool operator >= (FName) const = delete;
|
||||
|
||||
private:
|
||||
// Prevent these from being called as current practices are to use Compare.
|
||||
// Without this FStrings will be accidentally compared against char* ptrs.
|
||||
bool operator == (const FString &illegal) const;
|
||||
bool operator != (const FString &illegal) const;
|
||||
bool operator < (const FString &illegal) const;
|
||||
bool operator > (const FString &illegal) const;
|
||||
bool operator <= (const FString &illegal) const;
|
||||
bool operator >= (const FString &illegal) const;
|
||||
};
|
||||
|
||||
bool operator == (const char *, const FString &) = delete;
|
||||
bool operator != (const char *, const FString &) = delete;
|
||||
bool operator < (const char *, const FString &) = delete;
|
||||
bool operator > (const char *, const FString &) = delete;
|
||||
bool operator <= (const char *, const FString &) = delete;
|
||||
bool operator >= (const char *, const FString &) = delete;
|
||||
|
||||
bool operator == (FName, const FString &) = delete;
|
||||
bool operator != (FName, const FString &) = delete;
|
||||
bool operator < (FName, const FString &) = delete;
|
||||
bool operator > (FName, const FString &) = delete;
|
||||
bool operator <= (FName, const FString &) = delete;
|
||||
bool operator >= (FName, const FString &) = delete;
|
||||
|
||||
class FStringf : public FString
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
setwallyscale 717 front bot 1.090909
|
||||
|
||||
setslopeoverflow
|
||||
polyobj
|
||||
}
|
||||
|
||||
B2D8DA03489D1C67F60DC87FBC4EA338 // map01 - Massmouth 2
|
||||
|
|
|
@ -255,28 +255,24 @@ map E1M5 lookup "CHUSTR_E1M5"
|
|||
cluster 1
|
||||
{
|
||||
flat = "FLOOR4_8"
|
||||
music = "$MUSIC_VICTOR"
|
||||
exittext = lookup, "CE1TEXT"
|
||||
}
|
||||
|
||||
cluster 2
|
||||
{
|
||||
flat = "SFLR6_1"
|
||||
music = "$MUSIC_VICTOR"
|
||||
exittext = lookup, "CE2TEXT"
|
||||
}
|
||||
|
||||
cluster 3
|
||||
{
|
||||
flat = "MFLR8_4"
|
||||
music = "$MUSIC_VICTOR"
|
||||
exittext = lookup, "CE3TEXT"
|
||||
}
|
||||
|
||||
cluster 4
|
||||
{
|
||||
flat = "MFLR8_3"
|
||||
music = "$MUSIC_VICTOR"
|
||||
exittext = lookup, "CE4TEXT"
|
||||
}
|
||||
|
||||
|
|
|
@ -506,28 +506,24 @@ map E4M9 lookup "HUSTR_E4M9"
|
|||
cluster 1
|
||||
{
|
||||
flat = "$bgflatE1"
|
||||
music = "$MUSIC_VICTOR"
|
||||
exittext = lookup, "E1TEXT"
|
||||
}
|
||||
|
||||
cluster 2
|
||||
{
|
||||
flat = "$bgflatE2"
|
||||
music = "$MUSIC_VICTOR"
|
||||
exittext = lookup, "E2TEXT"
|
||||
}
|
||||
|
||||
cluster 3
|
||||
{
|
||||
flat = "$bgflatE3"
|
||||
music = "$MUSIC_VICTOR"
|
||||
exittext = lookup, "E3TEXT"
|
||||
}
|
||||
|
||||
cluster 4
|
||||
{
|
||||
flat = "$bgflatE4"
|
||||
music = "$MUSIC_VICTOR"
|
||||
exittext = lookup, "E4TEXT"
|
||||
}
|
||||
|
||||
|
|
|
@ -380,7 +380,6 @@ map MAP32 lookup "HUSTR_32"
|
|||
cluster 5
|
||||
{
|
||||
flat = "$BGFLAT06"
|
||||
music = "$MUSIC_READ_M"
|
||||
exittext = lookup, "C1TEXT"
|
||||
|
||||
}
|
||||
|
@ -390,7 +389,6 @@ cluster 5
|
|||
cluster 6
|
||||
{
|
||||
flat = "$BGFLAT11"
|
||||
music = "$MUSIC_READ_M"
|
||||
exittext = lookup, "C2TEXT"
|
||||
|
||||
}
|
||||
|
@ -400,7 +398,6 @@ cluster 6
|
|||
cluster 7
|
||||
{
|
||||
flat = "$BGFLAT20"
|
||||
music = "$MUSIC_READ_M"
|
||||
exittext = lookup, "C3TEXT"
|
||||
}
|
||||
|
||||
|
@ -409,7 +406,6 @@ cluster 7
|
|||
cluster 8
|
||||
{
|
||||
flat = "$BGFLAT30"
|
||||
music = "$MUSIC_READ_M"
|
||||
exittext = lookup, "C4TEXT"
|
||||
}
|
||||
|
||||
|
@ -418,7 +414,6 @@ cluster 8
|
|||
cluster 9
|
||||
{
|
||||
flat = "$BGFLAT15"
|
||||
music = "$MUSIC_READ_M"
|
||||
entertext = lookup, "C5TEXT"
|
||||
}
|
||||
|
||||
|
@ -427,7 +422,6 @@ cluster 9
|
|||
cluster 10
|
||||
{
|
||||
flat = "$BGFLAT31"
|
||||
music = "$MUSIC_READ_M"
|
||||
entertext = lookup, "C6TEXT"
|
||||
}
|
||||
|
||||
|
@ -537,7 +531,6 @@ map LEVEL09 lookup "NHUSTR_9"
|
|||
cluster 11
|
||||
{
|
||||
flat = "SLIME16"
|
||||
music = "$MUSIC_READ_M"
|
||||
exittext = lookup, "NERVETEXT"
|
||||
}
|
||||
|
||||
|
|
|
@ -805,35 +805,30 @@ map E6M3 "Untitled"
|
|||
cluster 1
|
||||
{
|
||||
flat = "FLOOR25"
|
||||
music = "MUS_CPTD"
|
||||
exittext = lookup, "HE1TEXT"
|
||||
}
|
||||
|
||||
cluster 2
|
||||
{
|
||||
flat = "FLATHUH1"
|
||||
music = "MUS_CPTD"
|
||||
exittext = lookup, "HE2TEXT"
|
||||
}
|
||||
|
||||
cluster 3
|
||||
{
|
||||
flat = "FLTWAWA2"
|
||||
music = "MUS_CPTD"
|
||||
exittext = lookup, "HE3TEXT"
|
||||
}
|
||||
|
||||
cluster 4
|
||||
{
|
||||
flat = "FLOOR28"
|
||||
music = "MUS_CPTD"
|
||||
exittext = lookup, "HE4TEXT"
|
||||
}
|
||||
|
||||
cluster 5
|
||||
{
|
||||
flat = "FLOOR08"
|
||||
music = "MUS_CPTD"
|
||||
exittext = lookup, "HE5TEXT"
|
||||
}
|
||||
|
||||
|
|
|
@ -464,7 +464,6 @@ cluster 1
|
|||
hub
|
||||
exittext = "clus1msg"
|
||||
exittextislump
|
||||
music = "hub"
|
||||
pic = "interpic"
|
||||
}
|
||||
|
||||
|
@ -473,7 +472,6 @@ cluster 2
|
|||
hub
|
||||
exittext = "clus2msg"
|
||||
exittextislump
|
||||
music = "hub"
|
||||
pic = "interpic"
|
||||
}
|
||||
|
||||
|
@ -482,7 +480,6 @@ cluster 3
|
|||
hub
|
||||
exittext = "clus3msg"
|
||||
exittextislump
|
||||
music = "hub"
|
||||
pic = "interpic"
|
||||
}
|
||||
|
||||
|
@ -491,7 +488,6 @@ cluster 4
|
|||
hub
|
||||
exittext = "clus4msg"
|
||||
exittextislump
|
||||
music = "hub"
|
||||
pic = "interpic"
|
||||
}
|
||||
|
||||
|
|
|
@ -374,7 +374,6 @@ map MAP32 lookup "PHUSTR_32"
|
|||
cluster 5
|
||||
{
|
||||
flat = "$BGFLAT06"
|
||||
music = "$MUSIC_READ_M"
|
||||
exittext = lookup, "P1TEXT"
|
||||
}
|
||||
|
||||
|
@ -383,7 +382,6 @@ cluster 5
|
|||
cluster 6
|
||||
{
|
||||
flat = "$BGFLAT11"
|
||||
music = "$MUSIC_READ_M"
|
||||
exittext = lookup, "P2TEXT"
|
||||
}
|
||||
|
||||
|
@ -392,7 +390,6 @@ cluster 6
|
|||
cluster 7
|
||||
{
|
||||
flat = "$BGFLAT20"
|
||||
music = "$MUSIC_READ_M"
|
||||
exittext = lookup, "P3TEXT"
|
||||
}
|
||||
|
||||
|
@ -401,7 +398,6 @@ cluster 7
|
|||
cluster 8
|
||||
{
|
||||
flat = "$BGFLAT30"
|
||||
music = "$MUSIC_READ_M"
|
||||
exittext = lookup, "P4TEXT"
|
||||
}
|
||||
|
||||
|
@ -410,7 +406,6 @@ cluster 8
|
|||
cluster 9
|
||||
{
|
||||
flat = "$BGFLAT15"
|
||||
music = "$MUSIC_READ_M"
|
||||
entertext = lookup, "P5TEXT"
|
||||
}
|
||||
|
||||
|
@ -419,7 +414,6 @@ cluster 9
|
|||
cluster 10
|
||||
{
|
||||
flat = "$BGFLAT31"
|
||||
music = "$MUSIC_READ_M"
|
||||
entertext = lookup, "P6TEXT"
|
||||
}
|
||||
|
||||
|
|
|
@ -374,7 +374,6 @@ map MAP32 lookup "THUSTR_32"
|
|||
cluster 5
|
||||
{
|
||||
flat = "$BGFLAT06"
|
||||
music = "$MUSIC_READ_M"
|
||||
exittext = lookup, "T1TEXT"
|
||||
}
|
||||
|
||||
|
@ -383,7 +382,6 @@ cluster 5
|
|||
cluster 6
|
||||
{
|
||||
flat = "$BGFLAT11"
|
||||
music = "$MUSIC_READ_M"
|
||||
exittext = lookup, "T2TEXT"
|
||||
}
|
||||
|
||||
|
@ -392,7 +390,6 @@ cluster 6
|
|||
cluster 7
|
||||
{
|
||||
flat = "$BGFLAT20"
|
||||
music = "$MUSIC_READ_M"
|
||||
exittext = lookup, "T3TEXT"
|
||||
}
|
||||
|
||||
|
@ -401,7 +398,6 @@ cluster 7
|
|||
cluster 8
|
||||
{
|
||||
flat = "$BGFLAT30"
|
||||
music = "$MUSIC_READ_M"
|
||||
exittext = lookup, "T4TEXT"
|
||||
}
|
||||
|
||||
|
@ -410,7 +406,6 @@ cluster 8
|
|||
cluster 9
|
||||
{
|
||||
flat = "$BGFLAT15"
|
||||
music = "$MUSIC_READ_M"
|
||||
entertext = lookup, "T5TEXT"
|
||||
}
|
||||
|
||||
|
@ -419,6 +414,5 @@ cluster 9
|
|||
cluster 10
|
||||
{
|
||||
flat = "$BGFLAT31"
|
||||
music = "$MUSIC_READ_M"
|
||||
entertext = lookup, "T6TEXT"
|
||||
}
|
||||
|
|
|
@ -1,212 +1,212 @@
|
|||
zscript/base.txt
|
||||
zscript/constants.txt
|
||||
zscript/actor.txt
|
||||
zscript/actor_checks.txt
|
||||
#include "zscript/base.txt"
|
||||
#include "zscript/constants.txt"
|
||||
#include "zscript/actor.txt"
|
||||
#include "zscript/actor_checks.txt"
|
||||
|
||||
zscript/shared/inventory.txt
|
||||
zscript/shared/inv_misc.txt
|
||||
zscript/shared/weapons.txt
|
||||
zscript/shared/armor.txt
|
||||
zscript/shared/powerups.txt
|
||||
zscript/shared/player.txt
|
||||
zscript/shared/morph.txt
|
||||
zscript/shared/botstuff.txt
|
||||
zscript/shared/sharedmisc.txt
|
||||
zscript/shared/blood.txt
|
||||
zscript/shared/debris.txt
|
||||
zscript/shared/decal.txt
|
||||
zscript/shared/splashes.txt
|
||||
zscript/shared/itemeffects.txt
|
||||
zscript/shared/fountain.txt
|
||||
zscript/shared/spark.txt
|
||||
zscript/shared/soundsequence.txt
|
||||
zscript/shared/soundenvironment.txt
|
||||
zscript/shared/bridge.txt
|
||||
zscript/shared/specialspot.txt
|
||||
zscript/shared/teleport.txt
|
||||
zscript/shared/camera.txt
|
||||
zscript/shared/movingcamera.txt
|
||||
zscript/shared/mapmarker.txt
|
||||
zscript/shared/waterzone.txt
|
||||
zscript/shared/skies.txt
|
||||
zscript/shared/hatetarget.txt
|
||||
zscript/shared/secrettrigger.txt
|
||||
zscript/shared/setcolor.txt
|
||||
zscript/shared/sectoraction.txt
|
||||
zscript/shared/ice.txt
|
||||
zscript/shared/dog.txt
|
||||
zscript/shared/fastprojectile.txt
|
||||
zscript/shared/dynlights.txt
|
||||
#include "zscript/shared/inventory.txt"
|
||||
#include "zscript/shared/inv_misc.txt"
|
||||
#include "zscript/shared/weapons.txt"
|
||||
#include "zscript/shared/armor.txt"
|
||||
#include "zscript/shared/powerups.txt"
|
||||
#include "zscript/shared/player.txt"
|
||||
#include "zscript/shared/morph.txt"
|
||||
#include "zscript/shared/botstuff.txt"
|
||||
#include "zscript/shared/sharedmisc.txt"
|
||||
#include "zscript/shared/blood.txt"
|
||||
#include "zscript/shared/debris.txt"
|
||||
#include "zscript/shared/decal.txt"
|
||||
#include "zscript/shared/splashes.txt"
|
||||
#include "zscript/shared/itemeffects.txt"
|
||||
#include "zscript/shared/fountain.txt"
|
||||
#include "zscript/shared/spark.txt"
|
||||
#include "zscript/shared/soundsequence.txt"
|
||||
#include "zscript/shared/soundenvironment.txt"
|
||||
#include "zscript/shared/bridge.txt"
|
||||
#include "zscript/shared/specialspot.txt"
|
||||
#include "zscript/shared/teleport.txt"
|
||||
#include "zscript/shared/camera.txt"
|
||||
#include "zscript/shared/movingcamera.txt"
|
||||
#include "zscript/shared/mapmarker.txt"
|
||||
#include "zscript/shared/waterzone.txt"
|
||||
#include "zscript/shared/skies.txt"
|
||||
#include "zscript/shared/hatetarget.txt"
|
||||
#include "zscript/shared/secrettrigger.txt"
|
||||
#include "zscript/shared/setcolor.txt"
|
||||
#include "zscript/shared/sectoraction.txt"
|
||||
#include "zscript/shared/ice.txt"
|
||||
#include "zscript/shared/dog.txt"
|
||||
#include "zscript/shared/fastprojectile.txt"
|
||||
#include "zscript/shared/dynlights.txt"
|
||||
|
||||
zscript/doom/doomplayer.txt
|
||||
zscript/doom/possessed.txt
|
||||
zscript/doom/doomimp.txt
|
||||
zscript/doom/demon.txt
|
||||
zscript/doom/lostsoul.txt
|
||||
zscript/doom/cacodemon.txt
|
||||
zscript/doom/bruiser.txt
|
||||
zscript/doom/revenant.txt
|
||||
zscript/doom/arachnotron.txt
|
||||
zscript/doom/fatso.txt
|
||||
zscript/doom/painelemental.txt
|
||||
zscript/doom/archvile.txt
|
||||
zscript/doom/cyberdemon.txt
|
||||
zscript/doom/spidermaster.txt
|
||||
zscript/doom/keen.txt
|
||||
zscript/doom/bossbrain.txt
|
||||
zscript/doom/weaponfist.txt
|
||||
zscript/doom/weaponpistol.txt
|
||||
zscript/doom/weaponshotgun.txt
|
||||
zscript/doom/weaponssg.txt
|
||||
zscript/doom/weaponchaingun.txt
|
||||
zscript/doom/weaponchainsaw.txt
|
||||
zscript/doom/weaponrlaunch.txt
|
||||
zscript/doom/weaponplasma.txt
|
||||
zscript/doom/weaponbfg.txt
|
||||
#include "zscript/doom/doomplayer.txt"
|
||||
#include "zscript/doom/possessed.txt"
|
||||
#include "zscript/doom/doomimp.txt"
|
||||
#include "zscript/doom/demon.txt"
|
||||
#include "zscript/doom/lostsoul.txt"
|
||||
#include "zscript/doom/cacodemon.txt"
|
||||
#include "zscript/doom/bruiser.txt"
|
||||
#include "zscript/doom/revenant.txt"
|
||||
#include "zscript/doom/arachnotron.txt"
|
||||
#include "zscript/doom/fatso.txt"
|
||||
#include "zscript/doom/painelemental.txt"
|
||||
#include "zscript/doom/archvile.txt"
|
||||
#include "zscript/doom/cyberdemon.txt"
|
||||
#include "zscript/doom/spidermaster.txt"
|
||||
#include "zscript/doom/keen.txt"
|
||||
#include "zscript/doom/bossbrain.txt"
|
||||
#include "zscript/doom/weaponfist.txt"
|
||||
#include "zscript/doom/weaponpistol.txt"
|
||||
#include "zscript/doom/weaponshotgun.txt"
|
||||
#include "zscript/doom/weaponssg.txt"
|
||||
#include "zscript/doom/weaponchaingun.txt"
|
||||
#include "zscript/doom/weaponchainsaw.txt"
|
||||
#include "zscript/doom/weaponrlaunch.txt"
|
||||
#include "zscript/doom/weaponplasma.txt"
|
||||
#include "zscript/doom/weaponbfg.txt"
|
||||
|
||||
zscript/doom/deadthings.txt
|
||||
zscript/doom/doomammo.txt
|
||||
zscript/doom/doomarmor.txt
|
||||
zscript/doom/doomartifacts.txt
|
||||
zscript/doom/doomhealth.txt
|
||||
zscript/doom/doomkeys.txt
|
||||
zscript/doom/doommisc.txt
|
||||
zscript/doom/doomdecorations.txt
|
||||
zscript/doom/doomweapons.txt
|
||||
zscript/doom/stealthmonsters.txt
|
||||
zscript/doom/scriptedmarine.txt
|
||||
#include "zscript/doom/deadthings.txt"
|
||||
#include "zscript/doom/doomammo.txt"
|
||||
#include "zscript/doom/doomarmor.txt"
|
||||
#include "zscript/doom/doomartifacts.txt"
|
||||
#include "zscript/doom/doomhealth.txt"
|
||||
#include "zscript/doom/doomkeys.txt"
|
||||
#include "zscript/doom/doommisc.txt"
|
||||
#include "zscript/doom/doomdecorations.txt"
|
||||
#include "zscript/doom/doomweapons.txt"
|
||||
#include "zscript/doom/stealthmonsters.txt"
|
||||
#include "zscript/doom/scriptedmarine.txt"
|
||||
|
||||
zscript/raven/artiegg.txt
|
||||
zscript/raven/artitele.txt
|
||||
zscript/raven/ravenartifacts.txt
|
||||
zscript/raven/ravenhealth.txt
|
||||
zscript/raven/ravenambient.txt
|
||||
zscript/raven/minotaur.txt
|
||||
#include "zscript/raven/artiegg.txt"
|
||||
#include "zscript/raven/artitele.txt"
|
||||
#include "zscript/raven/ravenartifacts.txt"
|
||||
#include "zscript/raven/ravenhealth.txt"
|
||||
#include "zscript/raven/ravenambient.txt"
|
||||
#include "zscript/raven/minotaur.txt"
|
||||
|
||||
zscript/heretic/hereticplayer.txt
|
||||
zscript/heretic/hereticammo.txt
|
||||
zscript/heretic/hereticarmor.txt
|
||||
zscript/heretic/hereticartifacts.txt
|
||||
zscript/heretic/heretickeys.txt
|
||||
zscript/heretic/hereticdecorations.txt
|
||||
zscript/heretic/hereticmisc.txt
|
||||
zscript/heretic/mummy.txt
|
||||
zscript/heretic/clink.txt
|
||||
zscript/heretic/beast.txt
|
||||
zscript/heretic/snake.txt
|
||||
zscript/heretic/hereticimp.txt
|
||||
zscript/heretic/knight.txt
|
||||
zscript/heretic/wizard.txt
|
||||
zscript/heretic/ironlich.txt
|
||||
zscript/heretic/dsparil.txt
|
||||
zscript/heretic/chicken.txt
|
||||
zscript/heretic/weaponstaff.txt
|
||||
zscript/heretic/weaponwand.txt
|
||||
zscript/heretic/weaponcrossbow.txt
|
||||
zscript/heretic/weapongauntlets.txt
|
||||
zscript/heretic/weaponmace.txt
|
||||
zscript/heretic/weaponblaster.txt
|
||||
zscript/heretic/weaponskullrod.txt
|
||||
zscript/heretic/weaponphoenix.txt
|
||||
#include "zscript/heretic/hereticplayer.txt"
|
||||
#include "zscript/heretic/hereticammo.txt"
|
||||
#include "zscript/heretic/hereticarmor.txt"
|
||||
#include "zscript/heretic/hereticartifacts.txt"
|
||||
#include "zscript/heretic/heretickeys.txt"
|
||||
#include "zscript/heretic/hereticdecorations.txt"
|
||||
#include "zscript/heretic/hereticmisc.txt"
|
||||
#include "zscript/heretic/mummy.txt"
|
||||
#include "zscript/heretic/clink.txt"
|
||||
#include "zscript/heretic/beast.txt"
|
||||
#include "zscript/heretic/snake.txt"
|
||||
#include "zscript/heretic/hereticimp.txt"
|
||||
#include "zscript/heretic/knight.txt"
|
||||
#include "zscript/heretic/wizard.txt"
|
||||
#include "zscript/heretic/ironlich.txt"
|
||||
#include "zscript/heretic/dsparil.txt"
|
||||
#include "zscript/heretic/chicken.txt"
|
||||
#include "zscript/heretic/weaponstaff.txt"
|
||||
#include "zscript/heretic/weaponwand.txt"
|
||||
#include "zscript/heretic/weaponcrossbow.txt"
|
||||
#include "zscript/heretic/weapongauntlets.txt"
|
||||
#include "zscript/heretic/weaponmace.txt"
|
||||
#include "zscript/heretic/weaponblaster.txt"
|
||||
#include "zscript/heretic/weaponskullrod.txt"
|
||||
#include "zscript/heretic/weaponphoenix.txt"
|
||||
|
||||
zscript/hexen/baseweapons.txt
|
||||
zscript/hexen/korax.txt
|
||||
zscript/hexen/fighterplayer.txt
|
||||
zscript/hexen/clericplayer.txt
|
||||
zscript/hexen/mageplayer.txt
|
||||
zscript/hexen/pig.txt
|
||||
zscript/hexen/flame.txt
|
||||
zscript/hexen/flies.txt
|
||||
zscript/hexen/hexenarmor.txt
|
||||
zscript/hexen/hexendecorations.txt
|
||||
zscript/hexen/hexenkeys.txt
|
||||
zscript/hexen/hexenspecialdecs.txt
|
||||
zscript/hexen/mana.txt
|
||||
zscript/hexen/puzzleitems.txt
|
||||
zscript/hexen/scriptprojectiles.txt
|
||||
zscript/hexen/speedboots.txt
|
||||
zscript/hexen/ettin.txt
|
||||
zscript/hexen/centaur.txt
|
||||
zscript/hexen/demons.txt
|
||||
zscript/hexen/firedemon.txt
|
||||
zscript/hexen/fog.txt
|
||||
zscript/hexen/summon.txt
|
||||
zscript/hexen/flechette.txt
|
||||
zscript/hexen/clericboss.txt
|
||||
zscript/hexen/fighterboss.txt
|
||||
zscript/hexen/mageboss.txt
|
||||
zscript/hexen/bats.txt
|
||||
zscript/hexen/bishop.txt
|
||||
zscript/hexen/blastradius.txt
|
||||
zscript/hexen/boostarmor.txt
|
||||
zscript/hexen/clericmace.txt
|
||||
zscript/hexen/clericflame.txt
|
||||
zscript/hexen/clericholy.txt
|
||||
zscript/hexen/clericstaff.txt
|
||||
zscript/hexen/magewand.txt
|
||||
zscript/hexen/magecone.txt
|
||||
zscript/hexen/magelightning.txt
|
||||
zscript/hexen/magestaff.txt
|
||||
zscript/hexen/fighterfist.txt
|
||||
zscript/hexen/fighteraxe.txt
|
||||
zscript/hexen/fighterhammer.txt
|
||||
zscript/hexen/fighterquietus.txt
|
||||
zscript/hexen/dragon.txt
|
||||
zscript/hexen/healingradius.txt
|
||||
zscript/hexen/teleportother.txt
|
||||
zscript/hexen/iceguy.txt
|
||||
zscript/hexen/serpent.txt
|
||||
zscript/hexen/spike.txt
|
||||
zscript/hexen/wraith.txt
|
||||
zscript/hexen/heresiarch.txt
|
||||
#include "zscript/hexen/baseweapons.txt"
|
||||
#include "zscript/hexen/korax.txt"
|
||||
#include "zscript/hexen/fighterplayer.txt"
|
||||
#include "zscript/hexen/clericplayer.txt"
|
||||
#include "zscript/hexen/mageplayer.txt"
|
||||
#include "zscript/hexen/pig.txt"
|
||||
#include "zscript/hexen/flame.txt"
|
||||
#include "zscript/hexen/flies.txt"
|
||||
#include "zscript/hexen/hexenarmor.txt"
|
||||
#include "zscript/hexen/hexendecorations.txt"
|
||||
#include "zscript/hexen/hexenkeys.txt"
|
||||
#include "zscript/hexen/hexenspecialdecs.txt"
|
||||
#include "zscript/hexen/mana.txt"
|
||||
#include "zscript/hexen/puzzleitems.txt"
|
||||
#include "zscript/hexen/scriptprojectiles.txt"
|
||||
#include "zscript/hexen/speedboots.txt"
|
||||
#include "zscript/hexen/ettin.txt"
|
||||
#include "zscript/hexen/centaur.txt"
|
||||
#include "zscript/hexen/demons.txt"
|
||||
#include "zscript/hexen/firedemon.txt"
|
||||
#include "zscript/hexen/fog.txt"
|
||||
#include "zscript/hexen/summon.txt"
|
||||
#include "zscript/hexen/flechette.txt"
|
||||
#include "zscript/hexen/clericboss.txt"
|
||||
#include "zscript/hexen/fighterboss.txt"
|
||||
#include "zscript/hexen/mageboss.txt"
|
||||
#include "zscript/hexen/bats.txt"
|
||||
#include "zscript/hexen/bishop.txt"
|
||||
#include "zscript/hexen/blastradius.txt"
|
||||
#include "zscript/hexen/boostarmor.txt"
|
||||
#include "zscript/hexen/clericmace.txt"
|
||||
#include "zscript/hexen/clericflame.txt"
|
||||
#include "zscript/hexen/clericholy.txt"
|
||||
#include "zscript/hexen/clericstaff.txt"
|
||||
#include "zscript/hexen/magewand.txt"
|
||||
#include "zscript/hexen/magecone.txt"
|
||||
#include "zscript/hexen/magelightning.txt"
|
||||
#include "zscript/hexen/magestaff.txt"
|
||||
#include "zscript/hexen/fighterfist.txt"
|
||||
#include "zscript/hexen/fighteraxe.txt"
|
||||
#include "zscript/hexen/fighterhammer.txt"
|
||||
#include "zscript/hexen/fighterquietus.txt"
|
||||
#include "zscript/hexen/dragon.txt"
|
||||
#include "zscript/hexen/healingradius.txt"
|
||||
#include "zscript/hexen/teleportother.txt"
|
||||
#include "zscript/hexen/iceguy.txt"
|
||||
#include "zscript/hexen/serpent.txt"
|
||||
#include "zscript/hexen/spike.txt"
|
||||
#include "zscript/hexen/wraith.txt"
|
||||
#include "zscript/hexen/heresiarch.txt"
|
||||
|
||||
zscript/strife/strifehumanoid.txt
|
||||
zscript/strife/strifeplayer.txt
|
||||
zscript/strife/strifeweapons.txt
|
||||
zscript/strife/spectral.txt
|
||||
zscript/strife/acolyte.txt
|
||||
zscript/strife/alienspectres.txt
|
||||
zscript/strife/beggars.txt
|
||||
zscript/strife/coin.txt
|
||||
zscript/strife/crusader.txt
|
||||
zscript/strife/entityboss.txt
|
||||
zscript/strife/inquisitor.txt
|
||||
zscript/strife/klaxon.txt
|
||||
zscript/strife/loremaster.txt
|
||||
zscript/strife/macil.txt
|
||||
zscript/strife/merchants.txt
|
||||
zscript/strife/peasants.txt
|
||||
zscript/strife/strifebishop.txt
|
||||
zscript/strife/oracle.txt
|
||||
zscript/strife/programmer.txt
|
||||
zscript/strife/questitems.txt
|
||||
zscript/strife/ratbuddy.txt
|
||||
zscript/strife/rebels.txt
|
||||
zscript/strife/reaver.txt
|
||||
zscript/strife/sentinel.txt
|
||||
zscript/strife/stalker.txt
|
||||
zscript/strife/strifeammo.txt
|
||||
zscript/strife/strifearmor.txt
|
||||
zscript/strife/strifefunctions.txt
|
||||
zscript/strife/strifeitems.txt
|
||||
zscript/strife/strifekeys.txt
|
||||
zscript/strife/strifestuff.txt
|
||||
zscript/strife/thingstoblowup.txt
|
||||
zscript/strife/templar.txt
|
||||
zscript/strife/zombie.txt
|
||||
zscript/strife/weapondagger.txt
|
||||
zscript/strife/weaponcrossbow.txt
|
||||
zscript/strife/weaponassault.txt
|
||||
zscript/strife/weaponmissile.txt
|
||||
zscript/strife/weaponflamer.txt
|
||||
zscript/strife/weapongrenade.txt
|
||||
zscript/strife/weaponmauler.txt
|
||||
zscript/strife/sigil.txt
|
||||
#include "zscript/strife/strifehumanoid.txt"
|
||||
#include "zscript/strife/strifeplayer.txt"
|
||||
#include "zscript/strife/strifeweapons.txt"
|
||||
#include "zscript/strife/spectral.txt"
|
||||
#include "zscript/strife/acolyte.txt"
|
||||
#include "zscript/strife/alienspectres.txt"
|
||||
#include "zscript/strife/beggars.txt"
|
||||
#include "zscript/strife/coin.txt"
|
||||
#include "zscript/strife/crusader.txt"
|
||||
#include "zscript/strife/entityboss.txt"
|
||||
#include "zscript/strife/inquisitor.txt"
|
||||
#include "zscript/strife/klaxon.txt"
|
||||
#include "zscript/strife/loremaster.txt"
|
||||
#include "zscript/strife/macil.txt"
|
||||
#include "zscript/strife/merchants.txt"
|
||||
#include "zscript/strife/peasants.txt"
|
||||
#include "zscript/strife/strifebishop.txt"
|
||||
#include "zscript/strife/oracle.txt"
|
||||
#include "zscript/strife/programmer.txt"
|
||||
#include "zscript/strife/questitems.txt"
|
||||
#include "zscript/strife/ratbuddy.txt"
|
||||
#include "zscript/strife/rebels.txt"
|
||||
#include "zscript/strife/reaver.txt"
|
||||
#include "zscript/strife/sentinel.txt"
|
||||
#include "zscript/strife/stalker.txt"
|
||||
#include "zscript/strife/strifeammo.txt"
|
||||
#include "zscript/strife/strifearmor.txt"
|
||||
#include "zscript/strife/strifefunctions.txt"
|
||||
#include "zscript/strife/strifeitems.txt"
|
||||
#include "zscript/strife/strifekeys.txt"
|
||||
#include "zscript/strife/strifestuff.txt"
|
||||
#include "zscript/strife/thingstoblowup.txt"
|
||||
#include "zscript/strife/templar.txt"
|
||||
#include "zscript/strife/zombie.txt"
|
||||
#include "zscript/strife/weapondagger.txt"
|
||||
#include "zscript/strife/weaponcrossbow.txt"
|
||||
#include "zscript/strife/weaponassault.txt"
|
||||
#include "zscript/strife/weaponmissile.txt"
|
||||
#include "zscript/strife/weaponflamer.txt"
|
||||
#include "zscript/strife/weapongrenade.txt"
|
||||
#include "zscript/strife/weaponmauler.txt"
|
||||
#include "zscript/strife/sigil.txt"
|
||||
|
||||
zscript/chex/chexmonsters.txt
|
||||
zscript/chex/chexkeys.txt
|
||||
zscript/chex/chexammo.txt
|
||||
zscript/chex/chexweapons.txt
|
||||
zscript/chex/chexitems.txt
|
||||
zscript/chex/chexdecorations.txt
|
||||
zscript/chex/chexplayer.txt
|
||||
#include "zscript/chex/chexmonsters.txt"
|
||||
#include "zscript/chex/chexkeys.txt"
|
||||
#include "zscript/chex/chexammo.txt"
|
||||
#include "zscript/chex/chexweapons.txt"
|
||||
#include "zscript/chex/chexitems.txt"
|
||||
#include "zscript/chex/chexdecorations.txt"
|
||||
#include "zscript/chex/chexplayer.txt"
|
||||
|
|
|
@ -303,7 +303,6 @@ class Actor : Thinker native
|
|||
native void DaggerAlert(Actor target);
|
||||
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);
|
||||
|
|
|
@ -368,6 +368,9 @@ enum EActivationFlags
|
|||
THINGSPEC_ClearSpecial = 32,
|
||||
THINGSPEC_NoDeathSpecial = 64,
|
||||
THINGSPEC_TriggerActs = 128,
|
||||
THINGSPEC_Activate = 1<<8, // The thing is activated when triggered
|
||||
THINGSPEC_Deactivate = 1<<9, // The thing is deactivated when triggered
|
||||
THINGSPEC_Switch = 1<<10, // The thing is alternatively activated and deactivated when triggered
|
||||
|
||||
// Shorter aliases for same
|
||||
AF_Default = 0,
|
||||
|
@ -379,6 +382,9 @@ enum EActivationFlags
|
|||
AF_ClearSpecial = 32,
|
||||
AF_NoDeathSpecial = 64,
|
||||
AF_TriggerActs = 128,
|
||||
AF_Activate = 1<<8, // The thing is activated when triggered
|
||||
AF_Deactivate = 1<<9, // The thing is deactivated when triggered
|
||||
AF_Switch = 1<<10, // The thing is alternatively activated and deactivated when triggered
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ class GoldWand : HereticWeapon
|
|||
return;
|
||||
}
|
||||
double pitch = BulletSlope();
|
||||
int damage = 7 + random[FireGoldWand]() & 7;
|
||||
int damage = 7 + (random[FireGoldWand]() & 7);
|
||||
double ang = angle;
|
||||
if (player.refire)
|
||||
{
|
||||
|
|
|
@ -583,7 +583,6 @@ class SorcBall1 : SorcBall
|
|||
{
|
||||
Super.BeginPlay ();
|
||||
AngleOffset = Heresiarch.BALL1_ANGLEOFFSET;
|
||||
A_Log("Ball1 begins " .. AngleOffset);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
@ -683,7 +682,6 @@ class SorcBall2 : SorcBall
|
|||
{
|
||||
Super.BeginPlay ();
|
||||
AngleOffset = Heresiarch.BALL2_ANGLEOFFSET;
|
||||
A_Log("Ball2 begins " .. AngleOffset);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
@ -733,7 +731,6 @@ class SorcBall3 : SorcBall
|
|||
{
|
||||
Super.BeginPlay ();
|
||||
AngleOffset = Heresiarch.BALL3_ANGLEOFFSET;
|
||||
A_Log("Ball3 begins " .. AngleOffset);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
|
|
@ -13,7 +13,7 @@ class SoundWind : Actor
|
|||
States
|
||||
{
|
||||
Spawn:
|
||||
TNT1 A 2 A_PlaySound("world/wind", CHAN_6);
|
||||
TNT1 A 2 A_PlaySound("world/wind", CHAN_6, 1, true);
|
||||
Loop;
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ class SoundWaterfall : Actor
|
|||
States
|
||||
{
|
||||
Spawn:
|
||||
TNT1 A 2 A_PlaySound("world/waterfall", CHAN_6);
|
||||
TNT1 A 2 A_PlaySound("world/waterfall", CHAN_6, 1, true);
|
||||
Loop;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,12 +21,24 @@ class IceChunk : Actor
|
|||
+NOBLOCKMAP
|
||||
+MOVEWITHSECTOR
|
||||
}
|
||||
native void A_IceSetTics ();
|
||||
|
||||
void A_IceSetTics ()
|
||||
{
|
||||
tics = 70 + (random[IceTics]() & 63);
|
||||
Name dtype = GetFloorTerrain().DamageMOD;
|
||||
if (dtype == 'Fire')
|
||||
{
|
||||
tics >>= 2;
|
||||
}
|
||||
else if (dtype == 'Ice')
|
||||
{
|
||||
tics <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
ICEC A 1;
|
||||
ICEC ABCD 10 A_IceSetTics;
|
||||
Stop;
|
||||
}
|
||||
|
|
|
@ -1864,7 +1864,7 @@ class PowerCoupling : Actor
|
|||
players[i].mo.GiveInventoryType ("QuestItem6");
|
||||
S_Sound ("svox/voc13", CHAN_VOICE);
|
||||
players[i].SetLogNumber (13);
|
||||
DoDropItem ("BrokenPowerCoupling", -1, 256);
|
||||
A_DropItem ("BrokenPowerCoupling", -1, 256);
|
||||
Destroy ();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue