diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 3bce521c8..3f5b734c4 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -521,7 +521,7 @@ int PType::GetMoveOp() const int PType::GetRegType() const { - assert(0 && "No register for this type"); + //assert(0 && "No register for this type"); // wrong place for this assert, it makes it impossible to use this function to check for bad types. return REGT_NIL; } diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 2bf1fedc8..d4ee11383 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -96,7 +96,7 @@ FCompileContext::FCompileContext(PFunction *fnc, PPrototype *ret, bool fromdecor if (fnc != nullptr) Class = fnc->OwningClass; } -FCompileContext::FCompileContext(PClass *cls) : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(true) // only used by DECORATE constants. +FCompileContext::FCompileContext(PClass *cls, bool fromdecorate) : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate) { } @@ -3745,7 +3745,7 @@ FxExpression *FxRandom::Resolve(FCompileContext &ctx) // //========================================================================== -int DecoRandom(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) +int DecoRandom(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam >= 1 && numparam <= 3); FRandom *rng = reinterpret_cast(param[0].a); @@ -3995,7 +3995,7 @@ FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScri // //========================================================================== -int DecoFRandom(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) +int DecoFRandom(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam == 1 || numparam == 3); FRandom *rng = reinterpret_cast(param[0].a); @@ -5255,7 +5255,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx) // //========================================================================== -int DecoCallLineSpecial(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) +int DecoCallLineSpecial(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam > 2 && numparam < 8); assert(param[0].Type == REGT_INT); @@ -6702,7 +6702,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) // //========================================================================== -int DecoNameToClass(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) +int DecoNameToClass(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam == 2); assert(numret == 1); @@ -6842,7 +6842,7 @@ static bool VerifyJumpTarget(AActor *stateowner, FStateParamInfo *stateinfo, int return false; } -static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) +static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { PARAM_PROLOGUE; PARAM_OBJECT(stateowner, AActor); @@ -7008,7 +7008,7 @@ static int DoFindState(VMFrameStack *stack, VMValue *param, int numparam, VMRetu } // Find a state with any number of dots in its name. -int BuiltinFindMultiNameState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) +int BuiltinFindMultiNameState(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam > 1); assert(numret == 1); @@ -7024,7 +7024,7 @@ int BuiltinFindMultiNameState(VMFrameStack *stack, VMValue *param, int numparam, } // Find a state without any dots in its name. -int BuiltinFindSingleNameState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) +int BuiltinFindSingleNameState(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam == 2); assert(numret == 1); diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index f6468e61f..a55491a0b 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -77,7 +77,7 @@ struct FCompileContext TDeletingArray FunctionArgs; FCompileContext(PFunction *func, PPrototype *ret, bool fromdecorate); - FCompileContext(PClass *cls); // only to be used to resolve constants! + FCompileContext(PClass *cls, bool fromdecorate); // only to be used to resolve constants! PSymbol *FindInClass(FName identifier, PSymbolTable *&symt); PSymbol *FindInSelfClass(FName identifier, PSymbolTable *&symt); diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index 84e1200e9..c63677e0c 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -87,7 +87,7 @@ FxExpression *ParseExpression (FScanner &sc, PClassActor *cls, bool mustresolve) if (mustresolve) { - FCompileContext ctx(cls); + FCompileContext ctx(cls, true); data = data->Resolve(ctx); } diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 601fb5e9a..e04935f58 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -667,8 +667,8 @@ void InitThingdef() symt.AddSymbol(new PField(NAME_MomX, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.X))); symt.AddSymbol(new PField(NAME_MomY, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.Y))); symt.AddSymbol(new PField(NAME_MomZ, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.Z))); - symt.AddSymbol(new PField(NAME_ScaleX, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Scale.X))); - symt.AddSymbol(new PField(NAME_ScaleY, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Scale.Y))); + symt.AddSymbol(new PField(NAME_ScaleX, TypeFloat64, VARF_Native|VARF_Deprecated, myoffsetof(AActor, Scale.X))); + symt.AddSymbol(new PField(NAME_ScaleY, TypeFloat64, VARF_Native|VARF_Deprecated, myoffsetof(AActor, Scale.Y))); 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))); diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 747d53c3b..c6ff99d48 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -173,20 +173,6 @@ enum EVMAbortException X_BAD_SELF, }; -class VMFunction : public DObject -{ - DECLARE_ABSTRACT_CLASS(VMFunction, DObject); - HAS_OBJECT_POINTERS; -public: - bool Native; - BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action - FName Name; - - class PPrototype *Proto; - - VMFunction(FName name = NAME_None) : Native(false), ImplicitArgs(0), Name(name), Proto(NULL) {} -}; - enum EVMOpMode { MODE_ASHIFT = 0, @@ -642,6 +628,21 @@ do_double: if (inexact) } }; +class VMFunction : public DObject +{ + DECLARE_ABSTRACT_CLASS(VMFunction, DObject); + HAS_OBJECT_POINTERS; +public: + bool Native; + BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action + FName Name; + TArray Defaults; + + class PPrototype *Proto; + + VMFunction(FName name = NAME_None) : Native(false), ImplicitArgs(0), Name(name), Proto(NULL) {} +}; + // VM frame layout: // VMFrame header // parameter stack - 16 byte boundary, 16 bytes each @@ -829,7 +830,7 @@ class VMNativeFunction : public VMFunction { DECLARE_CLASS(VMNativeFunction, VMFunction); public: - typedef int (*NativeCallType)(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret); + typedef int (*NativeCallType)(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret); VMNativeFunction() : NativeCall(NULL) { Native = true; } VMNativeFunction(NativeCallType call) : NativeCall(call) { Native = true; } @@ -900,8 +901,8 @@ void VMDumpConstants(FILE *out, const VMScriptFunction *func); void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction *func); // Use this in the prototype for a native function. -#define VM_ARGS VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret -#define VM_ARGS_NAMES stack, param, numparam, ret, numret +#define VM_ARGS VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret +#define VM_ARGS_NAMES stack, param, defaultparam, numparam, ret, numret // Use these to collect the parameters in a native function. // variable name at position

@@ -924,6 +925,16 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction // PARAM_INT_OPT(0,myint) { myint = 55; } // Just make sure to fill it in when using these macros, because the compiler isn't likely // to give useful error messages if you don't. +#define PARAM_EXISTS ((p) < numparam && param[p].Type != REGT_NIL) +#define ASSERTINT(p) assert((p).Type == REGT_INT) +#define ASSERTFLOAT(p) assert((p).Type == REGT_FLOAT) +#define ASSERTSTRING(p) assert((p).Type == REGT_STRING) +#define ASSERTOBJECT(p) assert((p).Type == REGT_POINTER && (p).atag == ATAG_OBJECT) +#define ASSERTPOINTER(p) assert((p).Type == REGT_POINTER && (p).atag == ATAG_GENERIC) +#define ASSERTSTATE(p) assert((p).Type == REGT_POINTER && ((p).atag == ATAG_GENERIC || (p).atag == ATAG_STATE)) + +#define PARAM_INT_DEF_AT(p,x) int x; if (PARAM_EXISTS) { ASSERTINT(param[p]); x = param[p].i; } else { ASSERTINT(defaultparam[p]); x = defaultparam[p].i; } + #define PARAM_INT_OPT_AT(p,x) int x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_INT); x = param[p].i; } else #define PARAM_BOOL_OPT_AT(p,x) bool x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_INT); x = !!param[p].i; } else #define PARAM_NAME_OPT_AT(p,x) FName x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_INT); x = ENamedName(param[p].i); } else @@ -954,6 +965,20 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #define PARAM_OBJECT(x,type) ++paramnum; PARAM_OBJECT_AT(paramnum,x,type) #define PARAM_CLASS(x,base) ++paramnum; PARAM_CLASS_AT(paramnum,x,base) +#define PARAM_INT_DEF(x) ++paramnum; PARAM_INT_DEF_AT(paramnum,x) +#define PARAM_BOOL_DEF(x) ++paramnum; PARAM_BOOL_DEF_AT(paramnum,x) +#define PARAM_NAME_DEF(x) ++paramnum; PARAM_NAME_DEF_AT(paramnum,x) +#define PARAM_SOUND_DEF(x) ++paramnum; PARAM_SOUND_DEF_AT(paramnum,x) +#define PARAM_COLOR_DEF(x) ++paramnum; PARAM_COLOR_DEF_AT(paramnum,x) +#define PARAM_FLOAT_DEF(x) ++paramnum; PARAM_FLOAT_DEF_AT(paramnum,x) +#define PARAM_ANGLE_DEF(x) ++paramnum; PARAM_ANGLE_DEF_AT(paramnum,x) +#define PARAM_STRING_DEF(x) ++paramnum; PARAM_STRING_DEF_AT(paramnum,x) +#define PARAM_STATE_DEF(x) ++paramnum; PARAM_STATE_DEF_AT(paramnum,x) +#define PARAM_STATEINFO_DEF(x) ++paramnum; PARAM_STATEINFO_DEF_AT(paramnum,x) +#define PARAM_POINTER_DEF(x,type) ++paramnum; PARAM_POINTER_DEF_AT(paramnum,x,type) +#define PARAM_OBJECT_DEF(x,type) ++paramnum; PARAM_OBJECT_DEF_AT(paramnum,x,type) +#define PARAM_CLASS_DEF(x,base) ++paramnum; PARAM_CLASS_DEF_AT(paramnum,x,base) + #define PARAM_INT_OPT(x) ++paramnum; PARAM_INT_OPT_AT(paramnum,x) #define PARAM_BOOL_OPT(x) ++paramnum; PARAM_BOOL_OPT_AT(paramnum,x) #define PARAM_NAME_OPT(x) ++paramnum; PARAM_NAME_OPT_AT(paramnum,x) @@ -968,7 +993,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #define PARAM_OBJECT_OPT(x,type) ++paramnum; PARAM_OBJECT_OPT_AT(paramnum,x,type) #define PARAM_CLASS_OPT(x,base) ++paramnum; PARAM_CLASS_OPT_AT(paramnum,x,base) -typedef int(*actionf_p)(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/ +typedef int(*actionf_p)(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/ struct AFuncDesc { diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index fb428f781..b8078f071 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -188,13 +188,14 @@ void VMFillParams(VMValue *params, VMFrame *callee, int numparam) const VMRegisters calleereg(callee); assert(calleefunc != NULL && !calleefunc->Native); - assert(numparam == calleefunc->NumArgs); + assert(numparam == calleefunc->NumArgs || ((int)calleefunc->Defaults.Size() == numparam)); assert(REGT_INT == 0 && REGT_FLOAT == 1 && REGT_STRING == 2 && REGT_POINTER == 3); regd = regf = regs = rega = 0; - for (int i = 0; i < numparam; ++i) + for (int i = 0; i < calleefunc->NumArgs; ++i) { - VMValue &p = params[i]; + // get all actual parameters and fill the rest from the defaults. + VMValue &p = i < numparam? params[i] : calleefunc->Defaults[i]; if (p.Type < REGT_STRING) { if (p.Type == REGT_INT) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 65891493e..a5ad3ac00 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -506,7 +506,7 @@ begin: FillReturns(reg, f, returns, pc+1, C); if (call->Native) { - numret = static_cast(call)->NativeCall(stack, reg.param + f->NumParam - B, B, returns, C); + numret = static_cast(call)->NativeCall(stack, reg.param + f->NumParam - B, call->Defaults, B, returns, C); } else { @@ -550,7 +550,7 @@ begin: if (call->Native) { - return static_cast(call)->NativeCall(stack, reg.param + f->NumParam - B, B, ret, numret); + return static_cast(call)->NativeCall(stack, reg.param + f->NumParam - B, call->Defaults, B, ret, numret); } else { // FIXME: Not a true tail call diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index e5e58aa47..bf2159fa1 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -415,7 +415,7 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur { if (func->Native) { - return static_cast(func)->NativeCall(this, params, numparams, results, numresults); + return static_cast(func)->NativeCall(this, params, func->Defaults, numparams, results, numresults); } else { diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index f0f884f68..3a1e734a4 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1952,6 +1952,7 @@ void ZCCCompiler::InitFunctions() TArray rets(1); TArray args; TArray argflags; + TArray argdefaults; TArray argnames; for (auto c : Classes) @@ -1961,6 +1962,7 @@ void ZCCCompiler::InitFunctions() rets.Clear(); args.Clear(); argflags.Clear(); + bool hasdefault = false; // For the time being, let's not allow overloading. This may be reconsidered later but really just adds an unnecessary amount of complexity here. if (AddTreeNode(f->Name, f, &c->TreeNodes, false)) { @@ -2018,36 +2020,96 @@ void ZCCCompiler::InitFunctions() } } SetImplicitArgs(&args, &argflags, &argnames, c->Type(), varflags); + argdefaults.Resize(argnames.Size()); auto p = f->Params; if (p != nullptr) { do { + VMValue vmval; // default is REGT_NIL which means 'no default value' here. if (p->Type != nullptr) { auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false); int flags = 0; if (p->Flags & ZCC_In) flags |= VARF_In; if (p->Flags & ZCC_Out) flags |= VARF_Out; - if (p->Default != nullptr) + if ((type->IsA(RUNTIME_CLASS(PStruct))) || (flags & VARF_Out)) { - auto val = Simplify(p->Default, &c->Type()->Symbols, true); - flags |= VARF_Optional; - if (val->Operation != PEX_ConstValue) + // 'out' parameters and all structs except vectors are passed by reference + if ((flags & VARF_Out) || (type != TypeVector2 && type != TypeVector3)) { - Error(c->cls, "Default parameter %s is not constant in %s", FName(p->Name).GetChars(), FName(f->Name).GetChars()); + type = NewPointer(type); } - // Todo: Store and handle the default value (native functions will discard it anyway but for scripted ones this should be done decently.) + } + if (type->GetRegType() == REGT_NIL && type != TypeVector2 && type != TypeVector3) + { + Error(p, "Invalid type %s for function parameter", type->DescriptiveName()); + } + else if (p->Default != nullptr) + { + flags |= VARF_Optional; + // The simplifier is not suited to convert the constant into something usable. + // All it does is reduce the expression to a constant but we still got to do proper type checking and conversion. + // It will also lose important type info about enums, once these get implemented + // The code generator can do this properly for us. + FxExpression *x = new FxTypeCast(ConvertNode(p->Default), type, false); + FCompileContext ctx(c->Type(), false); + x = x->Resolve(ctx); + + if (x != nullptr) + { + if (!x->isConstant()) + { + Error(p, "Default parameter %s is not constant in %s", FName(p->Name).GetChars(), FName(f->Name).GetChars()); + } + else if (x->ValueType != type) + { + Error(p, "Default parameter %s could not be converted to target type %s", FName(p->Name).GetChars(), c->Type()->TypeName.GetChars()); + } + else + { + auto cnst = static_cast(x); + hasdefault = true; + switch (type->GetRegType()) + { + case REGT_INT: + vmval = cnst->GetValue().GetInt(); + break; + + case REGT_FLOAT: + vmval = cnst->GetValue().GetFloat(); + break; + + case REGT_POINTER: + if (type->IsKindOf(RUNTIME_CLASS(PClassPointer))) + vmval = (DObject*)cnst->GetValue().GetPointer(); + else + vmval = cnst->GetValue().GetPointer(); + break; + + case REGT_STRING: + vmval = cnst->GetValue().GetString(); + break; + + default: + assert(0 && "no valid type for constant"); + break; + } + } + } + if (x != nullptr) delete x; } // TBD: disallow certain types? For now, let everything pass that isn't an array. args.Push(type); argflags.Push(flags); + } else { args.Push(nullptr); argflags.Push(0); } + argdefaults.Push(vmval); p = static_cast(p->SiblingNext); } while (p != f->Params); } @@ -2064,9 +2126,11 @@ void ZCCCompiler::InitFunctions() sym->Variants[0].Implementation = FunctionBuildList.AddFunction(sym, code, FStringf("%s.%s", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars()), false); } } - + if (sym->Variants[0].Implementation != nullptr && hasdefault) // do not copy empty default lists, they only waste space and processing time. + { + sym->Variants[0].Implementation->Defaults = std::move(argdefaults); + } // todo: Check inheritance. - // todo: Process function bodies. } } } diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 02cb4f3cf..706acaee7 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -90,7 +90,7 @@ class Actor : Thinker native native void A_NoBlocking(); native void A_XScream(); native void A_Look(); - native void A_Chase(state melee = "*", state missile = "none", int flags = 0); + native void A_Chase(state melee = null, state missile = null, int flags = 0); native void A_FaceTarget(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); native void A_FaceTracer(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); native void A_FaceMaster(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); @@ -203,8 +203,8 @@ class Actor : Thinker native native void A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10); native state A_Jump(int chance = 256, state label, ...); native void A_CustomMissile(class missiletype, float spawnheight = 32, float spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0, int ptr = AAPTR_TARGET); - native void A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET, class missile = "", float Spawnheight = 32, float Spawnofs_xy = 0); - native void A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, int aim = 0, float maxdiff = 0, class pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0); + native void A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET, class missile = null, float Spawnheight = 32, float Spawnofs_xy = 0); + native void A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = 0, color color2 = 0, int flags = 0, int aim = 0, float maxdiff = 0, class pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0); native state A_JumpIfHealthLower(int health, state label, int ptr_selector = AAPTR_DEFAULT); native state A_JumpIfCloser(float distance, state label, bool noz = false); native state A_JumpIfTracerCloser(float distance, state label, bool noz = false); @@ -217,8 +217,8 @@ class Actor : Thinker native native bool A_TakeInventory(class itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT); action native bool A_SpawnItem(class itemtype = "Unknown", float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false); native bool A_SpawnItemEx(class itemtype, float xofs = 0, float yofs = 0, float zofs = 0, float xvel = 0, float yvel = 0, float zvel = 0, float angle = 0, int flags = 0, int failchance = 0, int tid=0); - native void A_Print(string whattoprint, float time = 0, name fontname = ""); - native void A_PrintBold(string whattoprint, float time = 0, name fontname = ""); + native void A_Print(string whattoprint, float time = 0, name fontname = "none"); + native void A_PrintBold(string whattoprint, float time = 0, name fontname = "none"); native void A_Log(string whattoprint); native void A_LogInt(int whattoprint); native void A_LogFloat(float whattoprint); @@ -234,7 +234,7 @@ class Actor : Thinker native native state A_CheckSight(state label); native void A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false); native void A_DropInventory(class itemtype); - native void A_SetBlend(color color1, float alpha, int tics, color color2 = ""); + native void A_SetBlend(color color1, float alpha, int tics, color color2 = 0); deprecated native void A_ChangeFlag(string flagname, bool value); deprecated native state A_CheckFlag(string flagname, state label, int check_pointer = AAPTR_DEFAULT); native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE); @@ -247,8 +247,8 @@ class Actor : Thinker native native state A_CheckCeiling(state label); native state A_PlayerSkinCheck(state label); deprecated native void A_BasicAttack(int meleedamage, sound meleesound, class missiletype, float missileheight); - native state, bool A_Teleport(state teleportstate = "", class targettype = "BossSpot", class fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0, int ptr = AAPTR_DEFAULT); - native state, bool A_Warp(int ptr_destination, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0, int flags = 0, state success_state = "", float heightoffset = 0, float radiusoffset = 0, float pitch = 0); + native state, bool A_Teleport(state teleportstate = null, class targettype = "BossSpot", class fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0, int ptr = AAPTR_DEFAULT); + native state, bool A_Warp(int ptr_destination, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0, int flags = 0, state success_state = null, float heightoffset = 0, float radiusoffset = 0, float pitch = 0); action native bool A_ThrowGrenade(class itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true); native void A_Weave(int xspeed, int yspeed, float xdist, float ydist); @@ -257,8 +257,8 @@ class Actor : Thinker native native bool A_GiveToTarget(class itemtype, int amount = 0, int forward_ptr = AAPTR_DEFAULT); native bool A_TakeFromTarget(class itemtype, int amount = 0, int flags = 0, int forward_ptr = AAPTR_DEFAULT); native int A_RadiusGive(class itemtype, float distance, int flags, int amount = 0, class filter = "None", name species = "None", float mindist = 0, int limit = 0); - native state A_CheckSpecies(state jump, name species = "", int ptr = AAPTR_DEFAULT); - native void A_CountdownArg(int argnum, state targstate = ""); + native state A_CheckSpecies(state jump, name species = 'none', int ptr = AAPTR_DEFAULT); + native void A_CountdownArg(int argnum, state targstate = null); native void A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true); native void A_CustomComboAttack(class missiletype, float spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true); native void A_Burst(class chunktype); @@ -271,7 +271,7 @@ class Actor : Thinker native native void A_BarrelDestroy(); native void A_QueueCorpse(); native void A_DeQueueCorpse(); - native void A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = ""); + native void A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = null); native void A_ClearLastHeard(); native void A_ClearTarget(); native state A_CheckLOF(state jump, int flags = 0, float range = 0, float minrange = 0, float angle = 0, float pitch = 0, float offsetheight = 0, float offsetwidth = 0, int ptr_target = AAPTR_DEFAULT, float offsetforward = 0); @@ -357,7 +357,7 @@ class Actor : Thinker native native void A_TransferPointer(int ptr_source, int ptr_recepient, int sourcefield, int recepientfield=AAPTR_DEFAULT, int flags=0); native void A_CopyFriendliness(int ptr_source = AAPTR_MASTER); - action native bool A_Overlay(int layer, state start = "", bool nooverride = false); + action native bool A_Overlay(int layer, state start = null, bool nooverride = false); native void A_WeaponOffset(float wx = 0, float wy = 32, int flags = 0); action native void A_OverlayOffset(int layer = PSP_WEAPON, float wx = 0, float wy = 32, int flags = 0); action native void A_OverlayFlags(int layer, int flags, bool set); diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 2fde3b3cd..4a9cde740 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -42,10 +42,10 @@ class Inventory : Actor native class StateProvider : Inventory native { action native state A_JumpIfNoAmmo(state label); - action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus", sound MeleeSound = "", sound MissSound = ""); - action native void A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, float range = 0, class missile = "", float Spawnheight = 32, float Spawnofs_xy = 0); + action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus", sound MeleeSound = 0, sound MissSound = ""); + action native void A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, float range = 0, class missile = null, float Spawnheight = 32, float Spawnofs_xy = 0); action native void A_FireCustomMissile(class missiletype, float angle = 0, bool useammo = true, float spawnofs_xy = 0, float spawnheight = 0, int flags = 0, float pitch = 0); - action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = "", color color2 = "", int flags = 0, float maxdiff = 0, class pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0); + action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = 0, color color2 = 0, int flags = 0, float maxdiff = 0, class pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0); native void A_Light(int extralight); native void A_Light0(); native void A_Light1(); @@ -71,10 +71,10 @@ class StateProvider : Inventory native native void A_BFGsound(); action native void A_FireBFG(); action native void A_FireOldBFG(); - native void A_ReFire(state flash = ""); + native void A_ReFire(state flash = null); native void A_ClearReFire(); native void A_CheckReload(); - native void A_GunFlash(state flash = "", int flags = 0); + native void A_GunFlash(state flash = null, int flags = 0); action native void A_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class pufftype = "BulletPuff", int flags = 0, float range = 0, float spread_xy = 2.8125, float spread_z = 0, float lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus"); native state A_CheckForReload(int counter, state label, bool dontincrement = false); native void A_ResetReloadCounter();