mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-01-31 05:40:44 +00:00
- scriptified A_Mushroom to test something a bit more complex.
- fixed: FxMinusSign trashed local variables that were used with negation. - fixed: FxConditional only handled ints and floats, but not pointers and strings. - fixed: A 'no states in non-actors' error was triggered, even for classes without any states.
This commit is contained in:
parent
9eeb56212b
commit
f8ccda2dc8
15 changed files with 290 additions and 222 deletions
|
@ -838,7 +838,6 @@ set( NOT_COMPILED_SOURCE_FILES
|
||||||
g_doom/a_archvile.cpp
|
g_doom/a_archvile.cpp
|
||||||
g_doom/a_bossbrain.cpp
|
g_doom/a_bossbrain.cpp
|
||||||
g_doom/a_doomweaps.cpp
|
g_doom/a_doomweaps.cpp
|
||||||
g_doom/a_fatso.cpp
|
|
||||||
g_doom/a_keen.cpp
|
g_doom/a_keen.cpp
|
||||||
g_doom/a_lostsoul.cpp
|
g_doom/a_lostsoul.cpp
|
||||||
g_doom/a_painelemental.cpp
|
g_doom/a_painelemental.cpp
|
||||||
|
|
|
@ -1488,6 +1488,14 @@ static int PatchFrame (int frameNum)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// there is exactly one place where this is needed and we do not want to expose the state internals to ZSCRIPT.
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, isDEHState)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_STATE(state);
|
||||||
|
ACTION_RETURN_BOOL(state != nullptr && (state->DefineFlags & SDF_DEHACKED));
|
||||||
|
}
|
||||||
|
|
||||||
static int PatchSprite (int sprNum)
|
static int PatchSprite (int sprNum)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
|
@ -349,6 +349,13 @@ void DObject::Destroy ()
|
||||||
ObjectFlags = (ObjectFlags & ~OF_Fixed) | OF_EuthanizeMe;
|
ObjectFlags = (ObjectFlags & ~OF_Fixed) | OF_EuthanizeMe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(DObject, Destroy)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(DObject);
|
||||||
|
self->Destroy();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#include "a_archvile.cpp"
|
#include "a_archvile.cpp"
|
||||||
#include "a_bossbrain.cpp"
|
#include "a_bossbrain.cpp"
|
||||||
#include "a_doomweaps.cpp"
|
#include "a_doomweaps.cpp"
|
||||||
#include "a_fatso.cpp"
|
|
||||||
#include "a_keen.cpp"
|
#include "a_keen.cpp"
|
||||||
#include "a_lostsoul.cpp"
|
#include "a_lostsoul.cpp"
|
||||||
#include "a_painelemental.cpp"
|
#include "a_painelemental.cpp"
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
/*
|
|
||||||
#include "actor.h"
|
|
||||||
#include "info.h"
|
|
||||||
#include "m_random.h"
|
|
||||||
#include "s_sound.h"
|
|
||||||
#include "p_local.h"
|
|
||||||
#include "p_enemy.h"
|
|
||||||
#include "gstrings.h"
|
|
||||||
#include "a_action.h"
|
|
||||||
#include "vm.h"
|
|
||||||
*/
|
|
||||||
|
|
||||||
//
|
|
||||||
// Mancubus attack,
|
|
||||||
// firing three missiles in three different directions?
|
|
||||||
// Doesn't look like it.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// killough 9/98: a mushroom explosion effect, sorta :)
|
|
||||||
// Original idea: Linguica
|
|
||||||
//
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
MSF_Standard = 0,
|
|
||||||
MSF_Classic = 1,
|
|
||||||
MSF_DontHurt = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
PARAM_CLASS_DEF (spawntype, AActor)
|
|
||||||
PARAM_INT_DEF (n)
|
|
||||||
PARAM_INT_DEF (flags)
|
|
||||||
PARAM_FLOAT_DEF (vrange)
|
|
||||||
PARAM_FLOAT_DEF (hrange)
|
|
||||||
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
if (n == 0)
|
|
||||||
{
|
|
||||||
n = self->GetMissileDamage(0, 1);
|
|
||||||
}
|
|
||||||
if (spawntype == NULL)
|
|
||||||
{
|
|
||||||
spawntype = PClass::FindActor("FatShot");
|
|
||||||
}
|
|
||||||
|
|
||||||
P_RadiusAttack (self, self->target, 128, 128, self->DamageType, (flags & MSF_DontHurt) ? 0 : RADF_HURTSOURCE);
|
|
||||||
P_CheckSplash(self, 128.);
|
|
||||||
|
|
||||||
// Now launch mushroom cloud
|
|
||||||
AActor *target = Spawn("Mapspot", self->Pos(), NO_REPLACE); // We need something to aim at.
|
|
||||||
AActor *master = (flags & MSF_DontHurt) ? (AActor*)(self->target) : self;
|
|
||||||
target->Height = self->Height;
|
|
||||||
for (i = -n; i <= n; i += 8)
|
|
||||||
{
|
|
||||||
for (j = -n; j <= n; j += 8)
|
|
||||||
{
|
|
||||||
AActor *mo;
|
|
||||||
target->SetXYZ(
|
|
||||||
self->X() + i, // Aim in many directions from source
|
|
||||||
self->Y() + j,
|
|
||||||
self->Z() + (P_AproxDistance(i,j) * vrange)); // Aim up fairly high
|
|
||||||
if ((flags & MSF_Classic) || // Flag explicitely set, or no flags and compat options
|
|
||||||
(flags == 0 && (self->state->DefineFlags & SDF_DEHACKED) && (i_compatflags & COMPATF_MUSHROOM)))
|
|
||||||
{ // Use old function for MBF compatibility
|
|
||||||
mo = P_OldSpawnMissile (self, master, target, spawntype);
|
|
||||||
}
|
|
||||||
else // Use normal function
|
|
||||||
{
|
|
||||||
mo = P_SpawnMissile(self, target, spawntype, master);
|
|
||||||
}
|
|
||||||
if (mo != NULL)
|
|
||||||
{ // Slow it down a bit
|
|
||||||
mo->Vel *= hrange;
|
|
||||||
mo->flags &= ~MF_NOGRAVITY; // Make debris fall under gravity
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
target->Destroy();
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -67,7 +67,7 @@ enum EStateDefineFlags
|
||||||
SDF_DEHACKED = 8, // Identify a state as having been modified by a dehacked lump
|
SDF_DEHACKED = 8, // Identify a state as having been modified by a dehacked lump
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EStateType
|
enum EStateType : int // this must ensure proper alignment.
|
||||||
{
|
{
|
||||||
STATE_Actor,
|
STATE_Actor,
|
||||||
STATE_Psprite,
|
STATE_Psprite,
|
||||||
|
|
|
@ -4258,6 +4258,17 @@ AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t a
|
||||||
return actor;
|
return actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, Spawn)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_CLASS(type, AActor);
|
||||||
|
PARAM_FLOAT_DEF(x);
|
||||||
|
PARAM_FLOAT_DEF(y);
|
||||||
|
PARAM_FLOAT_DEF(z);
|
||||||
|
PARAM_INT_DEF(flags);
|
||||||
|
ACTION_RETURN_OBJECT(AActor::StaticSpawn(type, DVector3(x, y, z), replace_t(flags)));
|
||||||
|
}
|
||||||
|
|
||||||
PClassActor *ClassForSpawn(FName classname)
|
PClassActor *ClassForSpawn(FName classname)
|
||||||
{
|
{
|
||||||
PClass *cls = PClass::FindClass(classname);
|
PClass *cls = PClass::FindClass(classname);
|
||||||
|
@ -5951,6 +5962,16 @@ AActor *P_OldSpawnMissile(AActor *source, AActor *owner, AActor *dest, PClassAct
|
||||||
return th;
|
return th;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, OldSpawnMissile)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
PARAM_OBJECT(dest, AActor);
|
||||||
|
PARAM_CLASS(type, AActor);
|
||||||
|
PARAM_OBJECT_DEF(owner, AActor);
|
||||||
|
ACTION_RETURN_OBJECT(P_OldSpawnMissile(self, owner, dest, type));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNC P_SpawnMissileAngle
|
// FUNC P_SpawnMissileAngle
|
||||||
|
@ -6616,6 +6637,16 @@ DEFINE_ACTION_FUNCTION(AActor, VelFromAngle)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, SetXYZ)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
PARAM_FLOAT(x);
|
||||||
|
PARAM_FLOAT(y);
|
||||||
|
PARAM_FLOAT(z);
|
||||||
|
self->SetXYZ(x, y, z);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// DropItem handling
|
// DropItem handling
|
||||||
|
|
|
@ -156,7 +156,7 @@ void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos)
|
||||||
|
|
||||||
if (fail)
|
if (fail)
|
||||||
{
|
{
|
||||||
pos.Message(MSG_ERROR, "All return expressions must deduce to the same type");
|
pos.Message(MSG_ERROR, "Return type mismatch");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ static PSymbolTable Builtins;
|
||||||
static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCallType func)
|
static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCallType func)
|
||||||
{
|
{
|
||||||
PSymbol *sym = Builtins.FindSymbol(funcname, false);
|
PSymbol *sym = Builtins.FindSymbol(funcname, false);
|
||||||
if (sym == NULL)
|
if (sym == nullptr)
|
||||||
{
|
{
|
||||||
PSymbolVMFunction *symfunc = new PSymbolVMFunction(funcname);
|
PSymbolVMFunction *symfunc = new PSymbolVMFunction(funcname);
|
||||||
VMNativeFunction *calldec = new VMNativeFunction(func, funcname);
|
VMNativeFunction *calldec = new VMNativeFunction(func, funcname);
|
||||||
|
@ -282,7 +282,7 @@ bool FxExpression::isConstant() const
|
||||||
|
|
||||||
VMFunction *FxExpression::GetDirectFunction()
|
VMFunction *FxExpression::GetDirectFunction()
|
||||||
{
|
{
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -387,7 +387,7 @@ FxExpression *FxConstant::MakeConstant(PSymbol *sym, const FScriptPosition &pos)
|
||||||
{
|
{
|
||||||
FxExpression *x;
|
FxExpression *x;
|
||||||
PSymbolConstNumeric *csym = dyn_cast<PSymbolConstNumeric>(sym);
|
PSymbolConstNumeric *csym = dyn_cast<PSymbolConstNumeric>(sym);
|
||||||
if (csym != NULL)
|
if (csym != nullptr)
|
||||||
{
|
{
|
||||||
if (csym->ValueType->IsA(RUNTIME_CLASS(PInt)))
|
if (csym->ValueType->IsA(RUNTIME_CLASS(PInt)))
|
||||||
{
|
{
|
||||||
|
@ -400,13 +400,13 @@ FxExpression *FxConstant::MakeConstant(PSymbol *sym, const FScriptPosition &pos)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pos.Message(MSG_ERROR, "Invalid constant '%s'\n", csym->SymbolName.GetChars());
|
pos.Message(MSG_ERROR, "Invalid constant '%s'\n", csym->SymbolName.GetChars());
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pos.Message(MSG_ERROR, "'%s' is not a constant\n", sym->SymbolName.GetChars());
|
pos.Message(MSG_ERROR, "'%s' is not a constant\n", sym->SymbolName.GetChars());
|
||||||
x = NULL;
|
x = nullptr;
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -794,7 +794,7 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
FxExpression *x = basex;
|
FxExpression *x = basex;
|
||||||
x->ValueType = ValueType;
|
x->ValueType = ValueType;
|
||||||
basex = NULL;
|
basex = nullptr;
|
||||||
delete this;
|
delete this;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -833,7 +833,7 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx)
|
||||||
}
|
}
|
||||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -891,7 +891,7 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx)
|
||||||
if (basex->IsFloat())
|
if (basex->IsFloat())
|
||||||
{
|
{
|
||||||
FxExpression *x = basex;
|
FxExpression *x = basex;
|
||||||
basex = NULL;
|
basex = nullptr;
|
||||||
delete this;
|
delete this;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -923,7 +923,7 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -982,7 +982,7 @@ FxExpression *FxNameCast::Resolve(FCompileContext &ctx)
|
||||||
if (basex->ValueType == TypeName)
|
if (basex->ValueType == TypeName)
|
||||||
{
|
{
|
||||||
FxExpression *x = basex;
|
FxExpression *x = basex;
|
||||||
basex = NULL;
|
basex = nullptr;
|
||||||
delete this;
|
delete this;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -1001,7 +1001,7 @@ FxExpression *FxNameCast::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Cannot convert to name");
|
ScriptPosition.Message(MSG_ERROR, "Cannot convert to name");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1060,7 +1060,7 @@ FxExpression *FxStringCast::Resolve(FCompileContext &ctx)
|
||||||
if (basex->ValueType == TypeString)
|
if (basex->ValueType == TypeString)
|
||||||
{
|
{
|
||||||
FxExpression *x = basex;
|
FxExpression *x = basex;
|
||||||
basex = NULL;
|
basex = nullptr;
|
||||||
delete this;
|
delete this;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -1091,7 +1091,7 @@ FxExpression *FxStringCast::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Cannot convert to string");
|
ScriptPosition.Message(MSG_ERROR, "Cannot convert to string");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1158,7 +1158,7 @@ FxExpression *FxColorCast::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
FxExpression *x = basex;
|
FxExpression *x = basex;
|
||||||
x->ValueType = TypeColor;
|
x->ValueType = TypeColor;
|
||||||
basex = NULL;
|
basex = nullptr;
|
||||||
delete this;
|
delete this;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -1177,7 +1177,7 @@ FxExpression *FxColorCast::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Cannot convert to color");
|
ScriptPosition.Message(MSG_ERROR, "Cannot convert to color");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1237,7 +1237,7 @@ FxExpression *FxSoundCast::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
FxExpression *x = basex;
|
FxExpression *x = basex;
|
||||||
x->ValueType = TypeSound;
|
x->ValueType = TypeSound;
|
||||||
basex = NULL;
|
basex = nullptr;
|
||||||
delete this;
|
delete this;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -1256,7 +1256,7 @@ FxExpression *FxSoundCast::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Cannot convert to sound");
|
ScriptPosition.Message(MSG_ERROR, "Cannot convert to sound");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1318,6 +1318,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
|
||||||
// first deal with the simple types
|
// first deal with the simple types
|
||||||
if (ValueType == TypeError || basex->ValueType == TypeError)
|
if (ValueType == TypeError || basex->ValueType == TypeError)
|
||||||
{
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Trying to cast to invalid type. This error message means that somewhere in the script compiler an error check is missing.");
|
||||||
delete this;
|
delete this;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1502,7 +1503,7 @@ FxExpression *FxPlusSign::Resolve(FCompileContext& ctx)
|
||||||
if (Operand->IsNumeric() || Operand->IsVector())
|
if (Operand->IsNumeric() || Operand->IsVector())
|
||||||
{
|
{
|
||||||
FxExpression *e = Operand;
|
FxExpression *e = Operand;
|
||||||
Operand = NULL;
|
Operand = nullptr;
|
||||||
delete this;
|
delete this;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
@ -1510,7 +1511,7 @@ FxExpression *FxPlusSign::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1571,7 +1572,7 @@ FxExpression *FxMinusSign::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1587,7 +1588,14 @@ ExpEmit FxMinusSign::Emit(VMFunctionBuilder *build)
|
||||||
ExpEmit from = Operand->Emit(build);
|
ExpEmit from = Operand->Emit(build);
|
||||||
assert(from.Konst == 0);
|
assert(from.Konst == 0);
|
||||||
assert(ValueType->GetRegCount() == from.RegCount);
|
assert(ValueType->GetRegCount() == from.RegCount);
|
||||||
// Do it in-place.
|
// Do it in-place, unless a local variable
|
||||||
|
if (from.Fixed)
|
||||||
|
{
|
||||||
|
ExpEmit to = ExpEmit(build, from.RegType, from.RegCount);
|
||||||
|
build->Emit(Operand->ValueType->GetMoveOp(), to.RegNum, from.RegNum);
|
||||||
|
from = to;
|
||||||
|
}
|
||||||
|
|
||||||
if (ValueType->GetRegType() == REGT_INT)
|
if (ValueType->GetRegType() == REGT_INT)
|
||||||
{
|
{
|
||||||
build->Emit(OP_NEG, from.RegNum, from.RegNum, 0);
|
build->Emit(OP_NEG, from.RegNum, from.RegNum, 0);
|
||||||
|
@ -1653,10 +1661,10 @@ FxExpression *FxUnaryNotBitwise::Resolve(FCompileContext& ctx)
|
||||||
// DECORATE allows floats here so cast them to int.
|
// DECORATE allows floats here so cast them to int.
|
||||||
Operand = new FxIntCast(Operand, true);
|
Operand = new FxIntCast(Operand, true);
|
||||||
Operand = Operand->Resolve(ctx);
|
Operand = Operand->Resolve(ctx);
|
||||||
if (Operand == NULL)
|
if (Operand == nullptr)
|
||||||
{
|
{
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1665,7 +1673,7 @@ FxExpression *FxUnaryNotBitwise::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Integer type expected");
|
ScriptPosition.Message(MSG_ERROR, "Integer type expected");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Operand->isConstant())
|
if (Operand->isConstant())
|
||||||
|
@ -1804,13 +1812,13 @@ FxExpression *FxSizeAlign::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "cannot determine %s of a constant", Which == TK_AlignOf? "alignment" : "size");
|
ScriptPosition.Message(MSG_ERROR, "cannot determine %s of a constant", Which == TK_AlignOf? "alignment" : "size");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
else if (!Operand->RequestAddress(nullptr))
|
else if (!Operand->RequestAddress(nullptr))
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Operand must be addressable to determine %s", Which == TK_AlignOf ? "alignment" : "size");
|
ScriptPosition.Message(MSG_ERROR, "Operand must be addressable to determine %s", Which == TK_AlignOf ? "alignment" : "size");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2513,7 +2521,8 @@ FxAddSub::FxAddSub(int o, FxExpression *l, FxExpression *r)
|
||||||
FxExpression *FxAddSub::Resolve(FCompileContext& ctx)
|
FxExpression *FxAddSub::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
if (!ResolveLR(ctx, true)) return NULL;
|
if (!ResolveLR(ctx, true))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
if (!IsNumeric() && !IsVector())
|
if (!IsNumeric() && !IsVector())
|
||||||
{
|
{
|
||||||
|
@ -2652,13 +2661,14 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
|
|
||||||
if (!ResolveLR(ctx, true)) return NULL;
|
if (!ResolveLR(ctx, true))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
if (!IsNumeric() && !IsVector())
|
if (!IsNumeric() && !IsVector())
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
else if (left->isConstant() && right->isConstant())
|
else if (left->isConstant() && right->isConstant())
|
||||||
{
|
{
|
||||||
|
@ -2672,7 +2682,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Division by 0");
|
ScriptPosition.Message(MSG_ERROR, "Division by 0");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
v = Operator == '*'? v1 * v2 :
|
v = Operator == '*'? v1 * v2 :
|
||||||
|
@ -2693,7 +2703,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Division by 0");
|
ScriptPosition.Message(MSG_ERROR, "Division by 0");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
v = Operator == '*'? v1 * v2 :
|
v = Operator == '*'? v1 * v2 :
|
||||||
|
@ -2820,7 +2830,8 @@ FxExpression *FxPow::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
|
|
||||||
if (!ResolveLR(ctx, true)) return nullptr;
|
if (!ResolveLR(ctx, true))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
if (!IsNumeric())
|
if (!IsNumeric())
|
||||||
{
|
{
|
||||||
|
@ -2879,13 +2890,14 @@ FxCompareRel::FxCompareRel(int o, FxExpression *l, FxExpression *r)
|
||||||
FxExpression *FxCompareRel::Resolve(FCompileContext& ctx)
|
FxExpression *FxCompareRel::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
if (!ResolveLR(ctx, true)) return NULL;
|
if (!ResolveLR(ctx, true))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
if (!IsNumeric())
|
if (!IsNumeric())
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
else if (left->isConstant() && right->isConstant())
|
else if (left->isConstant() && right->isConstant())
|
||||||
{
|
{
|
||||||
|
@ -3038,19 +3050,20 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
|
|
||||||
if (!ResolveLR(ctx, true)) return NULL;
|
if (!ResolveLR(ctx, true))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
if (!left || !right)
|
if (!left || !right)
|
||||||
{
|
{
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsNumeric() && !IsPointer() && !IsVector() && ValueType != TypeName)
|
if (!IsNumeric() && !IsPointer() && !IsVector() && ValueType != TypeName)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Operator == TK_ApproxEq && left->ValueType->GetRegType() != REGT_FLOAT && left->ValueType->GetRegType() != REGT_STRING)
|
if (Operator == TK_ApproxEq && left->ValueType->GetRegType() != REGT_FLOAT && left->ValueType->GetRegType() != REGT_STRING)
|
||||||
|
@ -3174,7 +3187,8 @@ FxBinaryInt::FxBinaryInt(int o, FxExpression *l, FxExpression *r)
|
||||||
FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx)
|
FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
if (!ResolveLR(ctx, false)) return NULL;
|
if (!ResolveLR(ctx, false))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
if (IsFloat() && ctx.FromDecorate)
|
if (IsFloat() && ctx.FromDecorate)
|
||||||
{
|
{
|
||||||
|
@ -3189,10 +3203,10 @@ FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx)
|
||||||
right = new FxIntCast(right, ctx.FromDecorate);
|
right = new FxIntCast(right, ctx.FromDecorate);
|
||||||
right = right->Resolve(ctx);
|
right = right->Resolve(ctx);
|
||||||
}
|
}
|
||||||
if (left == NULL || right == NULL)
|
if (left == nullptr || right == nullptr)
|
||||||
{
|
{
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
ValueType = TypeSInt32;
|
ValueType = TypeSInt32;
|
||||||
}
|
}
|
||||||
|
@ -3201,7 +3215,7 @@ FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Integer type expected");
|
ScriptPosition.Message(MSG_ERROR, "Integer type expected");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
else if (left->isConstant() && right->isConstant())
|
else if (left->isConstant() && right->isConstant())
|
||||||
{
|
{
|
||||||
|
@ -3322,7 +3336,8 @@ FxLtGtEq::FxLtGtEq(FxExpression *l, FxExpression *r)
|
||||||
FxExpression *FxLtGtEq::Resolve(FCompileContext& ctx)
|
FxExpression *FxLtGtEq::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
if (!ResolveLR(ctx, true)) return NULL;
|
if (!ResolveLR(ctx, true))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
if (!left->IsNumeric() || !right->IsNumeric())
|
if (!left->IsNumeric() || !right->IsNumeric())
|
||||||
{
|
{
|
||||||
|
@ -3467,14 +3482,14 @@ FxExpression *FxBinaryLogical::Resolve(FCompileContext& ctx)
|
||||||
else if (b_left==1)
|
else if (b_left==1)
|
||||||
{
|
{
|
||||||
FxExpression *x = right;
|
FxExpression *x = right;
|
||||||
right=NULL;
|
right=nullptr;
|
||||||
delete this;
|
delete this;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
else if (b_right==1)
|
else if (b_right==1)
|
||||||
{
|
{
|
||||||
FxExpression *x = left;
|
FxExpression *x = left;
|
||||||
left=NULL;
|
left=nullptr;
|
||||||
delete this;
|
delete this;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -3496,14 +3511,14 @@ FxExpression *FxBinaryLogical::Resolve(FCompileContext& ctx)
|
||||||
else if (b_left==0)
|
else if (b_left==0)
|
||||||
{
|
{
|
||||||
FxExpression *x = right;
|
FxExpression *x = right;
|
||||||
right=NULL;
|
right=nullptr;
|
||||||
delete this;
|
delete this;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
else if (b_right==0)
|
else if (b_right==0)
|
||||||
{
|
{
|
||||||
FxExpression *x = left;
|
FxExpression *x = left;
|
||||||
left=NULL;
|
left=nullptr;
|
||||||
delete this;
|
delete this;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -3723,7 +3738,7 @@ ExpEmit FxTypeCheck::Emit(VMFunctionBuilder *build)
|
||||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinTypeCheck, BuiltinTypeCheck);
|
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinTypeCheck, BuiltinTypeCheck);
|
||||||
|
|
||||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||||
auto callfunc = ((PSymbolVMFunction *)sym)->Function;
|
auto callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||||
|
|
||||||
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
||||||
|
@ -3813,7 +3828,7 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx)
|
||||||
|
|
||||||
FxExpression *e = result? truex:falsex;
|
FxExpression *e = result? truex:falsex;
|
||||||
delete (result? falsex:truex);
|
delete (result? falsex:truex);
|
||||||
falsex = truex = NULL;
|
falsex = truex = nullptr;
|
||||||
delete this;
|
delete this;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
@ -3867,9 +3882,22 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build)
|
||||||
ExpEmit trueop = truex->Emit(build);
|
ExpEmit trueop = truex->Emit(build);
|
||||||
if (trueop.Konst)
|
if (trueop.Konst)
|
||||||
{
|
{
|
||||||
assert(trueop.RegType == REGT_FLOAT);
|
if (trueop.RegType == REGT_FLOAT)
|
||||||
out = ExpEmit(build, REGT_FLOAT);
|
{
|
||||||
build->Emit(OP_LKF, out.RegNum, trueop.RegNum);
|
out = ExpEmit(build, REGT_FLOAT);
|
||||||
|
build->Emit(OP_LKF, out.RegNum, trueop.RegNum);
|
||||||
|
}
|
||||||
|
else if (trueop.RegType == REGT_POINTER)
|
||||||
|
{
|
||||||
|
out = ExpEmit(build, REGT_POINTER);
|
||||||
|
build->Emit(OP_LKP, out.RegNum, trueop.RegNum);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(trueop.RegType == REGT_STRING);
|
||||||
|
out = ExpEmit(build, REGT_STRING);
|
||||||
|
build->Emit(OP_LKS, out.RegNum, trueop.RegNum);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3892,8 +3920,22 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build)
|
||||||
ExpEmit falseop = falsex->Emit(build);
|
ExpEmit falseop = falsex->Emit(build);
|
||||||
if (falseop.Konst)
|
if (falseop.Konst)
|
||||||
{
|
{
|
||||||
assert(falseop.RegType == REGT_FLOAT);
|
if (falseop.RegType == REGT_FLOAT)
|
||||||
build->Emit(OP_LKF, out.RegNum, falseop.RegNum);
|
{
|
||||||
|
out = ExpEmit(build, REGT_FLOAT);
|
||||||
|
build->Emit(OP_LKF, out.RegNum, falseop.RegNum);
|
||||||
|
}
|
||||||
|
else if (falseop.RegType == REGT_POINTER)
|
||||||
|
{
|
||||||
|
out = ExpEmit(build, REGT_POINTER);
|
||||||
|
build->Emit(OP_LKP, out.RegNum, falseop.RegNum);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(falseop.RegType == REGT_STRING);
|
||||||
|
out = ExpEmit(build, REGT_STRING);
|
||||||
|
build->Emit(OP_LKS, out.RegNum, falseop.RegNum);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3901,17 +3943,7 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build)
|
||||||
// returned by "true" so that only one register is returned by
|
// returned by "true" so that only one register is returned by
|
||||||
// this tree.
|
// this tree.
|
||||||
falseop.Free(build);
|
falseop.Free(build);
|
||||||
if (falseop.RegType == REGT_INT)
|
build->Emit(falsex->ValueType->GetMoveOp(), out.RegNum, falseop.RegNum, 0);
|
||||||
{
|
|
||||||
build->Emit(OP_MOVE, out.RegNum, falseop.RegNum, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(falseop.RegType == REGT_FLOAT);
|
|
||||||
assert(falseop.RegCount == out.RegCount);
|
|
||||||
static int flops[] = { OP_MOVEF, OP_MOVEV2, OP_MOVEV3 };
|
|
||||||
build->Emit(flops[falseop.RegNum], out.RegNum, falseop.RegNum, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
build->BackpatchToHere(truejump);
|
build->BackpatchToHere(truejump);
|
||||||
|
@ -3958,7 +3990,7 @@ FxExpression *FxAbs::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
else if (val->isConstant())
|
else if (val->isConstant())
|
||||||
{
|
{
|
||||||
|
@ -3976,7 +4008,7 @@ FxExpression *FxAbs::Resolve(FCompileContext &ctx)
|
||||||
default:
|
default:
|
||||||
// shouldn't happen
|
// shouldn't happen
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
FxExpression *x = new FxConstant(value, ScriptPosition);
|
FxExpression *x = new FxConstant(value, ScriptPosition);
|
||||||
delete this;
|
delete this;
|
||||||
|
@ -4047,7 +4079,7 @@ FxExpression *FxATan2::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter");
|
ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (yval->isConstant() && xval->isConstant())
|
if (yval->isConstant() && xval->isConstant())
|
||||||
{
|
{
|
||||||
|
@ -4151,7 +4183,7 @@ FxExpression *FxMinMax::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Arguments must be of type int or float");
|
ScriptPosition.Message(MSG_ERROR, "Arguments must be of type int or float");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (floatcount != 0)
|
if (floatcount != 0)
|
||||||
|
@ -4230,7 +4262,7 @@ FxExpression *FxMinMax::Resolve(FCompileContext &ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete choices[j];
|
delete choices[j];
|
||||||
choices[j] = NULL;
|
choices[j] = nullptr;
|
||||||
choices.Delete(j);
|
choices.Delete(j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4329,12 +4361,12 @@ FxRandom::FxRandom(FRandom * r, FxExpression *mi, FxExpression *ma, const FScrip
|
||||||
: FxExpression(EFX_Random, pos)
|
: FxExpression(EFX_Random, pos)
|
||||||
{
|
{
|
||||||
EmitTail = false;
|
EmitTail = false;
|
||||||
if (mi != NULL && ma != NULL)
|
if (mi != nullptr && ma != nullptr)
|
||||||
{
|
{
|
||||||
min = new FxIntCast(mi, nowarn);
|
min = new FxIntCast(mi, nowarn);
|
||||||
max = new FxIntCast(ma, nowarn);
|
max = new FxIntCast(ma, nowarn);
|
||||||
}
|
}
|
||||||
else min = max = NULL;
|
else min = max = nullptr;
|
||||||
rng = r;
|
rng = r;
|
||||||
ValueType = TypeSInt32;
|
ValueType = TypeSInt32;
|
||||||
}
|
}
|
||||||
|
@ -4424,13 +4456,13 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build)
|
||||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom);
|
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom);
|
||||||
|
|
||||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||||
|
|
||||||
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
||||||
|
|
||||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG));
|
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG));
|
||||||
if (min != NULL && max != NULL)
|
if (min != nullptr && max != nullptr)
|
||||||
{
|
{
|
||||||
EmitParameter(build, min, ScriptPosition);
|
EmitParameter(build, min, ScriptPosition);
|
||||||
EmitParameter(build, max, ScriptPosition);
|
EmitParameter(build, max, ScriptPosition);
|
||||||
|
@ -4545,7 +4577,7 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
|
||||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom);
|
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom);
|
||||||
|
|
||||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||||
|
|
||||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG));
|
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG));
|
||||||
|
@ -4623,9 +4655,9 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos)
|
FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos)
|
||||||
: FxRandom(r, NULL, NULL, pos, true)
|
: FxRandom(r, nullptr, nullptr, pos, true)
|
||||||
{
|
{
|
||||||
if (mi != NULL && ma != NULL)
|
if (mi != nullptr && ma != nullptr)
|
||||||
{
|
{
|
||||||
min = new FxFloatCast(mi);
|
min = new FxFloatCast(mi);
|
||||||
max = new FxFloatCast(ma);
|
max = new FxFloatCast(ma);
|
||||||
|
@ -4670,13 +4702,13 @@ ExpEmit FxFRandom::Emit(VMFunctionBuilder *build)
|
||||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinFRandom, BuiltinFRandom);
|
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinFRandom, BuiltinFRandom);
|
||||||
|
|
||||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||||
|
|
||||||
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
||||||
|
|
||||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG));
|
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG));
|
||||||
if (min != NULL && max != NULL)
|
if (min != nullptr && max != nullptr)
|
||||||
{
|
{
|
||||||
EmitParameter(build, min, ScriptPosition);
|
EmitParameter(build, min, ScriptPosition);
|
||||||
EmitParameter(build, max, ScriptPosition);
|
EmitParameter(build, max, ScriptPosition);
|
||||||
|
@ -4764,7 +4796,7 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build)
|
||||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom);
|
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom);
|
||||||
|
|
||||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||||
|
|
||||||
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
||||||
|
@ -4896,7 +4928,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// now check the global identifiers.
|
// now check the global identifiers.
|
||||||
else if ((sym = ctx.FindGlobal(Identifier)) != NULL)
|
else if ((sym = ctx.FindGlobal(Identifier)) != nullptr)
|
||||||
{
|
{
|
||||||
if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst)))
|
if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst)))
|
||||||
{
|
{
|
||||||
|
@ -4910,7 +4942,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// and line specials
|
// and line specials
|
||||||
else if ((num = P_FindLineSpecial(Identifier, NULL, NULL)))
|
else if ((num = P_FindLineSpecial(Identifier, nullptr, nullptr)))
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as line special %d\n", Identifier.GetChars(), num);
|
ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as line special %d\n", Identifier.GetChars(), num);
|
||||||
newex = new FxConstant(num, ScriptPosition);
|
newex = new FxConstant(num, ScriptPosition);
|
||||||
|
@ -5355,25 +5387,25 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
|
||||||
// DECORATE allows floats here so cast them to int.
|
// DECORATE allows floats here so cast them to int.
|
||||||
index = new FxIntCast(index, ctx.FromDecorate);
|
index = new FxIntCast(index, ctx.FromDecorate);
|
||||||
index = index->Resolve(ctx);
|
index = index->Resolve(ctx);
|
||||||
if (index == NULL)
|
if (index == nullptr)
|
||||||
{
|
{
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (index->ValueType->GetRegType() != REGT_INT && index->ValueType != TypeName)
|
if (index->ValueType->GetRegType() != REGT_INT && index->ValueType != TypeName)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Array index must be integer");
|
ScriptPosition.Message(MSG_ERROR, "Array index must be integer");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
PArray *arraytype = dyn_cast<PArray>(Array->ValueType);
|
PArray *arraytype = dyn_cast<PArray>(Array->ValueType);
|
||||||
if (arraytype == NULL)
|
if (arraytype == nullptr)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "'[]' can only be used with arrays.");
|
ScriptPosition.Message(MSG_ERROR, "'[]' can only be used with arrays.");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (index->isConstant())
|
if (index->isConstant())
|
||||||
{
|
{
|
||||||
|
@ -5382,7 +5414,7 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Array index out of bounds");
|
ScriptPosition.Message(MSG_ERROR, "Array index out of bounds");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5392,13 +5424,13 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
|
||||||
// int arrays only for now
|
// int arrays only for now
|
||||||
ScriptPosition.Message(MSG_ERROR, "Only numeric arrays are supported.");
|
ScriptPosition.Message(MSG_ERROR, "Only numeric arrays are supported.");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (!Array->RequestAddress(&AddressWritable))
|
if (!Array->RequestAddress(&AddressWritable))
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Unable to dereference array.");
|
ScriptPosition.Message(MSG_ERROR, "Unable to dereference array.");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -5901,12 +5933,12 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx)
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
|
|
||||||
SAFE_RESOLVE_OPT(Self, ctx);
|
SAFE_RESOLVE_OPT(Self, ctx);
|
||||||
if (ArgList != NULL)
|
if (ArgList != nullptr)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < ArgList->Size(); i++)
|
for (unsigned i = 0; i < ArgList->Size(); i++)
|
||||||
{
|
{
|
||||||
(*ArgList)[i] = (*ArgList)[i]->Resolve(ctx);
|
(*ArgList)[i] = (*ArgList)[i]->Resolve(ctx);
|
||||||
if ((*ArgList)[i] == NULL)
|
if ((*ArgList)[i] == nullptr)
|
||||||
{
|
{
|
||||||
failed = true;
|
failed = true;
|
||||||
}
|
}
|
||||||
|
@ -5934,7 +5966,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx)
|
||||||
if (failed)
|
if (failed)
|
||||||
{
|
{
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ValueType = TypeSInt32;
|
ValueType = TypeSInt32;
|
||||||
|
@ -5959,7 +5991,7 @@ int BuiltinCallLineSpecial(VMFrameStack *stack, VMValue *param, TArray<VMValue>
|
||||||
{
|
{
|
||||||
v[i - 2] = param[i].i;
|
v[i - 2] = param[i].i;
|
||||||
}
|
}
|
||||||
ACTION_RETURN_INT(P_ExecuteSpecial(param[0].i, NULL, reinterpret_cast<AActor*>(param[1].a), false, v[0], v[1], v[2], v[3], v[4]));
|
ACTION_RETURN_INT(P_ExecuteSpecial(param[0].i, nullptr, reinterpret_cast<AActor*>(param[1].a), false, v[0], v[1], v[2], v[3], v[4]));
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
|
ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
|
||||||
|
@ -5970,7 +6002,7 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
|
||||||
// fixme: This really should use the Self pointer that got passed to this class instead of just using the first argument from the function.
|
// fixme: This really should use the Self pointer that got passed to this class instead of just using the first argument from the function.
|
||||||
// Once static functions are possible, or specials can be called through a member access operator this won't work anymore.
|
// Once static functions are possible, or specials can be called through a member access operator this won't work anymore.
|
||||||
build->Emit(OP_PARAM, 0, REGT_POINTER, 0); // pass self
|
build->Emit(OP_PARAM, 0, REGT_POINTER, 0); // pass self
|
||||||
if (ArgList != NULL)
|
if (ArgList != nullptr)
|
||||||
{
|
{
|
||||||
for (; i < ArgList->Size(); ++i)
|
for (; i < ArgList->Size(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -6002,7 +6034,7 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
|
||||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinCallLineSpecial, BuiltinCallLineSpecial);
|
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinCallLineSpecial, BuiltinCallLineSpecial);
|
||||||
|
|
||||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||||
|
|
||||||
if (EmitTail)
|
if (EmitTail)
|
||||||
|
@ -6144,7 +6176,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
if (failed)
|
if (failed)
|
||||||
{
|
{
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
TArray<PType *> &rets = proto->ReturnTypes;
|
TArray<PType *> &rets = proto->ReturnTypes;
|
||||||
if (rets.Size() > 0)
|
if (rets.Size() > 0)
|
||||||
|
@ -6207,7 +6239,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Emit code to pass explicit parameters
|
// Emit code to pass explicit parameters
|
||||||
if (ArgList != NULL)
|
if (ArgList != nullptr)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < ArgList->Size(); ++i)
|
for (unsigned i = 0; i < ArgList->Size(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -6311,25 +6343,25 @@ FxExpression *FxFlopFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
|
|
||||||
if (ArgList == NULL || ArgList->Size() != 1)
|
if (ArgList == nullptr || ArgList->Size() != 1)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "%s only has one parameter", FName(FxFlops[Index].Name).GetChars());
|
ScriptPosition.Message(MSG_ERROR, "%s only has one parameter", FName(FxFlops[Index].Name).GetChars());
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*ArgList)[0] = (*ArgList)[0]->Resolve(ctx);
|
(*ArgList)[0] = (*ArgList)[0]->Resolve(ctx);
|
||||||
if ((*ArgList)[0] == NULL)
|
if ((*ArgList)[0] == nullptr)
|
||||||
{
|
{
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(*ArgList)[0]->IsNumeric())
|
if (!(*ArgList)[0]->IsNumeric())
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter");
|
ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if ((*ArgList)[0]->isConstant())
|
if ((*ArgList)[0]->isConstant())
|
||||||
{
|
{
|
||||||
|
@ -6417,7 +6449,7 @@ FxExpression *FxSequence::Resolve(FCompileContext &ctx)
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
for (unsigned i = 0; i < Expressions.Size(); ++i)
|
for (unsigned i = 0; i < Expressions.Size(); ++i)
|
||||||
{
|
{
|
||||||
if (NULL == (Expressions[i] = Expressions[i]->Resolve(ctx)))
|
if (nullptr == (Expressions[i] = Expressions[i]->Resolve(ctx)))
|
||||||
{
|
{
|
||||||
delete this;
|
delete this;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -6455,7 +6487,7 @@ VMFunction *FxSequence::GetDirectFunction()
|
||||||
{
|
{
|
||||||
return Expressions[0]->GetDirectFunction();
|
return Expressions[0]->GetDirectFunction();
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -6792,7 +6824,7 @@ FxIfStatement::FxIfStatement(FxExpression *cond, FxExpression *true_part,
|
||||||
WhenFalse = false_part;
|
WhenFalse = false_part;
|
||||||
if (WhenTrue != nullptr) WhenTrue->NeedResult = false;
|
if (WhenTrue != nullptr) WhenTrue->NeedResult = false;
|
||||||
if (WhenFalse != nullptr) WhenFalse->NeedResult = false;
|
if (WhenFalse != nullptr) WhenFalse->NeedResult = false;
|
||||||
assert(cond != NULL);
|
assert(cond != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
FxIfStatement::~FxIfStatement()
|
FxIfStatement::~FxIfStatement()
|
||||||
|
@ -6840,8 +6872,8 @@ FxExpression *FxIfStatement::Resolve(FCompileContext &ctx)
|
||||||
|
|
||||||
FxExpression *e = result ? WhenTrue : WhenFalse;
|
FxExpression *e = result ? WhenTrue : WhenFalse;
|
||||||
delete (result ? WhenFalse : WhenTrue);
|
delete (result ? WhenFalse : WhenTrue);
|
||||||
WhenTrue = WhenFalse = NULL;
|
WhenTrue = WhenFalse = nullptr;
|
||||||
if (e == NULL) e = new FxNop(ScriptPosition); // create a dummy if this statement gets completely removed by optimizing out the constant parts.
|
if (e == nullptr) e = new FxNop(ScriptPosition); // create a dummy if this statement gets completely removed by optimizing out the constant parts.
|
||||||
delete this;
|
delete this;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
@ -6861,7 +6893,7 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build)
|
||||||
ExpEmit cond = Condition->Emit(build);
|
ExpEmit cond = Condition->Emit(build);
|
||||||
assert(cond.RegType != REGT_STRING && !cond.Konst);
|
assert(cond.RegType != REGT_STRING && !cond.Konst);
|
||||||
|
|
||||||
if (WhenTrue != NULL)
|
if (WhenTrue != nullptr)
|
||||||
{
|
{
|
||||||
path1 = WhenTrue;
|
path1 = WhenTrue;
|
||||||
path2 = WhenFalse;
|
path2 = WhenFalse;
|
||||||
|
@ -6871,9 +6903,9 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
// When there is only a false path, reverse the condition so we can
|
// When there is only a false path, reverse the condition so we can
|
||||||
// treat it as a true path.
|
// treat it as a true path.
|
||||||
assert(WhenFalse != NULL);
|
assert(WhenFalse != nullptr);
|
||||||
path1 = WhenFalse;
|
path1 = WhenFalse;
|
||||||
path2 = NULL;
|
path2 = nullptr;
|
||||||
condcheck = 0;
|
condcheck = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6900,7 +6932,7 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build)
|
||||||
// Evaluate first path
|
// Evaluate first path
|
||||||
v = path1->Emit(build);
|
v = path1->Emit(build);
|
||||||
v.Free(build);
|
v.Free(build);
|
||||||
if (path2 != NULL)
|
if (path2 != nullptr)
|
||||||
{
|
{
|
||||||
size_t path1jump = build->Emit(OP_JMP, 0);
|
size_t path1jump = build->Emit(OP_JMP, 0);
|
||||||
// Evaluate second path
|
// Evaluate second path
|
||||||
|
@ -7412,18 +7444,18 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Cannot convert %s to class type", basex->ValueType->DescriptiveName());
|
ScriptPosition.Message(MSG_ERROR, "Cannot convert %s to class type", basex->ValueType->DescriptiveName());
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (basex->isConstant())
|
if (basex->isConstant())
|
||||||
{
|
{
|
||||||
FName clsname = static_cast<FxConstant *>(basex)->GetValue().GetName();
|
FName clsname = static_cast<FxConstant *>(basex)->GetValue().GetName();
|
||||||
PClass *cls = NULL;
|
PClass *cls = nullptr;
|
||||||
|
|
||||||
if (clsname != NAME_None)
|
if (clsname != NAME_None)
|
||||||
{
|
{
|
||||||
cls = PClass::FindClass(clsname);
|
cls = PClass::FindClass(clsname);
|
||||||
if (cls == NULL)
|
if (cls == nullptr)
|
||||||
{
|
{
|
||||||
/* lax */
|
/* lax */
|
||||||
// Since this happens in released WADs it must pass without a terminal error... :(
|
// Since this happens in released WADs it must pass without a terminal error... :(
|
||||||
|
@ -7437,7 +7469,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars());
|
ScriptPosition.Message(MSG_ERROR, "class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars());
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
ScriptPosition.Message(MSG_DEBUG, "resolving '%s' as class name", clsname.GetChars());
|
ScriptPosition.Message(MSG_DEBUG, "resolving '%s' as class name", clsname.GetChars());
|
||||||
}
|
}
|
||||||
|
@ -7474,7 +7506,7 @@ int BuiltinNameToClass(VMFrameStack *stack, VMValue *param, TArray<VMValue> &def
|
||||||
if (!cls->IsDescendantOf(desttype))
|
if (!cls->IsDescendantOf(desttype))
|
||||||
{
|
{
|
||||||
Printf("class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars());
|
Printf("class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars());
|
||||||
cls = NULL;
|
cls = nullptr;
|
||||||
}
|
}
|
||||||
ret->SetPointer(const_cast<PClass *>(cls), ATAG_OBJECT);
|
ret->SetPointer(const_cast<PClass *>(cls), ATAG_OBJECT);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -7484,7 +7516,7 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
if (basex->ValueType != TypeName)
|
if (basex->ValueType != TypeName)
|
||||||
{
|
{
|
||||||
return ExpEmit(build->GetConstantAddress(NULL, ATAG_OBJECT), REGT_POINTER, true);
|
return ExpEmit(build->GetConstantAddress(nullptr, ATAG_OBJECT), REGT_POINTER, true);
|
||||||
}
|
}
|
||||||
ExpEmit clsname = basex->Emit(build);
|
ExpEmit clsname = basex->Emit(build);
|
||||||
assert(!clsname.Konst);
|
assert(!clsname.Konst);
|
||||||
|
@ -7497,7 +7529,7 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
|
||||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinNameToClass, BuiltinNameToClass);
|
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinNameToClass, BuiltinNameToClass);
|
||||||
|
|
||||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||||
|
|
||||||
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1);
|
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1);
|
||||||
|
@ -7526,7 +7558,7 @@ FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx)
|
||||||
ScriptPosition.Message(MSG_ERROR, "%s: Attempt to jump to non existing state index %d",
|
ScriptPosition.Message(MSG_ERROR, "%s: Attempt to jump to non existing state index %d",
|
||||||
ctx.Class->TypeName.GetChars(), index);
|
ctx.Class->TypeName.GetChars(), index);
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
FxExpression *x = new FxConstant(aclass->OwnedStates + index, ScriptPosition);
|
FxExpression *x = new FxConstant(aclass->OwnedStates + index, ScriptPosition);
|
||||||
delete this;
|
delete this;
|
||||||
|
@ -7677,7 +7709,7 @@ FxMultiNameState::FxMultiNameState(const char *_statestring, const FScriptPositi
|
||||||
}
|
}
|
||||||
names = MakeStateNameList(statestring);
|
names = MakeStateNameList(statestring);
|
||||||
names.Insert(0, scopename);
|
names.Insert(0, scopename);
|
||||||
scope = NULL;
|
scope = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -7693,7 +7725,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx)
|
||||||
|
|
||||||
if (names[0] == NAME_None)
|
if (names[0] == NAME_None)
|
||||||
{
|
{
|
||||||
scope = NULL;
|
scope = nullptr;
|
||||||
}
|
}
|
||||||
else if (names[0] == NAME_Super)
|
else if (names[0] == NAME_Super)
|
||||||
{
|
{
|
||||||
|
@ -7702,27 +7734,27 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
scope = PClass::FindActor(names[0]);
|
scope = PClass::FindActor(names[0]);
|
||||||
if (scope == NULL)
|
if (scope == nullptr)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Unknown class '%s' in state label", names[0].GetChars());
|
ScriptPosition.Message(MSG_ERROR, "Unknown class '%s' in state label", names[0].GetChars());
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
else if (!scope->IsAncestorOf(ctx.Class))
|
else if (!scope->IsAncestorOf(ctx.Class))
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(), ctx.Class->TypeName.GetChars());
|
ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(), ctx.Class->TypeName.GetChars());
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (scope != NULL)
|
if (scope != nullptr)
|
||||||
{
|
{
|
||||||
FState *destination = NULL;
|
FState *destination = nullptr;
|
||||||
// If the label is class specific we can resolve it right here
|
// If the label is class specific we can resolve it right here
|
||||||
if (names[1] != NAME_None)
|
if (names[1] != NAME_None)
|
||||||
{
|
{
|
||||||
destination = scope->FindState(names.Size()-1, &names[1], false);
|
destination = scope->FindState(names.Size()-1, &names[1], false);
|
||||||
if (destination == NULL)
|
if (destination == nullptr)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_OPTERROR, "Unknown state jump destination");
|
ScriptPosition.Message(MSG_OPTERROR, "Unknown state jump destination");
|
||||||
/* lax */
|
/* lax */
|
||||||
|
@ -7749,7 +7781,7 @@ static int DoFindState(VMFrameStack *stack, VMValue *param, int numparam, VMRetu
|
||||||
{
|
{
|
||||||
PARAM_OBJECT_AT(0, self, AActor);
|
PARAM_OBJECT_AT(0, self, AActor);
|
||||||
FState *state = self->GetClass()->FindState(numparam - 1, names);
|
FState *state = self->GetClass()->FindState(numparam - 1, names);
|
||||||
if (state == NULL)
|
if (state == nullptr)
|
||||||
{
|
{
|
||||||
const char *dot = "";
|
const char *dot = "";
|
||||||
Printf("Jump target '");
|
Printf("Jump target '");
|
||||||
|
@ -7822,7 +7854,7 @@ ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||||
|
|
||||||
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), names.Size() + 1, 1);
|
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), names.Size() + 1, 1);
|
||||||
|
|
|
@ -671,7 +671,7 @@ void InitThingdef()
|
||||||
symt.AddSymbol(new PField(NAME_Score, TypeSInt32, VARF_Native, myoffsetof(AActor, Score)));
|
symt.AddSymbol(new PField(NAME_Score, TypeSInt32, VARF_Native, myoffsetof(AActor, Score)));
|
||||||
symt.AddSymbol(new PField(NAME_Accuracy, TypeSInt32, VARF_Native, myoffsetof(AActor, accuracy)));
|
symt.AddSymbol(new PField(NAME_Accuracy, TypeSInt32, VARF_Native, myoffsetof(AActor, accuracy)));
|
||||||
symt.AddSymbol(new PField(NAME_Stamina, TypeSInt32, VARF_Native, myoffsetof(AActor, stamina)));
|
symt.AddSymbol(new PField(NAME_Stamina, TypeSInt32, VARF_Native, myoffsetof(AActor, stamina)));
|
||||||
symt.AddSymbol(new PField(NAME_Height, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, Height)));
|
symt.AddSymbol(new PField(NAME_Height, TypeFloat64, VARF_Native, myoffsetof(AActor, Height)));
|
||||||
symt.AddSymbol(new PField(NAME_Radius, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, radius)));
|
symt.AddSymbol(new PField(NAME_Radius, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, radius)));
|
||||||
symt.AddSymbol(new PField(NAME_ReactionTime, TypeSInt32, VARF_Native, myoffsetof(AActor, reactiontime)));
|
symt.AddSymbol(new PField(NAME_ReactionTime, TypeSInt32, VARF_Native, myoffsetof(AActor, reactiontime)));
|
||||||
symt.AddSymbol(new PField(NAME_MeleeRange, TypeFloat64, VARF_Native, myoffsetof(AActor, meleerange)));
|
symt.AddSymbol(new PField(NAME_MeleeRange, TypeFloat64, VARF_Native, myoffsetof(AActor, meleerange)));
|
||||||
|
@ -698,6 +698,7 @@ void InitThingdef()
|
||||||
symt.AddSymbol(new PField("Pos", TypeVector3, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, __Pos)));
|
symt.AddSymbol(new PField("Pos", TypeVector3, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, __Pos)));
|
||||||
symt.AddSymbol(new PField("Vel", TypeVector3, VARF_Native, myoffsetof(AActor, Vel)));
|
symt.AddSymbol(new PField("Vel", TypeVector3, VARF_Native, myoffsetof(AActor, Vel)));
|
||||||
symt.AddSymbol(new PField("Scale", TypeVector2, VARF_Native, myoffsetof(AActor, Scale)));
|
symt.AddSymbol(new PField("Scale", TypeVector2, VARF_Native, myoffsetof(AActor, Scale)));
|
||||||
|
symt.AddSymbol(new PField("CurState", TypeState, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, state))); // has to be renamed on the script side because it clashes with the same named type.
|
||||||
symt.AddSymbol(new PField("SeeState", TypeState, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, SeeState)));
|
symt.AddSymbol(new PField("SeeState", TypeState, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, SeeState)));
|
||||||
symt.AddSymbol(new PField(NAME_Target, TypeActor, VARF_Native, myoffsetof(AActor, target)));
|
symt.AddSymbol(new PField(NAME_Target, TypeActor, VARF_Native, myoffsetof(AActor, target)));
|
||||||
symt.AddSymbol(new PField(NAME_Master, TypeActor, VARF_Native, myoffsetof(AActor, master)));
|
symt.AddSymbol(new PField(NAME_Master, TypeActor, VARF_Native, myoffsetof(AActor, master)));
|
||||||
|
|
|
@ -1490,6 +1490,7 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt)
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
Error(type, "Unable to resolve %s as type.", FName(type->UserType->Id).GetChars());
|
||||||
return TypeError;
|
return TypeError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2186,8 +2187,8 @@ static bool CheckRandom(ZCC_Expression *duration)
|
||||||
FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af)
|
FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af)
|
||||||
{
|
{
|
||||||
// We have 3 cases to consider here:
|
// We have 3 cases to consider here:
|
||||||
// 1. An action function without parameters. This can be called directly
|
// 1. A function without parameters. This can be called directly
|
||||||
// 2. An action functon with parameters or a non-action function. This needs to be wrapped into a helper function to set everything up.
|
// 2. A functon with parameters. This needs to be wrapped into a helper function to set everything up.
|
||||||
// 3. An anonymous function.
|
// 3. An anonymous function.
|
||||||
|
|
||||||
// 1. and 2. are exposed through AST_ExprFunctionCall
|
// 1. and 2. are exposed through AST_ExprFunctionCall
|
||||||
|
@ -2236,9 +2237,10 @@ void ZCCCompiler::CompileStates()
|
||||||
{
|
{
|
||||||
for (auto c : Classes)
|
for (auto c : Classes)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!c->Type()->IsDescendantOf(RUNTIME_CLASS(AActor)))
|
if (!c->Type()->IsDescendantOf(RUNTIME_CLASS(AActor)))
|
||||||
{
|
{
|
||||||
Error(c->cls, "%s: States can only be defined for actors.", c->Type()->TypeName.GetChars());
|
if (c->States.Size()) Error(c->cls, "%s: States can only be defined for actors.", c->Type()->TypeName.GetChars());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
FString statename; // The state builder wants the label as one complete string, not separated into tokens.
|
FString statename; // The state builder wants the label as one complete string, not separated into tokens.
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
zscript/base.txt
|
||||||
zscript/constants.txt
|
zscript/constants.txt
|
||||||
zscript/actor.txt
|
zscript/actor.txt
|
||||||
|
|
||||||
|
|
|
@ -53,9 +53,13 @@ class Actor : Thinker native
|
||||||
return GetPointer(ptr_select1) == GetPointer(ptr_select2);
|
return GetPointer(ptr_select1) == GetPointer(ptr_select2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
native static bool isDehState(state st);
|
||||||
native void SetOrigin(vector3 newpos, bool moving);
|
native void SetOrigin(vector3 newpos, bool moving);
|
||||||
|
native void SetXYZ(vector3 newpos);
|
||||||
native Actor GetPointer(int aaptr);
|
native Actor GetPointer(int aaptr);
|
||||||
|
native static Actor Spawn(class<Actor> type, vector3 pos = (0,0,0), int replace = NO_REPLACE);
|
||||||
native Actor SpawnMissile(Actor dest, class<Actor> type, Actor owner = null);
|
native Actor SpawnMissile(Actor dest, class<Actor> type, Actor owner = null);
|
||||||
|
native Actor OldSpawnMissile(Actor dest, class<Actor> type, Actor owner = null);
|
||||||
native void TraceBleed(int damage, Actor missile);
|
native void TraceBleed(int damage, Actor missile);
|
||||||
native bool CheckMeleeRange();
|
native bool CheckMeleeRange();
|
||||||
native int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags = 0, double angle = 0);
|
native int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags = 0, double angle = 0);
|
||||||
|
@ -228,7 +232,6 @@ class Actor : Thinker native
|
||||||
native void A_SpawnFly(class<Actor> spawntype = null); // needs special treatment for default
|
native void A_SpawnFly(class<Actor> spawntype = null); // needs special treatment for default
|
||||||
native void A_BrainExplode();
|
native void A_BrainExplode();
|
||||||
native void A_Detonate();
|
native void A_Detonate();
|
||||||
native void A_Mushroom(class<Actor> spawntype = "FatShot", int numspawns = 0, int flags = 0, float vrange = 4.0, float hrange = 0.5);
|
|
||||||
native bool A_CallSpecial(int special, int arg1=0, int arg2=0, int arg3=0, int arg4=0, int arg5=0);
|
native bool A_CallSpecial(int special, int arg1=0, int arg2=0, int arg3=0, int arg4=0, int arg5=0);
|
||||||
|
|
||||||
native void A_SetFloorClip();
|
native void A_SetFloorClip();
|
||||||
|
|
8
wadsrc/static/zscript/base.txt
Normal file
8
wadsrc/static/zscript/base.txt
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
class Object native
|
||||||
|
{
|
||||||
|
/*virtual*/ native void Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
class Thinker : Object native
|
||||||
|
{
|
||||||
|
}
|
|
@ -876,3 +876,9 @@ enum EDmgFlags
|
||||||
DMG_NO_PROTECT = 256,
|
DMG_NO_PROTECT = 256,
|
||||||
DMG_USEANGLE = 512,
|
DMG_USEANGLE = 512,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum EReplace
|
||||||
|
{
|
||||||
|
NO_REPLACE = 0,
|
||||||
|
ALLOW_REPLACE = 1
|
||||||
|
}
|
||||||
|
|
|
@ -110,6 +110,12 @@ extend class Actor
|
||||||
A_PlaySound("fatso/raiseguns", CHAN_WEAPON);
|
A_PlaySound("fatso/raiseguns", CHAN_WEAPON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mancubus attack,
|
||||||
|
// firing three missiles in three different directions?
|
||||||
|
// Doesn't look like it.
|
||||||
|
//
|
||||||
|
|
||||||
void A_FatAttack1(class<Actor> spawntype = "FatShot")
|
void A_FatAttack1(class<Actor> spawntype = "FatShot")
|
||||||
{
|
{
|
||||||
if (target)
|
if (target)
|
||||||
|
@ -163,5 +169,54 @@ extend class Actor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// killough 9/98: a mushroom explosion effect, sorta :)
|
||||||
|
// Original idea: Linguica
|
||||||
|
//
|
||||||
|
|
||||||
|
void A_Mushroom(class<Actor> spawntype = "FatShot", int numspawns = 0, int flags = 0, float vrange = 4.0, float hrange = 0.5)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (numspawns == 0)
|
||||||
|
{
|
||||||
|
numspawns = GetMissileDamage(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
A_Explode(128, 128, (flags & MSF_DontHurt) ? 0 : XF_HURTSOURCE);
|
||||||
|
|
||||||
|
// Now launch mushroom cloud
|
||||||
|
Actor aimtarget = Spawn("Mapspot", pos, NO_REPLACE); // We need something to aim at.
|
||||||
|
Actor owner = (flags & MSF_DontHurt) ? target : self;
|
||||||
|
aimtarget.Height = Height;
|
||||||
|
|
||||||
|
bool shootmode = ((flags & MSF_Classic) || // Flag explicitely set, or no flags and compat options
|
||||||
|
(flags == 0 && isDehState(CurState) && GetCVar("compat_mushroom")));
|
||||||
|
|
||||||
|
for (i = -numspawns; i <= numspawns; i += 8)
|
||||||
|
{
|
||||||
|
for (j = -numspawns; j <= numspawns; j += 8)
|
||||||
|
{
|
||||||
|
Actor mo;
|
||||||
|
aimtarget.SetXYZ(pos + (i, j, (i, j).Length() * vrange)); // Aim up fairly high
|
||||||
|
if (shootmode)
|
||||||
|
{ // Use old function for MBF compatibility
|
||||||
|
mo = OldSpawnMissile(aimtarget, spawntype, owner);
|
||||||
|
}
|
||||||
|
else // Use normal function
|
||||||
|
{
|
||||||
|
mo = SpawnMissile(aimtarget, spawntype, owner);
|
||||||
|
}
|
||||||
|
if (mo)
|
||||||
|
{ // Slow it down a bit
|
||||||
|
mo.Vel *= hrange;
|
||||||
|
mo.bNoGravity = false; // Make debris fall under gravity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aimtarget.Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue