mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 14:51:51 +00:00
Merge branch 'master' into portal
This commit is contained in:
commit
15040c955e
28 changed files with 944 additions and 603 deletions
|
@ -188,6 +188,16 @@ option(FORCE_INTERNAL_JPEG "Use internal jpeg")
|
|||
option(FORCE_INTERNAL_BZIP2 "Use internal bzip2")
|
||||
option(FORCE_INTERNAL_GME "Use internal gme" ON)
|
||||
|
||||
# Fast math flags, required by some subprojects
|
||||
set( ZD_FASTMATH_FLAG "" )
|
||||
if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
|
||||
set( ZD_FASTMATH_FLAG "-ffast-math" )
|
||||
else()
|
||||
if( MSVC )
|
||||
set( ZD_FASTMATH_FLAG "/fp:fast" )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if( ZLIB_FOUND AND NOT FORCE_INTERNAL_ZLIB )
|
||||
message( STATUS "Using system zlib" )
|
||||
else()
|
||||
|
|
|
@ -14,9 +14,8 @@ if( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE )
|
|||
endif(NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "4.5")
|
||||
endif()
|
||||
|
||||
if( MSVC )
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fp:fast" )
|
||||
endif()
|
||||
# Enable fast flag for dumb
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ZD_FASTMATH_FLAG}" )
|
||||
|
||||
CHECK_FUNCTION_EXISTS( itoa ITOA_EXISTS )
|
||||
if( NOT ITOA_EXISTS )
|
||||
|
|
|
@ -29,11 +29,8 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if( MSVC )
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fp:fast" )
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:fast" )
|
||||
endif()
|
||||
|
||||
# Enable fast flag for GME
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ZD_FASTMATH_FLAG}" )
|
||||
|
||||
# Default emulators to build (all of them! ;)
|
||||
if (NOT DEFINED USE_GME_AY)
|
||||
|
|
|
@ -5,13 +5,16 @@ set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG" )
|
|||
# Disable warnings for << operator precedence (4554) and
|
||||
# unreferenced labels (4102) from VC
|
||||
if( MSVC )
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4554 /wd4102 /fp:fast" )
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4554 /wd4102" )
|
||||
endif()
|
||||
|
||||
if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra" )
|
||||
endif()
|
||||
|
||||
# Enable fast flag for gdtoa
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ZD_FASTMATH_FLAG}" )
|
||||
|
||||
include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
|
||||
add_definitions( -DINFNAN_CHECK -DMULTIPLE_THREADS )
|
||||
|
||||
|
|
|
@ -35,14 +35,6 @@ if( CMAKE_SIZEOF_VOID_P MATCHES "8" )
|
|||
set( X64 64 )
|
||||
endif()
|
||||
|
||||
if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
|
||||
set ( FASTMATH "-ffast-math" )
|
||||
else()
|
||||
if ( MSVC )
|
||||
set ( FASTMATH "/fp:fast" )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# You can either use "make install" on the FMOD distribution to put it
|
||||
# in standard system locations, or you can unpack the FMOD distribution
|
||||
# in the root of the zdoom tree. e.g.:
|
||||
|
@ -866,6 +858,7 @@ set( NOT_COMPILED_SOURCE_FILES
|
|||
asm_x86_64/tmap3.s
|
||||
)
|
||||
|
||||
# Enable fast math for some sources
|
||||
set( FASTMATH_SOURCES
|
||||
r_swrenderer.cpp
|
||||
r_3dfloors.cpp
|
||||
|
@ -1203,12 +1196,12 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
|
|||
zzautozend.cpp
|
||||
)
|
||||
|
||||
set_source_files_properties( ${FASTMATH_SOURCES} PROPERTIES COMPILE_FLAGS ${FASTMATH} )
|
||||
set_source_files_properties( ${FASTMATH_SOURCES} PROPERTIES COMPILE_FLAGS ${ZD_FASTMATH_FLAG} )
|
||||
set_source_files_properties( xlat/parse_xlat.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c" )
|
||||
set_source_files_properties( sc_man.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h" )
|
||||
set_source_files_properties( ${NOT_COMPILED_SOURCE_FILES} PROPERTIES HEADER_FILE_ONLY TRUE )
|
||||
if ( WIN32 )
|
||||
set_source_files_properties( win32/fb_d3d9.cpp win32/fb_d3d9_wipe.cpp PROPERTIES COMPILE_FLAGS ${FASTMATH} )
|
||||
set_source_files_properties( win32/fb_d3d9.cpp win32/fb_d3d9_wipe.cpp PROPERTIES COMPILE_FLAGS ${ZD_FASTMATH_FLAG} )
|
||||
endif()
|
||||
|
||||
|
||||
|
|
|
@ -207,7 +207,6 @@ enum EObjectFlags
|
|||
OF_JustSpawned = 1 << 8, // Thinker was spawned this tic
|
||||
OF_SerialSuccess = 1 << 9, // For debugging Serialize() calls
|
||||
OF_Sentinel = 1 << 10, // Object is serving as the sentinel in a ring list
|
||||
OF_StateChanged = 1 << 11, // Used by A_Jump* functions to feed back to SetState()
|
||||
};
|
||||
|
||||
template<class T> class TObjPtr;
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
#include "po_man.h"
|
||||
#include "autosegs.h"
|
||||
#include "v_video.h"
|
||||
#include "textures.h"
|
||||
#include "textures/textures.h"
|
||||
#include "r_utility.h"
|
||||
#include "menu/menu.h"
|
||||
#include "intermission/intermission.h"
|
||||
|
|
|
@ -1222,6 +1222,38 @@ PStatePointer::PStatePointer()
|
|||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PStatePointer :: GetStoreOp
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int PStatePointer::GetStoreOp() const
|
||||
{
|
||||
return OP_SP;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PStatePointer :: GetLoadOp
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int PStatePointer::GetLoadOp() const
|
||||
{
|
||||
return OP_LP;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PStatePointer :: GetRegType
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int PStatePointer::GetRegType() const
|
||||
{
|
||||
return REGT_POINTER;
|
||||
}
|
||||
|
||||
/* PPointer ***************************************************************/
|
||||
|
||||
|
@ -1948,7 +1980,7 @@ size_t PFunction::PropagateMark()
|
|||
{
|
||||
for (unsigned i = 0; i < Variants.Size(); ++i)
|
||||
{
|
||||
GC::Mark(Variants[i].Proto);
|
||||
//GC::Mark(Variants[i].Proto);
|
||||
GC::Mark(Variants[i].Implementation);
|
||||
}
|
||||
return Variants.Size() * sizeof(Variants[0]) + Super::PropagateMark();
|
||||
|
@ -1967,9 +1999,10 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray<DWORD> &argflags, VMFun
|
|||
{
|
||||
Variant variant;
|
||||
|
||||
variant.Proto = proto;
|
||||
//variant.Proto = proto;
|
||||
variant.ArgFlags = argflags;
|
||||
variant.Implementation = impl;
|
||||
impl->Proto = proto;
|
||||
return Variants.Push(variant);
|
||||
}
|
||||
|
||||
|
|
|
@ -415,6 +415,10 @@ class PStatePointer : public PBasicType
|
|||
DECLARE_CLASS(PStatePointer, PBasicType);
|
||||
public:
|
||||
PStatePointer();
|
||||
|
||||
virtual int GetStoreOp() const;
|
||||
virtual int GetLoadOp() const;
|
||||
virtual int GetRegType() const;
|
||||
};
|
||||
|
||||
class PPointer : public PBasicType
|
||||
|
@ -582,7 +586,7 @@ class PFunction : public PSymbol
|
|||
public:
|
||||
struct Variant
|
||||
{
|
||||
PPrototype *Proto;
|
||||
//PPrototype *Proto;
|
||||
VMFunction *Implementation;
|
||||
TArray<DWORD> ArgFlags; // Should be the same length as Proto->ArgumentTypes
|
||||
};
|
||||
|
|
27
src/info.cpp
27
src/info.cpp
|
@ -52,7 +52,7 @@
|
|||
#include "cmdlib.h"
|
||||
#include "g_level.h"
|
||||
#include "stats.h"
|
||||
#include "thingdef.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
#include "d_player.h"
|
||||
|
||||
extern void LoadActors ();
|
||||
|
@ -69,14 +69,37 @@ void FState::SetAction(const char *name)
|
|||
ActionFunc = FindGlobalActionFunction(name)->Variants[0].Implementation;
|
||||
}
|
||||
|
||||
bool FState::CallAction(AActor *self, AActor *stateowner)
|
||||
bool FState::CallAction(AActor *self, AActor *stateowner, FState **stateret)
|
||||
{
|
||||
if (ActionFunc != NULL)
|
||||
{
|
||||
ActionCycles.Clock();
|
||||
|
||||
static VMFrameStack stack;
|
||||
VMValue params[3] = { self, stateowner, VMValue(this, ATAG_STATE) };
|
||||
// If the function returns a state, store it at *stateret.
|
||||
// If it doesn't return a state but stateret is non-NULL, we need
|
||||
// to set *stateret to NULL.
|
||||
if (stateret != NULL)
|
||||
{
|
||||
*stateret = NULL;
|
||||
if (ActionFunc->Proto == NULL ||
|
||||
ActionFunc->Proto->ReturnTypes.Size() == 0 ||
|
||||
ActionFunc->Proto->ReturnTypes[0] != TypeState)
|
||||
{
|
||||
stateret = NULL;
|
||||
}
|
||||
}
|
||||
if (stateret == NULL)
|
||||
{
|
||||
stack.Call(ActionFunc, params, countof(params), NULL, 0, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
VMReturn ret;
|
||||
ret.PointerAt((void **)stateret);
|
||||
stack.Call(ActionFunc, params, countof(params), &ret, 1, NULL);
|
||||
}
|
||||
ActionCycles.Unclock();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ struct FState
|
|||
void SetAction(VMFunction *func) { ActionFunc = func; }
|
||||
void ClearAction() { ActionFunc = NULL; }
|
||||
void SetAction(const char *name);
|
||||
bool CallAction(AActor *self, AActor *stateowner);
|
||||
bool CallAction(AActor *self, AActor *stateowner, FState **stateret);
|
||||
static PClassActor *StaticFindStateOwner (const FState *state);
|
||||
static PClassActor *StaticFindStateOwner (const FState *state, PClassActor *info);
|
||||
static FRandom pr_statetics;
|
||||
|
|
|
@ -614,23 +614,24 @@ bool AActor::SetState (FState *newstate, bool nofunction)
|
|||
}
|
||||
}
|
||||
|
||||
if (!nofunction && newstate->CallAction(this, this))
|
||||
if (!nofunction)
|
||||
{
|
||||
FState *returned_state;
|
||||
if (newstate->CallAction(this, this, &returned_state))
|
||||
{
|
||||
// Check whether the called action function resulted in destroying the actor
|
||||
if (ObjectFlags & OF_EuthanizeMe)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (ObjectFlags & OF_StateChanged)
|
||||
if (returned_state != NULL)
|
||||
{ // The action was an A_Jump-style function that wants to change the next state.
|
||||
ObjectFlags &= ~OF_StateChanged;
|
||||
FState *saved = newstate;
|
||||
newstate = state;
|
||||
state = saved; // we need this for comparison of sprites.
|
||||
newstate = returned_state;
|
||||
tics = 0; // make sure we loop and set the new state properly
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
newstate = newstate->GetNextState();
|
||||
} while (tics == 0);
|
||||
|
||||
|
@ -3905,16 +3906,16 @@ bool AActor::CheckNoDelay()
|
|||
{
|
||||
// For immediately spawned objects with the NoDelay flag set for their
|
||||
// Spawn state, explicitly call the current state's function.
|
||||
if (state->CallAction(this, this))
|
||||
FState *newstate;
|
||||
if (state->CallAction(this, this, &newstate))
|
||||
{
|
||||
if (ObjectFlags & OF_EuthanizeMe)
|
||||
{
|
||||
return false; // freed itself
|
||||
}
|
||||
if (ObjectFlags & OF_StateChanged)
|
||||
if (newstate != NULL)
|
||||
{
|
||||
ObjectFlags &= ~OF_StateChanged;
|
||||
return SetState(state);
|
||||
return SetState(newstate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -178,9 +178,16 @@ void P_SetPsprite (player_t *player, int position, FState *state, bool nofunctio
|
|||
|
||||
if (!nofunction && player->mo != NULL)
|
||||
{
|
||||
if (state->CallAction(player->mo, player->ReadyWeapon))
|
||||
FState *newstate;
|
||||
if (state->CallAction(player->mo, player->ReadyWeapon, &newstate))
|
||||
{
|
||||
if (!psp->state)
|
||||
if (newstate != NULL)
|
||||
{
|
||||
state = newstate;
|
||||
psp->tics = 0;
|
||||
continue;
|
||||
}
|
||||
if (psp->state == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -281,7 +281,7 @@ static void FinishThingdef()
|
|||
if (func == NULL)
|
||||
{
|
||||
FCompileContext ctx(tcall->ActorClass);
|
||||
tcall->Code = static_cast<FxTailable *>(tcall->Code->Resolve(ctx));
|
||||
tcall->Code = tcall->Code->Resolve(ctx);
|
||||
|
||||
// Make sure resolving it didn't obliterate it.
|
||||
if (tcall->Code != NULL)
|
||||
|
@ -292,11 +292,25 @@ static void FinishThingdef()
|
|||
// self, stateowner, state (all are pointers)
|
||||
buildit.Registers[REGT_POINTER].Get(3);
|
||||
|
||||
// Emit a tail call via FxVMFunctionCall
|
||||
tcall->Code->Emit(&buildit, true);
|
||||
// Emit code
|
||||
tcall->Code->Emit(&buildit);
|
||||
|
||||
VMScriptFunction *sfunc = buildit.MakeFunction();
|
||||
sfunc->NumArgs = NAP;
|
||||
|
||||
// Generate prototype for this anonymous function
|
||||
TArray<PType *> args(3);
|
||||
SetImplicitArgs(&args, NULL, tcall->ActorClass, VARF_Method | VARF_Action);
|
||||
if (tcall->Proto != NULL)
|
||||
{
|
||||
sfunc->Proto = NewPrototype(tcall->Proto->ReturnTypes, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
TArray<PType *> norets(0);
|
||||
sfunc->Proto = NewPrototype(norets, args);
|
||||
}
|
||||
|
||||
func = sfunc;
|
||||
|
||||
if (dump != NULL)
|
||||
|
@ -354,6 +368,7 @@ static void FinishThingdef()
|
|||
dmg->Emit(&buildit);
|
||||
sfunc = buildit.MakeFunction();
|
||||
sfunc->NumArgs = 1;
|
||||
sfunc->Proto = NULL; ///FIXME: Need a proper prototype here
|
||||
// Save this function in case this damage value was reused
|
||||
// (which happens quite easily with inheritance).
|
||||
dmg->SetFunction(sfunc);
|
||||
|
|
|
@ -122,7 +122,8 @@ struct FStateTempCall
|
|||
FStateTempCall() : ActorClass(NULL), Code(NULL), FirstState(0), NumStates(0) {}
|
||||
|
||||
PClassActor *ActorClass;
|
||||
class FxTailable *Code;
|
||||
class FxExpression *Code;
|
||||
class PPrototype *Proto;
|
||||
int FirstState;
|
||||
int NumStates;
|
||||
};
|
||||
|
@ -189,8 +190,10 @@ AFuncDesc *FindFunction(const char * string);
|
|||
void ParseStates(FScanner &sc, PClassActor *actor, AActor *defaults, Baggage &bag);
|
||||
void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray<FxExpression *> &out_params,
|
||||
PFunction *afd, FString statestring, FStateDefinitions *statedef);
|
||||
FxTailable *ParseActions(FScanner &sc, FState state, FString statestring, Baggage &bag);
|
||||
FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Baggage &bag, PPrototype *&proto, bool &endswithret);
|
||||
class FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, Baggage &bag);
|
||||
void AddImplicitReturn(class FxSequence *code, const PPrototype *proto, FScanner &sc);
|
||||
void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, PClassActor *cls, DWORD funcflags);
|
||||
|
||||
PFunction *FindGlobalActionFunction(const char *name);
|
||||
|
||||
|
@ -354,8 +357,9 @@ int MatchString (const char *in, const char **strings);
|
|||
}
|
||||
|
||||
|
||||
#define ACTION_SET_RESULT(v) do { if (numret > 0) { assert(ret != NULL); ret->SetInt(v); numret = 1; } } while(0)
|
||||
#define ACTION_OR_RESULT(v) do { if (numret > 0) { assert(ret != NULL); ret->SetInt(*(int *)ret->Location | int(v)); numret = 1; } } while(0)
|
||||
#define ACTION_RETURN_STATE(state) if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_STATE); return 1; } return 0
|
||||
#define ACTION_RETURN_INT(v) if (numret > 0) { assert(ret != NULL); ret->SetInt(v); return 1; } return 0
|
||||
#define ACTION_RETURN_BOOL(v) ACTION_RETURN_INT(v)
|
||||
|
||||
// Checks to see what called the current action function
|
||||
#define ACTION_CALL_FROM_ACTOR() (callingstate == self->state)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -204,6 +204,7 @@ public:
|
|||
|
||||
virtual bool isConstant() const;
|
||||
virtual void RequestAddress();
|
||||
virtual VMFunction *GetDirectFunction();
|
||||
|
||||
virtual ExpEmit Emit(VMFunctionBuilder *build);
|
||||
|
||||
|
@ -389,6 +390,17 @@ public:
|
|||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
class FxCastStateToBool : public FxExpression
|
||||
{
|
||||
FxExpression *basex;
|
||||
|
||||
public:
|
||||
FxCastStateToBool(FxExpression *x);
|
||||
~FxCastStateToBool();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -817,43 +829,26 @@ public:
|
|||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxTailable
|
||||
//
|
||||
// An expression that can produce a tail call
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxTailable : public FxExpression
|
||||
{
|
||||
public:
|
||||
FxTailable(const FScriptPosition &pos) : FxExpression(pos) {}
|
||||
virtual ExpEmit Emit(VMFunctionBuilder *build, bool tailcall) = 0;
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
virtual VMFunction *GetDirectFunction();
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxVMFunctionCall
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxVMFunctionCall : public FxTailable
|
||||
class FxVMFunctionCall : public FxExpression
|
||||
{
|
||||
PFunction *Function;
|
||||
FArgumentList *ArgList;
|
||||
PType *ReturnType;
|
||||
|
||||
public:
|
||||
FxVMFunctionCall(PFunction *func, FArgumentList *args, const FScriptPosition &pos);
|
||||
~FxVMFunctionCall();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
ExpEmit Emit(VMFunctionBuilder *build, bool tailcall);
|
||||
unsigned GetArgCount() { return ArgList == NULL ? 0 : ArgList->Size(); }
|
||||
VMFunction *GetVMFunction() { return Function->Variants[0].Implementation; }
|
||||
VMFunction *GetDirectFunction();
|
||||
unsigned GetArgCount() const { return ArgList == NULL ? 0 : ArgList->Size(); }
|
||||
VMFunction *GetVMFunction() const { return Function->Variants[0].Implementation; }
|
||||
bool IsDirectFunction();
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -862,15 +857,15 @@ public:
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxSequence : public FxTailable
|
||||
class FxSequence : public FxExpression
|
||||
{
|
||||
TDeletingArray<FxTailable *> Expressions;
|
||||
TDeletingArray<FxExpression *> Expressions;
|
||||
|
||||
public:
|
||||
FxSequence(const FScriptPosition &pos) : FxTailable(pos) {}
|
||||
FxSequence(const FScriptPosition &pos) : FxExpression(pos) {}
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpEmit Emit(VMFunctionBuilder *build, bool tailcall);
|
||||
void Add(FxTailable *expr) { if (expr != NULL) Expressions.Push(expr); }
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
void Add(FxExpression *expr) { if (expr != NULL) Expressions.Push(expr); }
|
||||
VMFunction *GetDirectFunction();
|
||||
};
|
||||
|
||||
|
@ -880,17 +875,17 @@ public:
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxIfStatement : public FxTailable
|
||||
class FxIfStatement : public FxExpression
|
||||
{
|
||||
FxExpression *Condition;
|
||||
FxTailable *WhenTrue;
|
||||
FxTailable *WhenFalse;
|
||||
FxExpression *WhenTrue;
|
||||
FxExpression *WhenFalse;
|
||||
|
||||
public:
|
||||
FxIfStatement(FxExpression *cond, FxTailable *true_part, FxTailable *false_part, const FScriptPosition &pos);
|
||||
FxIfStatement(FxExpression *cond, FxExpression *true_part, FxExpression *false_part, const FScriptPosition &pos);
|
||||
~FxIfStatement();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpEmit Emit(VMFunctionBuilder *build, bool tailcall);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -899,11 +894,15 @@ public:
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxReturnStatement : public FxTailable
|
||||
class FxReturnStatement : public FxExpression
|
||||
{
|
||||
FxVMFunctionCall *Call;
|
||||
|
||||
public:
|
||||
FxReturnStatement(const FScriptPosition &pos);
|
||||
ExpEmit Emit(VMFunctionBuilder *build, bool tailcall);
|
||||
FxReturnStatement(FxVMFunctionCall *call, const FScriptPosition &pos);
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
VMFunction *GetDirectFunction();
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -129,6 +129,17 @@ bool FxExpression::isConstant() const
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
VMFunction *FxExpression::GetDirectFunction()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxExpression *FxExpression::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
isresolved = true;
|
||||
|
@ -157,6 +168,11 @@ FxExpression *FxExpression::ResolveAsBoolean(FCompileContext &ctx)
|
|||
x->ValueType = VAL_Int;
|
||||
break;
|
||||
|
||||
case VAL_State:
|
||||
x = new FxCastStateToBool(x);
|
||||
x = x->Resolve(ctx);
|
||||
break;
|
||||
|
||||
default:
|
||||
ScriptPosition.Message(MSG_ERROR, "Not an integral type");
|
||||
delete this;
|
||||
|
@ -500,6 +516,67 @@ ExpEmit FxFloatCast::Emit(VMFunctionBuilder *build)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FxCastStateToBool::FxCastStateToBool(FxExpression *x)
|
||||
: FxExpression(x->ScriptPosition)
|
||||
{
|
||||
basex = x;
|
||||
ValueType = VAL_Int;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxCastStateToBool::~FxCastStateToBool()
|
||||
{
|
||||
SAFE_DELETE(basex);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxExpression *FxCastStateToBool::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(basex, ctx);
|
||||
|
||||
assert(basex->ValueType == VAL_State);
|
||||
assert(!basex->isConstant() && "We shouldn't be able to generate a constant state ref");
|
||||
return this;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpEmit FxCastStateToBool::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
ExpEmit from = basex->Emit(build);
|
||||
assert(from.RegType == REGT_POINTER);
|
||||
from.Free(build);
|
||||
ExpEmit to(build, REGT_INT);
|
||||
|
||||
// If from is NULL, produce 0. Otherwise, produce 1.
|
||||
build->Emit(OP_LI, to.RegNum, 0);
|
||||
build->Emit(OP_EQA_K, 1, from.RegNum, build->GetConstantAddress(NULL, ATAG_GENERIC));
|
||||
build->Emit(OP_JMP, 1);
|
||||
build->Emit(OP_LI, to.RegNum, 1);
|
||||
return to;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxPlusSign::FxPlusSign(FxExpression *operand)
|
||||
: FxExpression(operand->ScriptPosition)
|
||||
{
|
||||
|
@ -742,7 +819,6 @@ FxExpression *FxUnaryNotBoolean::Resolve(FCompileContext& ctx)
|
|||
{
|
||||
CHECKRESOLVED();
|
||||
if (Operand)
|
||||
|
||||
{
|
||||
Operand = Operand->ResolveAsBoolean(ctx);
|
||||
}
|
||||
|
@ -3064,28 +3140,6 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
|
|||
return dest;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpEmit FxTailable::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
return Emit(build, false);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
VMFunction *FxTailable::GetDirectFunction()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxVMFunctionCall
|
||||
|
@ -3093,7 +3147,7 @@ VMFunction *FxTailable::GetDirectFunction()
|
|||
//==========================================================================
|
||||
|
||||
FxVMFunctionCall::FxVMFunctionCall(PFunction *func, FArgumentList *args, const FScriptPosition &pos)
|
||||
: FxTailable(pos)
|
||||
: FxExpression(pos)
|
||||
{
|
||||
Function = func;
|
||||
ArgList = args;
|
||||
|
@ -3134,19 +3188,15 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
|
|||
delete this;
|
||||
return NULL;
|
||||
}
|
||||
TArray<PType *> &rets = Function->Variants[0].Proto->ReturnTypes;
|
||||
if (rets.Size() == 0)
|
||||
TArray<PType *> &rets = Function->Variants[0].Implementation->Proto->ReturnTypes;
|
||||
if (rets.Size() > 0)
|
||||
{
|
||||
ReturnType = TypeVoid;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReturnType = rets[0];
|
||||
// If more types are added to ParseNativeFunction(), add them here too.
|
||||
if (rets[0] == TypeSInt32) ValueType = VAL_Int;
|
||||
else if (rets[0] == TypeFloat64) ValueType = VAL_Float;
|
||||
else if (rets[0] == TypeAngle) ValueType = VAL_Angle;
|
||||
else if (rets[0] == TypeFixed) ValueType = VAL_Fixed;
|
||||
else if (rets[0] == TypeState) ValueType = VAL_State;
|
||||
else
|
||||
{
|
||||
ValueType = VAL_Int;
|
||||
|
@ -3164,6 +3214,11 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
return Emit(build, false);
|
||||
}
|
||||
|
||||
ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build, bool tailcall)
|
||||
{
|
||||
assert(build->Registers[REGT_POINTER].GetMostUsed() >= 3);
|
||||
|
@ -3190,17 +3245,17 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build, bool tailcall)
|
|||
}
|
||||
}
|
||||
// Get a constant register for this function
|
||||
int funcaddr = build->GetConstantAddress(Function->Variants[0].Implementation, ATAG_OBJECT);
|
||||
VMFunction *vmfunc = Function->Variants[0].Implementation;
|
||||
int funcaddr = build->GetConstantAddress(vmfunc, ATAG_OBJECT);
|
||||
// Emit the call
|
||||
if (tailcall)
|
||||
{ // Tail call
|
||||
build->Emit(OP_TAIL_K, funcaddr, count, 0);
|
||||
return ExpEmit();
|
||||
}
|
||||
else if (ReturnType != TypeVoid)
|
||||
else if (vmfunc->Proto->ReturnTypes.Size() > 0)
|
||||
{ // Call, expecting one result
|
||||
assert(ReturnType != NULL);
|
||||
ExpEmit reg(build, ReturnType->GetRegType());
|
||||
ExpEmit reg(build, vmfunc->Proto->ReturnTypes[0]->GetRegType());
|
||||
build->Emit(OP_CALL_K, funcaddr, count, 1);
|
||||
build->Emit(OP_RESULT, 0, reg.RegType, reg.RegNum);
|
||||
return reg;
|
||||
|
@ -3212,24 +3267,6 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build, bool tailcall)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxVMFunctionCall :: GetDirectFunction
|
||||
//
|
||||
// If the function is not passed any explicit arguments, returns the
|
||||
// function. Otherwise returns NULL.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
VMFunction *FxVMFunctionCall::GetDirectFunction()
|
||||
{
|
||||
if (GetArgCount() == 0)
|
||||
{
|
||||
return GetVMFunction();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -3330,7 +3367,7 @@ FxExpression *FxSequence::Resolve(FCompileContext &ctx)
|
|||
CHECKRESOLVED();
|
||||
for (unsigned i = 0; i < Expressions.Size(); ++i)
|
||||
{
|
||||
if (NULL == (Expressions[i] = static_cast<FxTailable *>(Expressions[i]->Resolve(ctx))))
|
||||
if (NULL == (Expressions[i] = Expressions[i]->Resolve(ctx)))
|
||||
{
|
||||
delete this;
|
||||
return NULL;
|
||||
|
@ -3345,11 +3382,11 @@ FxExpression *FxSequence::Resolve(FCompileContext &ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpEmit FxSequence::Emit(VMFunctionBuilder *build, bool tailcall)
|
||||
ExpEmit FxSequence::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
for (unsigned i = 0; i < Expressions.Size(); ++i)
|
||||
{
|
||||
ExpEmit v = Expressions[i]->Emit(build, tailcall ? i == Expressions.Size()-1 : false);
|
||||
ExpEmit v = Expressions[i]->Emit(build);
|
||||
// Throw away any result. We don't care about it.
|
||||
v.Free(build);
|
||||
}
|
||||
|
@ -3377,9 +3414,9 @@ VMFunction *FxSequence::GetDirectFunction()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FxIfStatement::FxIfStatement(FxExpression *cond, FxTailable *true_part,
|
||||
FxTailable *false_part, const FScriptPosition &pos)
|
||||
: FxTailable(pos)
|
||||
FxIfStatement::FxIfStatement(FxExpression *cond, FxExpression *true_part,
|
||||
FxExpression *false_part, const FScriptPosition &pos)
|
||||
: FxExpression(pos)
|
||||
{
|
||||
Condition = cond;
|
||||
WhenTrue = true_part;
|
||||
|
@ -3406,12 +3443,12 @@ FxExpression *FxIfStatement::Resolve(FCompileContext &ctx)
|
|||
ABORT(Condition);
|
||||
if (WhenTrue != NULL)
|
||||
{
|
||||
WhenTrue = static_cast<FxTailable *>(WhenTrue->Resolve(ctx));
|
||||
WhenTrue = WhenTrue->Resolve(ctx);
|
||||
ABORT(WhenTrue);
|
||||
}
|
||||
if (WhenFalse != NULL)
|
||||
{
|
||||
WhenFalse = static_cast<FxTailable *>(WhenFalse->Resolve(ctx));
|
||||
WhenFalse = WhenFalse->Resolve(ctx);
|
||||
ABORT(WhenFalse);
|
||||
}
|
||||
ValueType = VAL_Unknown;
|
||||
|
@ -3421,7 +3458,7 @@ FxExpression *FxIfStatement::Resolve(FCompileContext &ctx)
|
|||
ExpVal condval = static_cast<FxConstant *>(Condition)->GetValue();
|
||||
bool result = condval.GetBool();
|
||||
|
||||
FxTailable *e = result ? WhenTrue : WhenFalse;
|
||||
FxExpression *e = result ? WhenTrue : WhenFalse;
|
||||
delete (result ? WhenFalse : WhenTrue);
|
||||
WhenTrue = WhenFalse = NULL;
|
||||
delete this;
|
||||
|
@ -3430,11 +3467,11 @@ FxExpression *FxIfStatement::Resolve(FCompileContext &ctx)
|
|||
return this;
|
||||
}
|
||||
|
||||
ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build, bool tailcall)
|
||||
ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
ExpEmit v;
|
||||
size_t jumpspot;
|
||||
FxTailable *path1, *path2;
|
||||
FxExpression *path1, *path2;
|
||||
int condcheck;
|
||||
|
||||
// This is pretty much copied from FxConditional, except we don't
|
||||
|
@ -3464,24 +3501,18 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build, bool tailcall)
|
|||
cond.Free(build);
|
||||
|
||||
// Evaluate first path
|
||||
v = path1->Emit(build, tailcall);
|
||||
v = path1->Emit(build);
|
||||
v.Free(build);
|
||||
if (path2 != NULL)
|
||||
{
|
||||
size_t path1jump = build->Emit(OP_JMP, 0);
|
||||
// Evaluate second path
|
||||
build->BackpatchToHere(jumpspot);
|
||||
v = path2->Emit(build, tailcall);
|
||||
v = path2->Emit(build);
|
||||
v.Free(build);
|
||||
jumpspot = path1jump;
|
||||
}
|
||||
build->BackpatchToHere(jumpspot);
|
||||
if (tailcall)
|
||||
{
|
||||
// When tailcall is true, execution is not expected to get past
|
||||
// this if statement, so issue a RET.
|
||||
build->Emit(OP_RET, RET_FINAL, REGT_NIL, 0);
|
||||
}
|
||||
return ExpEmit();
|
||||
}
|
||||
|
||||
|
@ -3489,17 +3520,51 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build, bool tailcall)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FxReturnStatement::FxReturnStatement(const FScriptPosition &pos)
|
||||
: FxTailable(pos)
|
||||
FxReturnStatement::FxReturnStatement(FxVMFunctionCall *call, const FScriptPosition &pos)
|
||||
: FxExpression(pos), Call(call)
|
||||
{
|
||||
}
|
||||
|
||||
ExpEmit FxReturnStatement::Emit(VMFunctionBuilder *build, bool tailcall)
|
||||
FxExpression *FxReturnStatement::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
if (Call != NULL)
|
||||
{
|
||||
Call = static_cast<FxVMFunctionCall *>(Call->Resolve(ctx));
|
||||
ABORT(Call);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
ExpEmit FxReturnStatement::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
// If we return nothing, use a regular RET opcode. If we return
|
||||
// something, use TAIL to call the function. Our return type
|
||||
// should be compatible with the called function's return type.
|
||||
if (Call == NULL)
|
||||
{
|
||||
build->Emit(OP_RET, RET_FINAL, REGT_NIL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Call->Emit(build, true);
|
||||
}
|
||||
return ExpEmit();
|
||||
}
|
||||
|
||||
VMFunction *FxReturnStatement::GetDirectFunction()
|
||||
{
|
||||
// If this return statement calls a function with no arguments,
|
||||
// then it can be a "direct" function. That is, the DECORATE
|
||||
// definition can call that function directly without wrapping
|
||||
// it inside VM code.
|
||||
if (Call != NULL && Call->GetArgCount() == 0)
|
||||
{
|
||||
return Call->GetVMFunction();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
|
|
|
@ -375,6 +375,42 @@ static void ParseArgListDef(FScanner &sc, PClassActor *cls,
|
|||
sc.MustGetToken(';');
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SetImplicitArgs
|
||||
//
|
||||
// Adds the parameters implied by the function flags.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, PClassActor *cls, DWORD funcflags)
|
||||
{
|
||||
// Must be called before adding any other arguments.
|
||||
assert(args == NULL || args->Size() == 0);
|
||||
assert(argflags == NULL || argflags->Size() == 0);
|
||||
|
||||
if (funcflags & VARF_Method)
|
||||
{
|
||||
// implied self pointer
|
||||
if (args != NULL) args->Push(NewClassPointer(cls));
|
||||
if (argflags != NULL) argflags->Push(0);
|
||||
}
|
||||
if (funcflags & VARF_Action)
|
||||
{
|
||||
// implied stateowner and callingstate pointers
|
||||
if (args != NULL)
|
||||
{
|
||||
args->Push(NewClassPointer(RUNTIME_CLASS(AActor)));
|
||||
args->Push(TypeState);
|
||||
}
|
||||
if (argflags != NULL)
|
||||
{
|
||||
argflags->Push(0);
|
||||
argflags->Push(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ParseFunctionDef
|
||||
|
@ -401,15 +437,7 @@ void ParseFunctionDef(FScanner &sc, PClassActor *cls, FName funcname,
|
|||
}
|
||||
sc.MustGetToken('(');
|
||||
|
||||
if (funcflags & VARF_Method)
|
||||
{
|
||||
args.Push(NewClassPointer(cls)), argflags.Push(0); // implied self pointer
|
||||
}
|
||||
if (funcflags & VARF_Action)
|
||||
{
|
||||
args.Push(NewClassPointer(RUNTIME_CLASS(AActor))), argflags.Push(0); // implied stateowner pointer
|
||||
args.Push(TypeState), argflags.Push(0); // implied callingstate pointer
|
||||
}
|
||||
SetImplicitArgs(&args, &argflags, cls, funcflags);
|
||||
ParseArgListDef(sc, cls, args, argflags);
|
||||
|
||||
if (afd != NULL)
|
||||
|
@ -466,6 +494,10 @@ static void ParseNativeFunction(FScanner &sc, PClassActor *cls)
|
|||
rets.Push(TypeFixed);
|
||||
break;
|
||||
|
||||
case TK_State:
|
||||
rets.Push(TypeState);
|
||||
break;
|
||||
|
||||
case TK_Identifier:
|
||||
rets.Push(NewPointer(RUNTIME_CLASS(DObject)));
|
||||
// Todo: Object type
|
||||
|
@ -1036,10 +1068,22 @@ static void ParseActionDef (FScanner &sc, PClassActor *cls)
|
|||
|
||||
sc.MustGetToken(TK_Native);
|
||||
// check for a return value
|
||||
do
|
||||
{
|
||||
if (sc.CheckToken(TK_Int) || sc.CheckToken(TK_Bool))
|
||||
{
|
||||
rets.Push(TypeSInt32);
|
||||
}
|
||||
else if (sc.CheckToken(TK_State))
|
||||
{
|
||||
rets.Push(TypeState);
|
||||
}
|
||||
else if (sc.CheckToken(TK_Float))
|
||||
{
|
||||
rets.Push(TypeFloat64);
|
||||
}
|
||||
}
|
||||
while (sc.CheckToken(','));
|
||||
sc.MustGetToken(TK_Identifier);
|
||||
funcname = sc.String;
|
||||
ParseFunctionDef(sc, cls, funcname, rets, VARF_Method | VARF_Action);
|
||||
|
|
|
@ -314,7 +314,12 @@ do_stop:
|
|||
continue;
|
||||
}
|
||||
|
||||
tcall->Code = ParseActions(sc, state, statestring, bag);
|
||||
bool hasfinalret;
|
||||
tcall->Code = ParseActions(sc, state, statestring, bag, tcall->Proto, hasfinalret);
|
||||
if (!hasfinalret)
|
||||
{
|
||||
AddImplicitReturn(static_cast<FxSequence*>(tcall->Code), tcall->Proto, sc);
|
||||
}
|
||||
goto endofstate;
|
||||
}
|
||||
sc.UnGet();
|
||||
|
@ -348,49 +353,162 @@ endofstate:
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// ParseActions
|
||||
// AddImplicitReturn
|
||||
//
|
||||
// Adds an implied return; statement to the end of a code sequence.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxTailable *ParseActions(FScanner &sc, FState state, FString statestring, Baggage &bag)
|
||||
void AddImplicitReturn(FxSequence *code, const PPrototype *proto, FScanner &sc)
|
||||
{
|
||||
if (proto == NULL || proto->ReturnTypes.Size() == 0)
|
||||
{ // Returns nothing. Good. We can safely add an implied return.
|
||||
code->Add(new FxReturnStatement(NULL, sc));
|
||||
}
|
||||
else
|
||||
{ // Something was returned earlier in the sequence. Make it an error
|
||||
// instead of adding an implicit one.
|
||||
sc.ScriptError("Action list must end with a return statement");
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ReturnCheck
|
||||
//
|
||||
// If proto1 is NULL, returns proto2. If proto2 is NULL, returns proto1.
|
||||
// If neither is null, checks if both prototypes define the same return
|
||||
// types. If not, an error is flagged.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static PPrototype *ReturnCheck(PPrototype *proto1, PPrototype *proto2, FScanner &sc)
|
||||
{
|
||||
if (proto1 == NULL)
|
||||
{
|
||||
return proto2;
|
||||
}
|
||||
if (proto2 == NULL)
|
||||
{
|
||||
return proto1;
|
||||
}
|
||||
// A prototype that defines fewer return types can be compatible with
|
||||
// one that defines more if the shorter one matches the initial types
|
||||
// for the longer one.
|
||||
if (proto2->ReturnTypes.Size() < proto1->ReturnTypes.Size())
|
||||
{ // Make proto1 the shorter one to avoid code duplication below.
|
||||
swapvalues(proto1, proto2);
|
||||
}
|
||||
// If one prototype returns nothing, they both must.
|
||||
if (proto1->ReturnTypes.Size() == 0)
|
||||
{
|
||||
if (proto2->ReturnTypes.Size() == 0)
|
||||
{
|
||||
return proto1;
|
||||
}
|
||||
proto1 = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned i = 0; i < proto1->ReturnTypes.Size(); ++i)
|
||||
{
|
||||
if (proto1->ReturnTypes[i] != proto2->ReturnTypes[i])
|
||||
{ // Incompatible
|
||||
proto1 = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (proto1 == NULL)
|
||||
{
|
||||
sc.ScriptError("Return types are incompatible");
|
||||
}
|
||||
return proto1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ParseActions
|
||||
//
|
||||
// If this action block contains any return statements, the prototype for
|
||||
// one of them will be returned. This is used for deducing the return type
|
||||
// of anonymous functions. All called functions passed to return must have
|
||||
// matching return types.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Baggage &bag,
|
||||
PPrototype *&retproto, bool &endswithret)
|
||||
{
|
||||
// If it's not a '{', then it should be a single action.
|
||||
// Otherwise, it's a sequence of actions.
|
||||
if (!sc.Compare("{"))
|
||||
{
|
||||
return ParseAction(sc, state, statestring, bag);
|
||||
FxVMFunctionCall *call = ParseAction(sc, state, statestring, bag);
|
||||
retproto = call->GetVMFunction()->Proto;
|
||||
endswithret = true;
|
||||
return new FxReturnStatement(call, sc);
|
||||
}
|
||||
|
||||
const FScriptPosition pos(sc);
|
||||
|
||||
FxSequence *seq = NULL;
|
||||
PPrototype *proto = NULL;
|
||||
bool lastwasret = false;
|
||||
|
||||
sc.MustGetString();
|
||||
while (!sc.Compare("}"))
|
||||
{
|
||||
FxTailable *add;
|
||||
FxExpression *add;
|
||||
lastwasret = false;
|
||||
if (sc.Compare("if"))
|
||||
{ // Hangle an if statement
|
||||
FxExpression *cond;
|
||||
FxTailable *true_part, *false_part = NULL;
|
||||
FxExpression *true_part, *false_part = NULL;
|
||||
PPrototype *true_proto, *false_proto = NULL;
|
||||
bool true_ret, false_ret = false;
|
||||
sc.MustGetStringName("(");
|
||||
cond = ParseExpression(sc, bag.Info);
|
||||
sc.MustGetStringName(")");
|
||||
sc.MustGetStringName("{"); // braces are mandatory
|
||||
true_part = ParseActions(sc, state, statestring, bag);
|
||||
true_part = ParseActions(sc, state, statestring, bag, true_proto, true_ret);
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("else"))
|
||||
{
|
||||
sc.MustGetStringName("{"); // braces are still mandatory
|
||||
false_part = ParseActions(sc, state, statestring, bag);
|
||||
false_part = ParseActions(sc, state, statestring, bag, false_proto, false_ret);
|
||||
sc.MustGetString();
|
||||
}
|
||||
add = new FxIfStatement(cond, true_part, false_part, sc);
|
||||
proto = ReturnCheck(proto, true_proto, sc);
|
||||
proto = ReturnCheck(proto, false_proto, sc);
|
||||
// If one side does not end with a return, we don't consider the if statement
|
||||
// to end with a return.
|
||||
if (true_ret && (false_proto == NULL || false_ret))
|
||||
{
|
||||
lastwasret = true;
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("return"))
|
||||
{ // Handle a return statement
|
||||
sc.MustGetStringName(";");
|
||||
lastwasret = true;
|
||||
FxVMFunctionCall *retexp = NULL;
|
||||
PPrototype *retproto;
|
||||
sc.MustGetString();
|
||||
add = new FxReturnStatement(sc);
|
||||
if (!sc.Compare(";"))
|
||||
{
|
||||
retexp = ParseAction(sc, state, statestring, bag);
|
||||
sc.MustGetStringName(";");
|
||||
retproto = retexp->GetVMFunction()->Proto;
|
||||
}
|
||||
else
|
||||
{ // Returning nothing; we still need a prototype for that.
|
||||
TArray<PType *> notypes(0);
|
||||
retproto = NewPrototype(notypes, notypes);
|
||||
}
|
||||
proto = ReturnCheck(proto, retproto, sc);
|
||||
sc.MustGetString();
|
||||
add = new FxReturnStatement(retexp, sc);
|
||||
}
|
||||
else
|
||||
{ // Handle a regular action function call
|
||||
|
@ -408,6 +526,8 @@ FxTailable *ParseActions(FScanner &sc, FState state, FString statestring, Baggag
|
|||
seq->Add(add);
|
||||
}
|
||||
}
|
||||
endswithret = lastwasret;
|
||||
retproto = proto;
|
||||
return seq;
|
||||
}
|
||||
|
||||
|
@ -460,7 +580,7 @@ FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, B
|
|||
void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray<FxExpression *> &out_params,
|
||||
PFunction *afd, FString statestring, FStateDefinitions *statedef)
|
||||
{
|
||||
const TArray<PType *> ¶ms = afd->Variants[0].Proto->ArgumentTypes;
|
||||
const TArray<PType *> ¶ms = afd->Variants[0].Implementation->Proto->ArgumentTypes;
|
||||
const TArray<DWORD> ¶mflags = afd->Variants[0].ArgFlags;
|
||||
int numparams = (int)params.Size();
|
||||
int pnum = 0;
|
||||
|
|
|
@ -158,12 +158,15 @@ enum
|
|||
class VMFunction : public DObject
|
||||
{
|
||||
DECLARE_ABSTRACT_CLASS(VMFunction, DObject);
|
||||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
bool Native;
|
||||
FName Name;
|
||||
|
||||
VMFunction() : Native(false), Name(NAME_None) {}
|
||||
VMFunction(FName name) : Native(false), Name(name) {}
|
||||
class PPrototype *Proto;
|
||||
|
||||
VMFunction() : Native(false), Name(NAME_None), Proto(NULL) {}
|
||||
VMFunction(FName name) : Native(false), Name(name), Proto(NULL) {}
|
||||
};
|
||||
|
||||
enum EVMOpMode
|
||||
|
|
|
@ -551,7 +551,7 @@ begin:
|
|||
}
|
||||
stack->PopFrame();
|
||||
}
|
||||
assert(numret == C);
|
||||
assert(numret == C && "Number of parameters returned differs from what was expected by the caller");
|
||||
for (b = B; b != 0; --b)
|
||||
{
|
||||
reg.param[--f->NumParam].~VMValue();
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
#include "vm.h"
|
||||
|
||||
IMPLEMENT_CLASS(VMException)
|
||||
IMPLEMENT_ABSTRACT_CLASS(VMFunction)
|
||||
IMPLEMENT_ABSTRACT_POINTY_CLASS(VMFunction)
|
||||
DECLARE_POINTER(Proto)
|
||||
END_POINTERS
|
||||
IMPLEMENT_CLASS(VMScriptFunction)
|
||||
IMPLEMENT_CLASS(VMNativeFunction)
|
||||
|
||||
|
|
|
@ -43,10 +43,14 @@ ACTOR Actor native //: Thinker
|
|||
native int CountInv(class<Inventory> itemtype, int ptr_select = AAPTR_DEFAULT);
|
||||
native float GetDistance(bool checkz, int ptr = AAPTR_DEFAULT);
|
||||
|
||||
native state A_State(state returnme);
|
||||
native int A_Int(int returnme);
|
||||
native bool A_Bool(bool returnme);
|
||||
|
||||
// Action functions
|
||||
// Meh, MBF redundant functions. Only for DeHackEd support.
|
||||
action native A_Turn(float angle = 0);
|
||||
action native A_LineEffect(int boomspecial = 0, int tag = 0);
|
||||
action native bool A_LineEffect(int boomspecial = 0, int tag = 0);
|
||||
// End of MBF redundant functions.
|
||||
|
||||
action native A_MonsterRail();
|
||||
|
@ -108,7 +112,7 @@ ACTOR Actor native //: Thinker
|
|||
action native A_Die(name damagetype = "none");
|
||||
action native A_Detonate();
|
||||
action native A_Mushroom(class<Actor> spawntype = "FatShot", int numspawns = 0, int flags = 0, float vrange = 4.0, float hrange = 0.5);
|
||||
action native A_CallSpecial(int special, int arg1=0, int arg2=0, int arg3=0, int arg4=0, int arg5=0);
|
||||
action native bool A_CallSpecial(int special, int arg1=0, int arg2=0, int arg3=0, int arg4=0, int arg5=0);
|
||||
|
||||
action native A_SetFloorClip();
|
||||
action native A_UnSetFloorClip();
|
||||
|
@ -181,22 +185,22 @@ ACTOR Actor native //: Thinker
|
|||
action native A_PlaySoundEx(sound whattoplay, coerce name slot, bool looping = false, int attenuation = 0);
|
||||
action native A_StopSoundEx(coerce name slot);
|
||||
action native A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10);
|
||||
action native A_Jump(int chance = 256, state label, ...);
|
||||
action native state A_Jump(int chance = 256, state label, ...);
|
||||
action native A_CustomMissile(class<Actor> missiletype, float spawnheight = 32, int spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0, int ptr = AAPTR_TARGET);
|
||||
action native A_CustomBulletAttack(float/*angle*/ spread_xy, float/*angle*/ spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET);
|
||||
action native A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, int aim = 0, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float/*angle*/ spread_xy = 0, float/*angle*/ spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270);
|
||||
action native A_JumpIfHealthLower(int health, state label, int ptr_selector = AAPTR_DEFAULT);
|
||||
action native A_JumpIfCloser(float distance, state label, bool noz = false);
|
||||
action native A_JumpIfTracerCloser(float distance, state label, bool noz = false);
|
||||
action native A_JumpIfMasterCloser(float distance, state label, bool noz = false);
|
||||
action native A_JumpIfTargetOutsideMeleeRange(state label);
|
||||
action native A_JumpIfTargetInsideMeleeRange(state label);
|
||||
action native A_JumpIfInventory(class<Inventory> itemtype, int itemamount, state label, int owner = AAPTR_DEFAULT);
|
||||
action native A_JumpIfArmorType(name Type, state label, int amount = 1);
|
||||
action native A_GiveInventory(class<Inventory> itemtype, int amount = 0, int giveto = AAPTR_DEFAULT);
|
||||
action native A_TakeInventory(class<Inventory> itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT);
|
||||
action native A_SpawnItem(class<Actor> itemtype = "Unknown", float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false);
|
||||
action native A_SpawnItemEx(class<Actor> 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);
|
||||
action native state A_JumpIfHealthLower(int health, state label, int ptr_selector = AAPTR_DEFAULT);
|
||||
action native state A_JumpIfCloser(float distance, state label, bool noz = false);
|
||||
action native state A_JumpIfTracerCloser(float distance, state label, bool noz = false);
|
||||
action native state A_JumpIfMasterCloser(float distance, state label, bool noz = false);
|
||||
action native state A_JumpIfTargetOutsideMeleeRange(state label);
|
||||
action native state A_JumpIfTargetInsideMeleeRange(state label);
|
||||
action native state A_JumpIfInventory(class<Inventory> itemtype, int itemamount, state label, int owner = AAPTR_DEFAULT);
|
||||
action native state A_JumpIfArmorType(name Type, state label, int amount = 1);
|
||||
action native bool A_GiveInventory(class<Inventory> itemtype, int amount = 0, int giveto = AAPTR_DEFAULT);
|
||||
action native bool A_TakeInventory(class<Inventory> itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT);
|
||||
action native bool A_SpawnItem(class<Actor> itemtype = "Unknown", float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false);
|
||||
action native bool A_SpawnItemEx(class<Actor> 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);
|
||||
action native A_Print(string whattoprint, float time = 0, name fontname = "");
|
||||
action native A_PrintBold(string whattoprint, float time = 0, name fontname = "");
|
||||
action native A_Log(string whattoprint);
|
||||
|
@ -209,31 +213,31 @@ ACTOR Actor native //: Thinker
|
|||
action native A_SetMass(int mass);
|
||||
action native A_SpawnDebris(class<Actor> spawntype, bool transfer_translation = false, float mult_h = 1, float mult_v = 1);
|
||||
action native A_SpawnParticle(color color1, int flags = 0, int lifetime = 35, int size = 1, float angle = 0, float xoff = 0, float yoff = 0, float zoff = 0, float velx = 0, float vely = 0, float velz = 0, float accelx = 0, float accely = 0, float accelz = 0, float startalphaf = 1, float fadestepf = -1);
|
||||
action native A_CheckSight(state label);
|
||||
action native state A_CheckSight(state label);
|
||||
action native A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false);
|
||||
action native A_DropInventory(class<Inventory> itemtype);
|
||||
action native A_SetBlend(color color1, float alpha, int tics, color color2 = "");
|
||||
action native A_ChangeFlag(string flagname, bool value);
|
||||
action native A_CheckFlag(string flagname, state label, int check_pointer = AAPTR_DEFAULT);
|
||||
action native A_JumpIf(bool expression, state label);
|
||||
action native state A_CheckFlag(string flagname, state label, int check_pointer = AAPTR_DEFAULT);
|
||||
action native state A_JumpIf(bool expression, state label);
|
||||
action native A_RaiseMaster(bool copy = 0);
|
||||
action native A_RaiseChildren(bool copy = 0);
|
||||
action native A_RaiseSiblings(bool copy = 0);
|
||||
action native A_CheckFloor(state label);
|
||||
action native A_CheckCeiling(state label);
|
||||
action native A_PlayerSkinCheck(state label);
|
||||
action native state A_CheckFloor(state label);
|
||||
action native state A_CheckCeiling(state label);
|
||||
action native state A_PlayerSkinCheck(state label);
|
||||
action native A_BasicAttack(int meleedamage, sound meleesound, class<actor> missiletype, float missileheight);
|
||||
action native A_Teleport(state teleportstate = "", class<SpecialSpot> targettype = "BossSpot", class<Actor> fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0, int ptr = AAPTR_DEFAULT);
|
||||
action native 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);
|
||||
action native A_ThrowGrenade(class<Actor> itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true);
|
||||
action native state, bool A_Teleport(state teleportstate = "", class<SpecialSpot> targettype = "BossSpot", class<Actor> fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0, int ptr = AAPTR_DEFAULT);
|
||||
action 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);
|
||||
action native bool A_ThrowGrenade(class<Actor> itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true);
|
||||
action native A_Weave(int xspeed, int yspeed, float xdist, float ydist);
|
||||
|
||||
action native A_Recoil(float xyvel);
|
||||
action native A_JumpIfInTargetInventory(class<Inventory> itemtype, int amount, state label, int forward_ptr = AAPTR_DEFAULT);
|
||||
action native A_GiveToTarget(class<Inventory> itemtype, int amount = 0, int forward_ptr = AAPTR_DEFAULT);
|
||||
action native A_TakeFromTarget(class<Inventory> itemtype, int amount = 0, int flags = 0, int forward_ptr = AAPTR_DEFAULT);
|
||||
action native A_RadiusGive(class<Inventory> itemtype, float distance, int flags, int amount = 0, class<Actor> filter = "None", name species = "None", int mindist = 0);
|
||||
action native A_CheckSpecies(state jump, name species = "", int ptr = AAPTR_DEFAULT);
|
||||
action native state A_JumpIfInTargetInventory(class<Inventory> itemtype, int amount, state label, int forward_ptr = AAPTR_DEFAULT);
|
||||
action native bool A_GiveToTarget(class<Inventory> itemtype, int amount = 0, int forward_ptr = AAPTR_DEFAULT);
|
||||
action native bool A_TakeFromTarget(class<Inventory> itemtype, int amount = 0, int flags = 0, int forward_ptr = AAPTR_DEFAULT);
|
||||
action native int A_RadiusGive(class<Inventory> itemtype, float distance, int flags, int amount = 0, class<Actor> filter = "None", name species = "None", int mindist = 0);
|
||||
action native state A_CheckSpecies(state jump, name species = "", int ptr = AAPTR_DEFAULT);
|
||||
action native A_CountdownArg(int argnum, state targstate = "");
|
||||
action native A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true);
|
||||
action native A_CustomComboAttack(class<Actor> missiletype, float spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true);
|
||||
|
@ -249,10 +253,10 @@ ACTOR Actor native //: Thinker
|
|||
action native A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = "");
|
||||
action native A_ClearLastHeard();
|
||||
action native A_ClearTarget();
|
||||
action native 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);
|
||||
action native A_JumpIfTargetInLOS (state label, float/*angle*/ fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0);
|
||||
action native A_JumpIfInTargetLOS (state label, float/*angle*/ fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0);
|
||||
action native A_SelectWeapon(class<Weapon> whichweapon);
|
||||
action 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);
|
||||
action native state A_JumpIfTargetInLOS (state label, float/*angle*/ fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0);
|
||||
action native state A_JumpIfInTargetLOS (state label, float/*angle*/ fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0);
|
||||
action native bool A_SelectWeapon(class<Weapon> whichweapon);
|
||||
action native A_Punch();
|
||||
action native A_Feathers();
|
||||
action native A_ClassBossHealth();
|
||||
|
@ -264,7 +268,7 @@ ACTOR Actor native //: Thinker
|
|||
action native A_RemoveForcefield();
|
||||
action native A_DropWeaponPieces(class<Actor> p1, class<Actor> p2, class<Actor> p3);
|
||||
action native A_PigPain ();
|
||||
action native A_MonsterRefire(int chance, state label);
|
||||
action native state A_MonsterRefire(int chance, state label);
|
||||
action native A_SetAngle(float angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT);
|
||||
action native A_SetPitch(float pitch, int flags = 0, int ptr = AAPTR_DEFAULT);
|
||||
action native A_SetRoll(float/*angle*/ roll, int flags = 0, int ptr = AAPTR_DEFAULT);
|
||||
|
@ -299,37 +303,37 @@ ACTOR Actor native //: Thinker
|
|||
action native A_RemoveChildren(bool removeall = false, int flags = 0, class<Actor> filter = "None", name species = "None");
|
||||
action native A_RemoveSiblings(bool removeall = false, int flags = 0, class<Actor> filter = "None", name species = "None");
|
||||
action native A_Remove(int removee, int flags = 0, class<Actor> filter = "None", name species = "None");
|
||||
action native A_GiveToChildren(class<Inventory> itemtype, int amount = 0);
|
||||
action native A_GiveToSiblings(class<Inventory> itemtype, int amount = 0);
|
||||
action native A_TakeFromChildren(class<Inventory> itemtype, int amount = 0);
|
||||
action native A_TakeFromSiblings(class<Inventory> itemtype, int amount = 0);
|
||||
action native int A_GiveToChildren(class<Inventory> itemtype, int amount = 0);
|
||||
action native int A_GiveToSiblings(class<Inventory> itemtype, int amount = 0);
|
||||
action native int A_TakeFromChildren(class<Inventory> itemtype, int amount = 0);
|
||||
action native int A_TakeFromSiblings(class<Inventory> itemtype, int amount = 0);
|
||||
action native A_SetTeleFog(class<Actor> oldpos, class<Actor> newpos);
|
||||
action native A_SwapTeleFog();
|
||||
action native A_SetFloatBobPhase(int bob);
|
||||
action native A_SetHealth(int health, int ptr = AAPTR_DEFAULT);
|
||||
action native A_ResetHealth(int ptr = AAPTR_DEFAULT);
|
||||
action native A_JumpIfHigherOrLower(state high, state low, float offsethigh = 0, float offsetlow = 0, bool includeHeight = true, int ptr = AAPTR_TARGET);
|
||||
action native state A_JumpIfHigherOrLower(state high, state low, float offsethigh = 0, float offsetlow = 0, bool includeHeight = true, int ptr = AAPTR_TARGET);
|
||||
action native A_SetSpecies(name species, int ptr = AAPTR_DEFAULT);
|
||||
action native A_SetRipperLevel(int level);
|
||||
action native A_SetRipMin(int min);
|
||||
action native A_SetRipMax(int max);
|
||||
action native A_SetChaseThreshold(int threshold, bool def = false, int ptr = AAPTR_DEFAULT);
|
||||
action native A_CheckProximity(state jump, class<Actor> classname, float distance, int count = 1, int flags = 0, int ptr = AAPTR_DEFAULT);
|
||||
action native A_CheckBlock(state block, int flags = 0, int ptr = AAPTR_DEFAULT);
|
||||
action native A_CheckSightOrRange(float distance, state label, bool two_dimension = false);
|
||||
action native A_CheckRange(float distance, state label, bool two_dimension = false);
|
||||
action native A_FaceMovementDirection(float offset = 0, float anglelimit = 0, float pitchlimit = 0, int flags = 0, int ptr = AAPTR_DEFAULT);
|
||||
action native state A_CheckProximity(state jump, class<Actor> classname, float distance, int count = 1, int flags = 0, int ptr = AAPTR_DEFAULT);
|
||||
action native state A_CheckBlock(state block, int flags = 0, int ptr = AAPTR_DEFAULT);
|
||||
action native state A_CheckSightOrRange(float distance, state label, bool two_dimension = false);
|
||||
action native state A_CheckRange(float distance, state label, bool two_dimension = false);
|
||||
action native bool A_FaceMovementDirection(float offset = 0, float anglelimit = 0, float pitchlimit = 0, int flags = 0, int ptr = AAPTR_DEFAULT);
|
||||
|
||||
action native A_RearrangePointers(int newtarget, int newmaster = AAPTR_DEFAULT, int newtracer = AAPTR_DEFAULT, int flags=0);
|
||||
action native A_TransferPointer(int ptr_source, int ptr_recepient, int sourcefield, int recepientfield=AAPTR_DEFAULT, int flags=0);
|
||||
action native A_CopyFriendliness(int ptr_source = AAPTR_MASTER);
|
||||
|
||||
action native ACS_NamedExecute(name script, int mapnum=0, int arg1=0, int arg2=0, int arg3=0);
|
||||
action native ACS_NamedSuspend(name script, int mapnum=0);
|
||||
action native ACS_NamedTerminate(name script, int mapnum=0);
|
||||
action native ACS_NamedLockedExecute(name script, int mapnum=0, int arg1=0, int arg2=0, int lock=0);
|
||||
action native ACS_NamedLockedExecuteDoor(name script, int mapnum=0, int arg1=0, int arg2=0, int lock=0);
|
||||
action native ACS_NamedExecuteWithResult(name script, int arg1=0, int arg2=0, int arg3=0, int arg4=0);
|
||||
action native int ACS_NamedExecute(name script, int mapnum=0, int arg1=0, int arg2=0, int arg3=0);
|
||||
action native int ACS_NamedSuspend(name script, int mapnum=0);
|
||||
action native int ACS_NamedTerminate(name script, int mapnum=0);
|
||||
action native int ACS_NamedLockedExecute(name script, int mapnum=0, int arg1=0, int arg2=0, int lock=0);
|
||||
action native int ACS_NamedLockedExecuteDoor(name script, int mapnum=0, int arg1=0, int arg2=0, int lock=0);
|
||||
action native int ACS_NamedExecuteWithResult(name script, int arg1=0, int arg2=0, int arg3=0, int arg4=0);
|
||||
action native ACS_NamedExecuteAlways(name script, int mapnum=0, int arg1=0, int arg2=0, int arg3=0);
|
||||
|
||||
States
|
||||
|
|
|
@ -34,7 +34,7 @@ ACTOR Fatso
|
|||
FATT H 10 BRIGHT A_FatAttack2
|
||||
FATT IG 5 A_FaceTarget
|
||||
FATT H 10 BRIGHT A_FatAttack3
|
||||
FATT IG 5
|
||||
FATT IG 5 A_FaceTarget
|
||||
Goto See
|
||||
Pain:
|
||||
FATT J 3
|
||||
|
|
|
@ -29,8 +29,8 @@ ACTOR PainElemental
|
|||
Missile:
|
||||
PAIN D 5 A_FaceTarget
|
||||
PAIN E 5 A_FaceTarget
|
||||
PAIN F 4 BRIGHT A_FaceTarget
|
||||
PAIN F 1 BRIGHT A_PainAttack
|
||||
PAIN F 5 BRIGHT A_FaceTarget
|
||||
PAIN F 0 BRIGHT A_PainAttack
|
||||
Goto See
|
||||
Pain:
|
||||
PAIN G 6
|
||||
|
|
|
@ -31,7 +31,7 @@ ACTOR Revenant
|
|||
SKEL AABBCCDDEEFF 2 A_Chase
|
||||
Loop
|
||||
Melee:
|
||||
SKEL G 1 A_FaceTarget
|
||||
SKEL G 0 A_FaceTarget
|
||||
SKEL G 6 A_SkelWhoosh
|
||||
SKEL H 6 A_FaceTarget
|
||||
SKEL I 6 A_SkelFist
|
||||
|
|
|
@ -7,7 +7,7 @@ ACTOR Inventory native
|
|||
Inventory.PickupSound "misc/i_pkup"
|
||||
Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG"
|
||||
|
||||
action native A_JumpIfNoAmmo(state label);
|
||||
action native state A_JumpIfNoAmmo(state label);
|
||||
action native A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class<Actor> pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus", sound MeleeSound = "", sound MissSound = "");
|
||||
action native A_FireBullets(float/*angle*/ spread_xy, float/*angle*/ spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", int flags = 1, float range = 0);
|
||||
action native A_FireCustomMissile(class<Actor> missiletype, float angle = 0, bool useammo = true, int spawnofs_xy = 0, float spawnheight = 0, int flags = 0, float pitch = 0);
|
||||
|
@ -42,7 +42,7 @@ ACTOR Inventory native
|
|||
action native A_CheckReload();
|
||||
action native A_GunFlash(state flash = "", int flags = 0);
|
||||
action native A_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class<Actor> pufftype = "BulletPuff", int flags = 0, float range = 0, float/*angle*/ spread_xy = 2.8125, float/*angle*/ spread_z = 0, float lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus");
|
||||
action native A_CheckForReload(int counter, state label, bool dontincrement = false);
|
||||
action native state A_CheckForReload(int counter, state label, bool dontincrement = false);
|
||||
action native A_ResetReloadCounter();
|
||||
action native A_RestoreSpecialPosition();
|
||||
action native A_RestoreSpecialDoomThing();
|
||||
|
|
Loading…
Reference in a new issue