mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 13:01:47 +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_bossbrain.cpp
|
||||
g_doom/a_doomweaps.cpp
|
||||
g_doom/a_fatso.cpp
|
||||
g_doom/a_keen.cpp
|
||||
g_doom/a_lostsoul.cpp
|
||||
g_doom/a_painelemental.cpp
|
||||
|
|
|
@ -1488,6 +1488,14 @@ static int PatchFrame (int frameNum)
|
|||
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)
|
||||
{
|
||||
int result;
|
||||
|
|
|
@ -349,6 +349,13 @@ void DObject::Destroy ()
|
|||
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_bossbrain.cpp"
|
||||
#include "a_doomweaps.cpp"
|
||||
#include "a_fatso.cpp"
|
||||
#include "a_keen.cpp"
|
||||
#include "a_lostsoul.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
|
||||
};
|
||||
|
||||
enum EStateType
|
||||
enum EStateType : int // this must ensure proper alignment.
|
||||
{
|
||||
STATE_Actor,
|
||||
STATE_Psprite,
|
||||
|
|
|
@ -4258,6 +4258,17 @@ AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t a
|
|||
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)
|
||||
{
|
||||
PClass *cls = PClass::FindClass(classname);
|
||||
|
@ -5951,6 +5962,16 @@ AActor *P_OldSpawnMissile(AActor *source, AActor *owner, AActor *dest, PClassAct
|
|||
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
|
||||
|
@ -6616,6 +6637,16 @@ DEFINE_ACTION_FUNCTION(AActor, VelFromAngle)
|
|||
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
|
||||
|
|
|
@ -156,7 +156,7 @@ void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos)
|
|||
|
||||
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)
|
||||
{
|
||||
PSymbol *sym = Builtins.FindSymbol(funcname, false);
|
||||
if (sym == NULL)
|
||||
if (sym == nullptr)
|
||||
{
|
||||
PSymbolVMFunction *symfunc = new PSymbolVMFunction(funcname);
|
||||
VMNativeFunction *calldec = new VMNativeFunction(func, funcname);
|
||||
|
@ -282,7 +282,7 @@ bool FxExpression::isConstant() const
|
|||
|
||||
VMFunction *FxExpression::GetDirectFunction()
|
||||
{
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -387,7 +387,7 @@ FxExpression *FxConstant::MakeConstant(PSymbol *sym, const FScriptPosition &pos)
|
|||
{
|
||||
FxExpression *x;
|
||||
PSymbolConstNumeric *csym = dyn_cast<PSymbolConstNumeric>(sym);
|
||||
if (csym != NULL)
|
||||
if (csym != nullptr)
|
||||
{
|
||||
if (csym->ValueType->IsA(RUNTIME_CLASS(PInt)))
|
||||
{
|
||||
|
@ -400,13 +400,13 @@ FxExpression *FxConstant::MakeConstant(PSymbol *sym, const FScriptPosition &pos)
|
|||
else
|
||||
{
|
||||
pos.Message(MSG_ERROR, "Invalid constant '%s'\n", csym->SymbolName.GetChars());
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pos.Message(MSG_ERROR, "'%s' is not a constant\n", sym->SymbolName.GetChars());
|
||||
x = NULL;
|
||||
x = nullptr;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
@ -794,7 +794,7 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
FxExpression *x = basex;
|
||||
x->ValueType = ValueType;
|
||||
basex = NULL;
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
|
@ -833,7 +833,7 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx)
|
|||
}
|
||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -891,7 +891,7 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx)
|
|||
if (basex->IsFloat())
|
||||
{
|
||||
FxExpression *x = basex;
|
||||
basex = NULL;
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
|
@ -923,7 +923,7 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -982,7 +982,7 @@ FxExpression *FxNameCast::Resolve(FCompileContext &ctx)
|
|||
if (basex->ValueType == TypeName)
|
||||
{
|
||||
FxExpression *x = basex;
|
||||
basex = NULL;
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
|
@ -1001,7 +1001,7 @@ FxExpression *FxNameCast::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot convert to name");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1060,7 +1060,7 @@ FxExpression *FxStringCast::Resolve(FCompileContext &ctx)
|
|||
if (basex->ValueType == TypeString)
|
||||
{
|
||||
FxExpression *x = basex;
|
||||
basex = NULL;
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
|
@ -1091,7 +1091,7 @@ FxExpression *FxStringCast::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot convert to string");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1158,7 +1158,7 @@ FxExpression *FxColorCast::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
FxExpression *x = basex;
|
||||
x->ValueType = TypeColor;
|
||||
basex = NULL;
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
|
@ -1177,7 +1177,7 @@ FxExpression *FxColorCast::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot convert to color");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1237,7 +1237,7 @@ FxExpression *FxSoundCast::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
FxExpression *x = basex;
|
||||
x->ValueType = TypeSound;
|
||||
basex = NULL;
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
|
@ -1256,7 +1256,7 @@ FxExpression *FxSoundCast::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot convert to sound");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1318,6 +1318,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
|
|||
// first deal with the simple types
|
||||
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;
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1502,7 +1503,7 @@ FxExpression *FxPlusSign::Resolve(FCompileContext& ctx)
|
|||
if (Operand->IsNumeric() || Operand->IsVector())
|
||||
{
|
||||
FxExpression *e = Operand;
|
||||
Operand = NULL;
|
||||
Operand = nullptr;
|
||||
delete this;
|
||||
return e;
|
||||
}
|
||||
|
@ -1510,7 +1511,7 @@ FxExpression *FxPlusSign::Resolve(FCompileContext& ctx)
|
|||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1571,7 +1572,7 @@ FxExpression *FxMinusSign::Resolve(FCompileContext& ctx)
|
|||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1587,7 +1588,14 @@ ExpEmit FxMinusSign::Emit(VMFunctionBuilder *build)
|
|||
ExpEmit from = Operand->Emit(build);
|
||||
assert(from.Konst == 0);
|
||||
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)
|
||||
{
|
||||
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.
|
||||
Operand = new FxIntCast(Operand, true);
|
||||
Operand = Operand->Resolve(ctx);
|
||||
if (Operand == NULL)
|
||||
if (Operand == nullptr)
|
||||
{
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1665,7 +1673,7 @@ FxExpression *FxUnaryNotBitwise::Resolve(FCompileContext& ctx)
|
|||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Integer type expected");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
else if (!Operand->RequestAddress(nullptr))
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Operand must be addressable to determine %s", Which == TK_AlignOf ? "alignment" : "size");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2513,7 +2521,8 @@ FxAddSub::FxAddSub(int o, FxExpression *l, FxExpression *r)
|
|||
FxExpression *FxAddSub::Resolve(FCompileContext& ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
if (!ResolveLR(ctx, true)) return NULL;
|
||||
if (!ResolveLR(ctx, true))
|
||||
return nullptr;
|
||||
|
||||
if (!IsNumeric() && !IsVector())
|
||||
{
|
||||
|
@ -2652,13 +2661,14 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx)
|
|||
{
|
||||
CHECKRESOLVED();
|
||||
|
||||
if (!ResolveLR(ctx, true)) return NULL;
|
||||
if (!ResolveLR(ctx, true))
|
||||
return nullptr;
|
||||
|
||||
if (!IsNumeric() && !IsVector())
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
else if (left->isConstant() && right->isConstant())
|
||||
{
|
||||
|
@ -2672,7 +2682,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx)
|
|||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Division by 0");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
v = Operator == '*'? v1 * v2 :
|
||||
|
@ -2693,7 +2703,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx)
|
|||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Division by 0");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
v = Operator == '*'? v1 * v2 :
|
||||
|
@ -2820,7 +2830,8 @@ FxExpression *FxPow::Resolve(FCompileContext& ctx)
|
|||
{
|
||||
CHECKRESOLVED();
|
||||
|
||||
if (!ResolveLR(ctx, true)) return nullptr;
|
||||
if (!ResolveLR(ctx, true))
|
||||
return nullptr;
|
||||
|
||||
if (!IsNumeric())
|
||||
{
|
||||
|
@ -2879,13 +2890,14 @@ FxCompareRel::FxCompareRel(int o, FxExpression *l, FxExpression *r)
|
|||
FxExpression *FxCompareRel::Resolve(FCompileContext& ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
if (!ResolveLR(ctx, true)) return NULL;
|
||||
if (!ResolveLR(ctx, true))
|
||||
return nullptr;
|
||||
|
||||
if (!IsNumeric())
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
else if (left->isConstant() && right->isConstant())
|
||||
{
|
||||
|
@ -3038,19 +3050,20 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx)
|
|||
{
|
||||
CHECKRESOLVED();
|
||||
|
||||
if (!ResolveLR(ctx, true)) return NULL;
|
||||
if (!ResolveLR(ctx, true))
|
||||
return nullptr;
|
||||
|
||||
if (!left || !right)
|
||||
{
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!IsNumeric() && !IsPointer() && !IsVector() && ValueType != TypeName)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
if (!ResolveLR(ctx, false)) return NULL;
|
||||
if (!ResolveLR(ctx, false))
|
||||
return nullptr;
|
||||
|
||||
if (IsFloat() && ctx.FromDecorate)
|
||||
{
|
||||
|
@ -3189,10 +3203,10 @@ FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx)
|
|||
right = new FxIntCast(right, ctx.FromDecorate);
|
||||
right = right->Resolve(ctx);
|
||||
}
|
||||
if (left == NULL || right == NULL)
|
||||
if (left == nullptr || right == nullptr)
|
||||
{
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
ValueType = TypeSInt32;
|
||||
}
|
||||
|
@ -3201,7 +3215,7 @@ FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx)
|
|||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Integer type expected");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
else if (left->isConstant() && right->isConstant())
|
||||
{
|
||||
|
@ -3322,7 +3336,8 @@ FxLtGtEq::FxLtGtEq(FxExpression *l, FxExpression *r)
|
|||
FxExpression *FxLtGtEq::Resolve(FCompileContext& ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
if (!ResolveLR(ctx, true)) return NULL;
|
||||
if (!ResolveLR(ctx, true))
|
||||
return nullptr;
|
||||
|
||||
if (!left->IsNumeric() || !right->IsNumeric())
|
||||
{
|
||||
|
@ -3467,14 +3482,14 @@ FxExpression *FxBinaryLogical::Resolve(FCompileContext& ctx)
|
|||
else if (b_left==1)
|
||||
{
|
||||
FxExpression *x = right;
|
||||
right=NULL;
|
||||
right=nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
else if (b_right==1)
|
||||
{
|
||||
FxExpression *x = left;
|
||||
left=NULL;
|
||||
left=nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
|
@ -3496,14 +3511,14 @@ FxExpression *FxBinaryLogical::Resolve(FCompileContext& ctx)
|
|||
else if (b_left==0)
|
||||
{
|
||||
FxExpression *x = right;
|
||||
right=NULL;
|
||||
right=nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
else if (b_right==0)
|
||||
{
|
||||
FxExpression *x = left;
|
||||
left=NULL;
|
||||
left=nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
|
@ -3723,7 +3738,7 @@ ExpEmit FxTypeCheck::Emit(VMFunctionBuilder *build)
|
|||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinTypeCheck, BuiltinTypeCheck);
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
auto callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
||||
|
@ -3813,7 +3828,7 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx)
|
|||
|
||||
FxExpression *e = result? truex:falsex;
|
||||
delete (result? falsex:truex);
|
||||
falsex = truex = NULL;
|
||||
falsex = truex = nullptr;
|
||||
delete this;
|
||||
return e;
|
||||
}
|
||||
|
@ -3867,9 +3882,22 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build)
|
|||
ExpEmit trueop = truex->Emit(build);
|
||||
if (trueop.Konst)
|
||||
{
|
||||
assert(trueop.RegType == REGT_FLOAT);
|
||||
out = ExpEmit(build, REGT_FLOAT);
|
||||
build->Emit(OP_LKF, out.RegNum, trueop.RegNum);
|
||||
if (trueop.RegType == REGT_FLOAT)
|
||||
{
|
||||
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
|
||||
{
|
||||
|
@ -3892,8 +3920,22 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build)
|
|||
ExpEmit falseop = falsex->Emit(build);
|
||||
if (falseop.Konst)
|
||||
{
|
||||
assert(falseop.RegType == REGT_FLOAT);
|
||||
build->Emit(OP_LKF, out.RegNum, falseop.RegNum);
|
||||
if (falseop.RegType == REGT_FLOAT)
|
||||
{
|
||||
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
|
||||
{
|
||||
|
@ -3901,17 +3943,7 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build)
|
|||
// returned by "true" so that only one register is returned by
|
||||
// this tree.
|
||||
falseop.Free(build);
|
||||
if (falseop.RegType == REGT_INT)
|
||||
{
|
||||
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->Emit(falsex->ValueType->GetMoveOp(), out.RegNum, falseop.RegNum, 0);
|
||||
}
|
||||
}
|
||||
build->BackpatchToHere(truejump);
|
||||
|
@ -3958,7 +3990,7 @@ FxExpression *FxAbs::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
else if (val->isConstant())
|
||||
{
|
||||
|
@ -3976,7 +4008,7 @@ FxExpression *FxAbs::Resolve(FCompileContext &ctx)
|
|||
default:
|
||||
// shouldn't happen
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
FxExpression *x = new FxConstant(value, ScriptPosition);
|
||||
delete this;
|
||||
|
@ -4047,7 +4079,7 @@ FxExpression *FxATan2::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
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");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
if (floatcount != 0)
|
||||
|
@ -4230,7 +4262,7 @@ FxExpression *FxMinMax::Resolve(FCompileContext &ctx)
|
|||
}
|
||||
}
|
||||
delete choices[j];
|
||||
choices[j] = NULL;
|
||||
choices[j] = nullptr;
|
||||
choices.Delete(j);
|
||||
}
|
||||
}
|
||||
|
@ -4329,12 +4361,12 @@ FxRandom::FxRandom(FRandom * r, FxExpression *mi, FxExpression *ma, const FScrip
|
|||
: FxExpression(EFX_Random, pos)
|
||||
{
|
||||
EmitTail = false;
|
||||
if (mi != NULL && ma != NULL)
|
||||
if (mi != nullptr && ma != nullptr)
|
||||
{
|
||||
min = new FxIntCast(mi, nowarn);
|
||||
max = new FxIntCast(ma, nowarn);
|
||||
}
|
||||
else min = max = NULL;
|
||||
else min = max = nullptr;
|
||||
rng = r;
|
||||
ValueType = TypeSInt32;
|
||||
}
|
||||
|
@ -4424,13 +4456,13 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build)
|
|||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom);
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
||||
|
||||
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, max, ScriptPosition);
|
||||
|
@ -4545,7 +4577,7 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
|
|||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom);
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
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)
|
||||
: 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);
|
||||
max = new FxFloatCast(ma);
|
||||
|
@ -4670,13 +4702,13 @@ ExpEmit FxFRandom::Emit(VMFunctionBuilder *build)
|
|||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinFRandom, BuiltinFRandom);
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
||||
|
||||
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, max, ScriptPosition);
|
||||
|
@ -4764,7 +4796,7 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build)
|
|||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom);
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
||||
|
@ -4896,7 +4928,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
|||
}
|
||||
|
||||
// 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)))
|
||||
{
|
||||
|
@ -4910,7 +4942,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
|||
}
|
||||
|
||||
// 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);
|
||||
newex = new FxConstant(num, ScriptPosition);
|
||||
|
@ -5355,25 +5387,25 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
|
|||
// DECORATE allows floats here so cast them to int.
|
||||
index = new FxIntCast(index, ctx.FromDecorate);
|
||||
index = index->Resolve(ctx);
|
||||
if (index == NULL)
|
||||
if (index == nullptr)
|
||||
{
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
if (index->ValueType->GetRegType() != REGT_INT && index->ValueType != TypeName)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Array index must be integer");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PArray *arraytype = dyn_cast<PArray>(Array->ValueType);
|
||||
if (arraytype == NULL)
|
||||
if (arraytype == nullptr)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "'[]' can only be used with arrays.");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
if (index->isConstant())
|
||||
{
|
||||
|
@ -5382,7 +5414,7 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Array index out of bounds");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5392,13 +5424,13 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
|
|||
// int arrays only for now
|
||||
ScriptPosition.Message(MSG_ERROR, "Only numeric arrays are supported.");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
if (!Array->RequestAddress(&AddressWritable))
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Unable to dereference array.");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -5901,12 +5933,12 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx)
|
|||
bool failed = false;
|
||||
|
||||
SAFE_RESOLVE_OPT(Self, ctx);
|
||||
if (ArgList != NULL)
|
||||
if (ArgList != nullptr)
|
||||
{
|
||||
for (unsigned i = 0; i < ArgList->Size(); i++)
|
||||
{
|
||||
(*ArgList)[i] = (*ArgList)[i]->Resolve(ctx);
|
||||
if ((*ArgList)[i] == NULL)
|
||||
if ((*ArgList)[i] == nullptr)
|
||||
{
|
||||
failed = true;
|
||||
}
|
||||
|
@ -5934,7 +5966,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx)
|
|||
if (failed)
|
||||
{
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
ValueType = TypeSInt32;
|
||||
|
@ -5959,7 +5991,7 @@ int BuiltinCallLineSpecial(VMFrameStack *stack, VMValue *param, TArray<VMValue>
|
|||
{
|
||||
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)
|
||||
|
@ -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.
|
||||
// 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
|
||||
if (ArgList != NULL)
|
||||
if (ArgList != nullptr)
|
||||
{
|
||||
for (; i < ArgList->Size(); ++i)
|
||||
{
|
||||
|
@ -6002,7 +6034,7 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
|
|||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinCallLineSpecial, BuiltinCallLineSpecial);
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
if (EmitTail)
|
||||
|
@ -6144,7 +6176,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
|
|||
if (failed)
|
||||
{
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
TArray<PType *> &rets = proto->ReturnTypes;
|
||||
if (rets.Size() > 0)
|
||||
|
@ -6207,7 +6239,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
|||
}
|
||||
}
|
||||
// Emit code to pass explicit parameters
|
||||
if (ArgList != NULL)
|
||||
if (ArgList != nullptr)
|
||||
{
|
||||
for (unsigned i = 0; i < ArgList->Size(); ++i)
|
||||
{
|
||||
|
@ -6311,25 +6343,25 @@ FxExpression *FxFlopFunctionCall::Resolve(FCompileContext& ctx)
|
|||
{
|
||||
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());
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
(*ArgList)[0] = (*ArgList)[0]->Resolve(ctx);
|
||||
if ((*ArgList)[0] == NULL)
|
||||
if ((*ArgList)[0] == nullptr)
|
||||
{
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!(*ArgList)[0]->IsNumeric())
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter");
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
if ((*ArgList)[0]->isConstant())
|
||||
{
|
||||
|
@ -6417,7 +6449,7 @@ FxExpression *FxSequence::Resolve(FCompileContext &ctx)
|
|||
CHECKRESOLVED();
|
||||
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;
|
||||
return nullptr;
|
||||
|
@ -6455,7 +6487,7 @@ VMFunction *FxSequence::GetDirectFunction()
|
|||
{
|
||||
return Expressions[0]->GetDirectFunction();
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -6792,7 +6824,7 @@ FxIfStatement::FxIfStatement(FxExpression *cond, FxExpression *true_part,
|
|||
WhenFalse = false_part;
|
||||
if (WhenTrue != nullptr) WhenTrue->NeedResult = false;
|
||||
if (WhenFalse != nullptr) WhenFalse->NeedResult = false;
|
||||
assert(cond != NULL);
|
||||
assert(cond != nullptr);
|
||||
}
|
||||
|
||||
FxIfStatement::~FxIfStatement()
|
||||
|
@ -6840,8 +6872,8 @@ FxExpression *FxIfStatement::Resolve(FCompileContext &ctx)
|
|||
|
||||
FxExpression *e = result ? WhenTrue : WhenFalse;
|
||||
delete (result ? WhenFalse : WhenTrue);
|
||||
WhenTrue = WhenFalse = NULL;
|
||||
if (e == NULL) e = new FxNop(ScriptPosition); // create a dummy if this statement gets completely removed by optimizing out the constant parts.
|
||||
WhenTrue = WhenFalse = nullptr;
|
||||
if (e == nullptr) e = new FxNop(ScriptPosition); // create a dummy if this statement gets completely removed by optimizing out the constant parts.
|
||||
delete this;
|
||||
return e;
|
||||
}
|
||||
|
@ -6861,7 +6893,7 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build)
|
|||
ExpEmit cond = Condition->Emit(build);
|
||||
assert(cond.RegType != REGT_STRING && !cond.Konst);
|
||||
|
||||
if (WhenTrue != NULL)
|
||||
if (WhenTrue != nullptr)
|
||||
{
|
||||
path1 = WhenTrue;
|
||||
path2 = WhenFalse;
|
||||
|
@ -6871,9 +6903,9 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
// When there is only a false path, reverse the condition so we can
|
||||
// treat it as a true path.
|
||||
assert(WhenFalse != NULL);
|
||||
assert(WhenFalse != nullptr);
|
||||
path1 = WhenFalse;
|
||||
path2 = NULL;
|
||||
path2 = nullptr;
|
||||
condcheck = 0;
|
||||
}
|
||||
|
||||
|
@ -6900,7 +6932,7 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build)
|
|||
// Evaluate first path
|
||||
v = path1->Emit(build);
|
||||
v.Free(build);
|
||||
if (path2 != NULL)
|
||||
if (path2 != nullptr)
|
||||
{
|
||||
size_t path1jump = build->Emit(OP_JMP, 0);
|
||||
// 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());
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (basex->isConstant())
|
||||
{
|
||||
FName clsname = static_cast<FxConstant *>(basex)->GetValue().GetName();
|
||||
PClass *cls = NULL;
|
||||
PClass *cls = nullptr;
|
||||
|
||||
if (clsname != NAME_None)
|
||||
{
|
||||
cls = PClass::FindClass(clsname);
|
||||
if (cls == NULL)
|
||||
if (cls == nullptr)
|
||||
{
|
||||
/* lax */
|
||||
// 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());
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
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))
|
||||
{
|
||||
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);
|
||||
return 1;
|
||||
|
@ -7484,7 +7516,7 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
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);
|
||||
assert(!clsname.Konst);
|
||||
|
@ -7497,7 +7529,7 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
|
|||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinNameToClass, BuiltinNameToClass);
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
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",
|
||||
ctx.Class->TypeName.GetChars(), index);
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
FxExpression *x = new FxConstant(aclass->OwnedStates + index, ScriptPosition);
|
||||
delete this;
|
||||
|
@ -7677,7 +7709,7 @@ FxMultiNameState::FxMultiNameState(const char *_statestring, const FScriptPositi
|
|||
}
|
||||
names = MakeStateNameList(statestring);
|
||||
names.Insert(0, scopename);
|
||||
scope = NULL;
|
||||
scope = nullptr;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -7693,7 +7725,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx)
|
|||
|
||||
if (names[0] == NAME_None)
|
||||
{
|
||||
scope = NULL;
|
||||
scope = nullptr;
|
||||
}
|
||||
else if (names[0] == NAME_Super)
|
||||
{
|
||||
|
@ -7702,27 +7734,27 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx)
|
|||
else
|
||||
{
|
||||
scope = PClass::FindActor(names[0]);
|
||||
if (scope == NULL)
|
||||
if (scope == nullptr)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Unknown class '%s' in state label", names[0].GetChars());
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
else if (!scope->IsAncestorOf(ctx.Class))
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(), ctx.Class->TypeName.GetChars());
|
||||
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 (names[1] != NAME_None)
|
||||
{
|
||||
destination = scope->FindState(names.Size()-1, &names[1], false);
|
||||
if (destination == NULL)
|
||||
if (destination == nullptr)
|
||||
{
|
||||
ScriptPosition.Message(MSG_OPTERROR, "Unknown state jump destination");
|
||||
/* lax */
|
||||
|
@ -7749,7 +7781,7 @@ static int DoFindState(VMFrameStack *stack, VMValue *param, int numparam, VMRetu
|
|||
{
|
||||
PARAM_OBJECT_AT(0, self, AActor);
|
||||
FState *state = self->GetClass()->FindState(numparam - 1, names);
|
||||
if (state == NULL)
|
||||
if (state == nullptr)
|
||||
{
|
||||
const char *dot = "";
|
||||
Printf("Jump target '");
|
||||
|
@ -7822,7 +7854,7 @@ ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build)
|
|||
}
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
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_Accuracy, TypeSInt32, VARF_Native, myoffsetof(AActor, accuracy)));
|
||||
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_ReactionTime, TypeSInt32, VARF_Native, myoffsetof(AActor, reactiontime)));
|
||||
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("Vel", TypeVector3, VARF_Native, myoffsetof(AActor, Vel)));
|
||||
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(NAME_Target, TypeActor, VARF_Native, myoffsetof(AActor, target)));
|
||||
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;
|
||||
}
|
||||
Error(type, "Unable to resolve %s as type.", FName(type->UserType->Id).GetChars());
|
||||
return TypeError;
|
||||
}
|
||||
|
||||
|
@ -2186,8 +2187,8 @@ static bool CheckRandom(ZCC_Expression *duration)
|
|||
FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af)
|
||||
{
|
||||
// We have 3 cases to consider here:
|
||||
// 1. An action 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.
|
||||
// 1. A function without parameters. This can be called directly
|
||||
// 2. A functon with parameters. This needs to be wrapped into a helper function to set everything up.
|
||||
// 3. An anonymous function.
|
||||
|
||||
// 1. and 2. are exposed through AST_ExprFunctionCall
|
||||
|
@ -2236,9 +2237,10 @@ void ZCCCompiler::CompileStates()
|
|||
{
|
||||
for (auto c : Classes)
|
||||
{
|
||||
|
||||
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;
|
||||
}
|
||||
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/actor.txt
|
||||
|
||||
|
|
|
@ -53,9 +53,13 @@ class Actor : Thinker native
|
|||
return GetPointer(ptr_select1) == GetPointer(ptr_select2);
|
||||
}
|
||||
|
||||
native static bool isDehState(state st);
|
||||
native void SetOrigin(vector3 newpos, bool moving);
|
||||
native void SetXYZ(vector3 newpos);
|
||||
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 OldSpawnMissile(Actor dest, class<Actor> type, Actor owner = null);
|
||||
native void TraceBleed(int damage, Actor missile);
|
||||
native bool CheckMeleeRange();
|
||||
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_BrainExplode();
|
||||
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 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_USEANGLE = 512,
|
||||
}
|
||||
|
||||
enum EReplace
|
||||
{
|
||||
NO_REPLACE = 0,
|
||||
ALLOW_REPLACE = 1
|
||||
}
|
||||
|
|
|
@ -110,6 +110,12 @@ extend class Actor
|
|||
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")
|
||||
{
|
||||
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